]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
frv.h: Clean up references to GO_IF_LEGITIMATE_ADDRESS.
[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,
66647d44 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
bd4dc3cd 4;; Free Software Foundation, Inc.
3a33f76f 5;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
7a0a1f09 6;; and Martin Simmons (@harleqn.co.uk).
b36ba79f 7;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
3a33f76f 8
4f448245 9;; This file is part of GCC.
3a33f76f 10
4f448245
NC
11;; GCC is free software; you can redistribute it and/or modify it
12;; under the terms of the GNU General Public License as published
2f83c7d6 13;; by the Free Software Foundation; either version 3, or (at your
4f448245 14;; option) any later version.
3a33f76f 15
4f448245
NC
16;; GCC is distributed in the hope that it will be useful, but WITHOUT
17;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19;; License for more details.
3a33f76f
RK
20
21;; You should have received a copy of the GNU General Public License
2f83c7d6
NC
22;; along with GCC; see the file COPYING3. If not see
23;; <http://www.gnu.org/licenses/>.
3a33f76f
RK
24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
ff9940b0 27\f
b15bca31
RE
28;;---------------------------------------------------------------------------
29;; Constants
30
31;; Register numbers
32(define_constants
9f7bf991
RE
33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
b15bca31
RE
35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
9f7bf991
RE
39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
b15bca31
RE
42 ]
43)
03f1640c
RE
44;; 3rd operand to select_dominance_cc_mode
45(define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50)
b15bca31 51
ff9940b0 52;; UNSPEC Usage:
f54fd62e 53;; Note: sin and cos are no-longer used.
88f77cba 54;; Unspec constants for Neon are defined in neon.md.
b15bca31
RE
55
56(define_constants
57 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
58 ; operand 0 is the result,
59 ; operand 1 the parameter.
60 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
61 ; operand 0 is the result,
62 ; operand 1 the parameter.
63 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
64 ; operand 0 is the first register,
65 ; subsequent registers are in parallel (use ...)
66 ; expressions.
67 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
68 ; usage, that is, we will add the pic_register
69 ; value to it before trying to dereference it.
f9bd1a89
RS
70 (UNSPEC_PIC_BASE 4) ; Add PC and all but the last operand together,
71 ; The last operand is the number of a PIC_LABEL
72 ; that points at the containing instruction.
228692e2 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.
97e38a92 96 (UNSPEC_STACK_ALIGN 22) ; Doubleword aligned stack pointer. Used to
5b3e6663 97 ; generate correct unwind information.
97e38a92 98 (UNSPEC_PIC_OFFSET 23) ; A symbolic 12-bit OFFSET that has been treated
9403b7f7 99 ; correctly for PIC usage.
f9bd1a89
RS
100 (UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
101 ; a given symbolic address.
b15bca31
RE
102 ]
103)
104
5895f793 105;; UNSPEC_VOLATILE Usage:
b15bca31
RE
106
107(define_constants
108 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
109 ; insn in the code.
110 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
111 ; instruction epilogue sequence that isn't expanded
112 ; into normal RTL. Used for both normal and sibcall
113 ; epilogues.
114 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
115 ; for inlined constants.
116 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
117 ; table.
118 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
119 ; an 8-bit object.
120 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
121 ; a 16-bit object.
122 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
123 ; a 32-bit object.
124 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
125 ; a 64-bit object.
88f77cba
JB
126 (VUNSPEC_POOL_16 8) ; `pool-entry(16)'. An entry in the constant pool for
127 ; a 128-bit object.
128 (VUNSPEC_TMRC 9) ; Used by the iWMMXt TMRC instruction.
129 (VUNSPEC_TMCR 10) ; Used by the iWMMXt TMCR instruction.
130 (VUNSPEC_ALIGN8 11) ; 8-byte alignment version of VUNSPEC_ALIGN
131 (VUNSPEC_WCMP_EQ 12) ; Used by the iWMMXt WCMPEQ instructions
132 (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
133 (VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions
c112cf2b 134 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
c9ca9b88 135 ; handling.
b15bca31
RE
136 ]
137)
3a33f76f 138\f
b15bca31 139;;---------------------------------------------------------------------------
ff9940b0
RE
140;; Attributes
141
5895f793
RE
142; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
143; generating ARM code. This is used to control the length of some insn
144; patterns that share the same RTL in both ARM and Thumb code.
0616531f 145(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
d5b7b3ae 146
5895f793
RE
147; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
148; scheduling decisions for the load unit and the multiplier.
abac3b49 149(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
ff9940b0 150
df8e2ad0
BE
151; IS_XSCALE is set to 'yes' when compiling for XScale.
152(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
153
d19fb8e3
NC
154;; Operand number of an input operand that is shifted. Zero if the
155;; given instruction does not shift one of its input operands.
d19fb8e3
NC
156(define_attr "shift" "" (const_int 0))
157
dfaa6d72
RE
158; Floating Point Unit. If we only have floating point emulation, then there
159; is no point in scheduling the floating point insns. (Well, for best
160; performance we should try and group them together).
51c69ddb 161(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp,vfpv3d16,vfpv3,neon"
29ad9694 162 (const (symbol_ref "arm_fpu_attr")))
dfaa6d72 163
a1dc0475
RE
164; LENGTH of an instruction (in bytes)
165(define_attr "length" "" (const_int 4))
ff9940b0 166
949d79eb
RE
167; POOL_RANGE is how far away from a constant pool entry that this insn
168; can be placed. If the distance is zero, then this insn will never
169; reference the pool.
d5b7b3ae
RE
170; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
171; before its address.
949d79eb 172(define_attr "pool_range" "" (const_int 0))
d5b7b3ae 173(define_attr "neg_pool_range" "" (const_int 0))
949d79eb 174
5895f793 175; An assembler sequence may clobber the condition codes without us knowing.
56fbb855
RE
176; If such an insn references the pool, then we have no way of knowing how,
177; so use the most conservative value for pool_range.
ff9940b0 178(define_asm_attributes
56fbb855
RE
179 [(set_attr "conds" "clob")
180 (set_attr "length" "4")
181 (set_attr "pool_range" "250")])
ff9940b0 182
9b66ebb1
PB
183;; The instruction used to implement a particular pattern. This
184;; information is used by pipeline descriptions to provide accurate
185;; scheduling information.
186
187(define_attr "insn"
bd4dc3cd 188 "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other"
9b66ebb1
PB
189 (const_string "other"))
190
ff9940b0
RE
191; TYPE attribute is used to detect floating point instructions which, if
192; running on a co-processor can run in parallel with other, basic instructions
193; If write-buffer scheduling is enabled then it can also be used in the
194; scheduling of writes.
195
196; Classification of each insn
a8e17e9e
PB
197; Note: vfp.md has different meanings for some of these, and some further
198; types as well. See that file for details.
9b66ebb1
PB
199; alu any alu instruction that doesn't hit memory or fp
200; regs or have a shifted source operand
201; alu_shift any data instruction that doesn't hit memory or fp
202; regs, but has a source operand shifted by a constant
203; alu_shift_reg any data instruction that doesn't hit memory or fp
204; regs, but has a source operand shifted by a register value
4cdb3ed4 205; mult a multiply instruction
ff9940b0
RE
206; block blockage insn, this blocks all functional units
207; float a floating point arithmetic operation (subject to expansion)
dfaa6d72
RE
208; fdivd DFmode floating point division
209; fdivs SFmode floating point division
210; fmul Floating point multiply
211; ffmul Fast floating point multiply
212; farith Floating point arithmetic (4 cycle)
213; ffarith Fast floating point arithmetic (2 cycle)
ff9940b0 214; float_em a floating point arithmetic operation that is normally emulated
dfaa6d72 215; even on a machine with an fpa.
ff9940b0
RE
216; f_load a floating point load from memory
217; f_store a floating point store to memory
8ab5f5c9
KH
218; f_load[sd] single/double load from memory
219; f_store[sd] single/double store to memory
75fe7b2f 220; f_flag a transfer of co-processor flags to the CPSR
ff9940b0
RE
221; f_mem_r a transfer of a floating point register to a real reg via mem
222; r_mem_f the reverse of f_mem_r
223; f_2_r fast transfer float to arm (no memory needed)
224; r_2_f fast transfer arm to float
75fe7b2f 225; f_cvt convert floating<->integral
9b66ebb1 226; branch a branch
ff9940b0 227; call a subroutine call
9b66ebb1
PB
228; load_byte load byte(s) from memory to arm registers
229; load1 load 1 word from memory to arm registers
230; load2 load 2 words from memory to arm registers
231; load3 load 3 words from memory to arm registers
232; load4 load 4 words from memory to arm registers
233; store store 1 word to memory from arm registers
ff9940b0
RE
234; store2 store 2 words
235; store3 store 3 words
9b66ebb1 236; store4 store 4 (or more) words
f0375c66
NC
237; Additions for Cirrus Maverick co-processor:
238; mav_farith Floating point arithmetic (4 cycle)
239; mav_dmult Double multiplies (7 cycle)
ff9940b0 240;
c956e102 241
ff9940b0 242(define_attr "type"
51c69ddb 243 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,fmuls,fmuld,fmacs,fmacd,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult,fconsts,fconstd,fadds,faddd,ffariths,ffarithd,fcmps,fcmpd,fcpys"
9b66ebb1
PB
244 (if_then_else
245 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
246 (const_string "mult")
247 (const_string "alu")))
ff9940b0 248
f5a1b0d2 249; Load scheduling, set from the arm_ld_sched variable
4912a07c 250; initialized by arm_override_options()
f5a1b0d2 251(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
fef37aaf 252
ecee559f
PB
253;; Classification of NEON instructions for scheduling purposes.
254;; Do not set this attribute and the "type" attribute together in
255;; any one instruction pattern.
256(define_attr "neon_type"
257 "neon_int_1,\
258 neon_int_2,\
259 neon_int_3,\
260 neon_int_4,\
261 neon_int_5,\
262 neon_vqneg_vqabs,\
263 neon_vmov,\
264 neon_vaba,\
265 neon_vsma,\
266 neon_vaba_qqq,\
267 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
268 neon_mul_qqq_8_16_32_ddd_32,\
269 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
270 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
271 neon_mla_qqq_8_16,\
272 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
273 neon_mla_qqq_32_qqd_32_scalar,\
274 neon_mul_ddd_16_scalar_32_16_long_scalar,\
275 neon_mul_qqd_32_scalar,\
276 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
277 neon_shift_1,\
278 neon_shift_2,\
279 neon_shift_3,\
280 neon_vshl_ddd,\
281 neon_vqshl_vrshl_vqrshl_qqq,\
282 neon_vsra_vrsra,\
283 neon_fp_vadd_ddd_vabs_dd,\
284 neon_fp_vadd_qqq_vabs_qq,\
285 neon_fp_vsum,\
286 neon_fp_vmul_ddd,\
287 neon_fp_vmul_qqd,\
288 neon_fp_vmla_ddd,\
289 neon_fp_vmla_qqq,\
290 neon_fp_vmla_ddd_scalar,\
291 neon_fp_vmla_qqq_scalar,\
292 neon_fp_vrecps_vrsqrts_ddd,\
293 neon_fp_vrecps_vrsqrts_qqq,\
294 neon_bp_simple,\
295 neon_bp_2cycle,\
296 neon_bp_3cycle,\
297 neon_ldr,\
298 neon_str,\
299 neon_vld1_1_2_regs,\
300 neon_vld1_3_4_regs,\
301 neon_vld2_2_regs_vld1_vld2_all_lanes,\
302 neon_vld2_4_regs,\
303 neon_vld3_vld4,\
304 neon_vst1_1_2_regs_vst2_2_regs,\
305 neon_vst1_3_4_regs,\
306 neon_vst2_4_regs_vst3_vst4,\
307 neon_vst3_vst4,\
308 neon_vld1_vld2_lane,\
309 neon_vld3_vld4_lane,\
310 neon_vst1_vst2_lane,\
311 neon_vst3_vst4_lane,\
312 neon_vld3_vld4_all_lanes,\
313 neon_mcr,\
314 neon_mcr_2_mcrr,\
315 neon_mrc,\
316 neon_mrrc,\
317 neon_ldm_2,\
318 neon_stm_2,\
319 none"
320 (const_string "none"))
321
4cdb3ed4
RE
322; condition codes: this one is used by final_prescan_insn to speed up
323; conditionalizing instructions. It saves having to scan the rtl to see if
324; it uses or alters the condition codes.
5895f793 325;
4cdb3ed4 326; USE means that the condition codes are used by the insn in the process of
5895f793
RE
327; outputting code, this means (at present) that we can't use the insn in
328; inlined branches
329;
4cdb3ed4 330; SET means that the purpose of the insn is to set the condition codes in a
5895f793
RE
331; well defined manner.
332;
4cdb3ed4 333; CLOB means that the condition codes are altered in an undefined manner, if
5895f793
RE
334; they are altered at all
335;
05ed98a1 336; JUMP_CLOB is used when the condition cannot be represented by a single
5895f793
RE
337; instruction (UNEQ and LTGT). These cannot be predicated.
338;
ecee559f
PB
339; UNCONDITIONAL means the instions can not be conditionally executed.
340;
4cdb3ed4 341; NOCOND means that the condition codes are neither altered nor affect the
5895f793 342; output of this insn
4cdb3ed4 343
ecee559f 344(define_attr "conds" "use,set,clob,jump_clob,unconditional,nocond"
4cdb3ed4 345 (if_then_else (eq_attr "type" "call")
61f0ccff 346 (const_string "clob")
ecee559f
PB
347 (if_then_else (eq_attr "neon_type" "none")
348 (const_string "nocond")
349 (const_string "unconditional"))))
4cdb3ed4 350
5895f793
RE
351; Predicable means that the insn can be conditionally executed based on
352; an automatically added predicate (additional patterns are generated by
353; gen...). We default to 'no' because no Thumb patterns match this rule
354; and not all ARM patterns do.
cca0a211
RE
355(define_attr "predicable" "no,yes" (const_string "no"))
356
b36ba79f
RE
357; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
358; have one. Later ones, such as StrongARM, have write-back caches, so don't
9a9f7594 359; suffer blockages enough to warrant modelling this (and it can adversely
b36ba79f 360; affect the schedule).
abac3b49 361(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
b36ba79f 362
5895f793
RE
363; WRITE_CONFLICT implies that a read following an unrelated write is likely
364; to stall the processor. Used with model_wbuf above.
ff9940b0
RE
365(define_attr "write_conflict" "no,yes"
366 (if_then_else (eq_attr "type"
9b66ebb1 367 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
ff9940b0
RE
368 (const_string "yes")
369 (const_string "no")))
370
5895f793
RE
371; Classify the insns into those that take one cycle and those that take more
372; than one on the main cpu execution unit.
4cdb3ed4
RE
373(define_attr "core_cycles" "single,multi"
374 (if_then_else (eq_attr "type"
9b66ebb1 375 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
4cdb3ed4
RE
376 (const_string "single")
377 (const_string "multi")))
378
d5b7b3ae 379;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
5895f793 380;; distant label. Only applicable to Thumb code.
d5b7b3ae
RE
381(define_attr "far_jump" "yes,no" (const_string "no"))
382
9b901d50 383
5b3e6663
PB
384;; The number of machine instructions this pattern expands to.
385;; Used for Thumb-2 conditional execution.
386(define_attr "ce_count" "" (const_int 1))
387
9b901d50 388;;---------------------------------------------------------------------------
3abcb3a7 389;; Mode iterators
9b901d50
RE
390
391; A list of modes that are exactly 64 bits in size. We use this to expand
392; some splits that are the same for all modes when operating on ARM
393; registers.
3abcb3a7 394(define_mode_iterator ANY64 [DI DF V8QI V4HI V2SI V2SF])
9b901d50
RE
395
396;;---------------------------------------------------------------------------
397;; Predicates
398
a657c98a 399(include "predicates.md")
ce92b223 400(include "constraints.md")
a657c98a 401
9b66ebb1
PB
402;;---------------------------------------------------------------------------
403;; Pipeline descriptions
5895f793 404
2f71a20a
RE
405;; Processor type. This is created automatically from arm-cores.def.
406(include "arm-tune.md")
d19fb8e3 407
51c69ddb
PB
408(define_attr "tune_cortexr4" "yes,no"
409 (const (if_then_else
410 (eq_attr "tune" "cortexr4,cortexr4f")
411 (const_string "yes")
412 (const_string "no"))))
413
9b66ebb1
PB
414;; True if the generic scheduling description should be used.
415
416(define_attr "generic_sched" "yes,no"
e648d85a 417 (const (if_then_else
7612f14d 418 (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
51c69ddb 419 (eq_attr "tune_cortexr4" "yes"))
e648d85a
ILT
420 (const_string "no")
421 (const_string "yes"))))
422
75fe7b2f
RE
423(define_attr "generic_vfp" "yes,no"
424 (const (if_then_else
425 (and (eq_attr "fpu" "vfp")
7612f14d 426 (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9")
51c69ddb 427 (eq_attr "tune_cortexr4" "no"))
75fe7b2f
RE
428 (const_string "yes")
429 (const_string "no"))))
430
9b66ebb1
PB
431(include "arm-generic.md")
432(include "arm926ejs.md")
75fe7b2f 433(include "arm1020e.md")
9b66ebb1
PB
434(include "arm1026ejs.md")
435(include "arm1136jfs.md")
c956e102 436(include "cortex-a8.md")
7612f14d 437(include "cortex-a9.md")
bd4dc3cd 438(include "cortex-r4.md")
51c69ddb 439(include "cortex-r4f.md")
3f4d9b98 440(include "vfp11.md")
103fc15d 441
ff9940b0 442\f
5895f793 443;;---------------------------------------------------------------------------
b15bca31
RE
444;; Insn patterns
445;;
bb6ae783 446;; Addition insns.
5895f793 447
ff9940b0
RE
448;; Note: For DImode insns, there is normally no reason why operands should
449;; not be in the same register, what we don't want is for something being
450;; written to partially overlap something that is an input.
9b6b54e2
NC
451;; Cirrus 64bit additions should not be split because we have a native
452;; 64bit addition instructions.
ff9940b0 453
d5b7b3ae
RE
454(define_expand "adddi3"
455 [(parallel
5895f793 456 [(set (match_operand:DI 0 "s_register_operand" "")
d5b7b3ae
RE
457 (plus:DI (match_operand:DI 1 "s_register_operand" "")
458 (match_operand:DI 2 "s_register_operand" "")))
48a08b9c 459 (clobber (reg:CC CC_REGNUM))])]
d5b7b3ae
RE
460 "TARGET_EITHER"
461 "
9b66ebb1 462 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
9b6b54e2
NC
463 {
464 if (!cirrus_fp_register (operands[0], DImode))
465 operands[0] = force_reg (DImode, operands[0]);
466 if (!cirrus_fp_register (operands[1], DImode))
467 operands[1] = force_reg (DImode, operands[1]);
468 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
469 DONE;
470 }
471
5b3e6663 472 if (TARGET_THUMB1)
d5b7b3ae
RE
473 {
474 if (GET_CODE (operands[1]) != REG)
475 operands[1] = force_reg (SImode, operands[1]);
476 if (GET_CODE (operands[2]) != REG)
477 operands[2] = force_reg (SImode, operands[2]);
478 }
479 "
480)
481
5b3e6663 482(define_insn "*thumb1_adddi3"
d5b7b3ae
RE
483 [(set (match_operand:DI 0 "register_operand" "=l")
484 (plus:DI (match_operand:DI 1 "register_operand" "%0")
5895f793 485 (match_operand:DI 2 "register_operand" "l")))
48a08b9c 486 (clobber (reg:CC CC_REGNUM))
d5b7b3ae 487 ]
5b3e6663 488 "TARGET_THUMB1"
d5b7b3ae
RE
489 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
490 [(set_attr "length" "4")]
491)
492
bb6ae783 493(define_insn_and_split "*arm_adddi3"
d5b7b3ae 494 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
5895f793
RE
495 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
496 (match_operand:DI 2 "s_register_operand" "r, 0")))
48a08b9c 497 (clobber (reg:CC CC_REGNUM))]
5b3e6663 498 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
3a8de233 499 "#"
5b3e6663 500 "TARGET_32BIT && reload_completed"
bb6ae783
RE
501 [(parallel [(set (reg:CC_C CC_REGNUM)
502 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
503 (match_dup 1)))
504 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
505 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
506 (plus:SI (match_dup 4) (match_dup 5))))]
507 "
508 {
509 operands[3] = gen_highpart (SImode, operands[0]);
510 operands[0] = gen_lowpart (SImode, operands[0]);
511 operands[4] = gen_highpart (SImode, operands[1]);
512 operands[1] = gen_lowpart (SImode, operands[1]);
513 operands[5] = gen_highpart (SImode, operands[2]);
514 operands[2] = gen_lowpart (SImode, operands[2]);
515 }"
d5b7b3ae
RE
516 [(set_attr "conds" "clob")
517 (set_attr "length" "8")]
518)
ff9940b0 519
bb6ae783 520(define_insn_and_split "*adddi_sesidi_di"
ff9940b0
RE
521 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
522 (plus:DI (sign_extend:DI
3dafc5c3
RE
523 (match_operand:SI 2 "s_register_operand" "r,r"))
524 (match_operand:DI 1 "s_register_operand" "r,0")))
48a08b9c 525 (clobber (reg:CC CC_REGNUM))]
5b3e6663 526 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
3a8de233 527 "#"
5b3e6663 528 "TARGET_32BIT && reload_completed"
bb6ae783
RE
529 [(parallel [(set (reg:CC_C CC_REGNUM)
530 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
531 (match_dup 1)))
532 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
533 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
534 (plus:SI (ashiftrt:SI (match_dup 2)
535 (const_int 31))
536 (match_dup 4))))]
537 "
538 {
539 operands[3] = gen_highpart (SImode, operands[0]);
540 operands[0] = gen_lowpart (SImode, operands[0]);
541 operands[4] = gen_highpart (SImode, operands[1]);
542 operands[1] = gen_lowpart (SImode, operands[1]);
543 operands[2] = gen_lowpart (SImode, operands[2]);
544 }"
5895f793
RE
545 [(set_attr "conds" "clob")
546 (set_attr "length" "8")]
547)
ff9940b0 548
bb6ae783 549(define_insn_and_split "*adddi_zesidi_di"
ff9940b0
RE
550 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
551 (plus:DI (zero_extend:DI
3dafc5c3
RE
552 (match_operand:SI 2 "s_register_operand" "r,r"))
553 (match_operand:DI 1 "s_register_operand" "r,0")))
bb6ae783 554 (clobber (reg:CC CC_REGNUM))]
5b3e6663 555 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
3a8de233 556 "#"
5b3e6663 557 "TARGET_32BIT && reload_completed"
bb6ae783
RE
558 [(parallel [(set (reg:CC_C CC_REGNUM)
559 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
560 (match_dup 1)))
561 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
562 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
563 (plus:SI (match_dup 4) (const_int 0))))]
564 "
565 {
566 operands[3] = gen_highpart (SImode, operands[0]);
567 operands[0] = gen_lowpart (SImode, operands[0]);
568 operands[4] = gen_highpart (SImode, operands[1]);
569 operands[1] = gen_lowpart (SImode, operands[1]);
570 operands[2] = gen_lowpart (SImode, operands[2]);
571 }"
d5b7b3ae
RE
572 [(set_attr "conds" "clob")
573 (set_attr "length" "8")]
574)
3a33f76f 575
091426d3 576(define_expand "addsi3"
d5b7b3ae 577 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
578 (plus:SI (match_operand:SI 1 "s_register_operand" "")
579 (match_operand:SI 2 "reg_or_int_operand" "")))]
d5b7b3ae 580 "TARGET_EITHER"
091426d3 581 "
5b3e6663 582 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
091426d3 583 {
a406f566
MM
584 arm_split_constant (PLUS, SImode, NULL_RTX,
585 INTVAL (operands[2]), operands[0], operands[1],
b3a13419 586 optimize && can_create_pseudo_p ());
091426d3
RE
587 DONE;
588 }
d5b7b3ae
RE
589 "
590)
091426d3 591
72ac76be 592; If there is a scratch available, this will be faster than synthesizing the
bb6ae783
RE
593; addition.
594(define_peephole2
595 [(match_scratch:SI 3 "r")
3053b100
RE
596 (set (match_operand:SI 0 "arm_general_register_operand" "")
597 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
d5b7b3ae 598 (match_operand:SI 2 "const_int_operand" "")))]
5b3e6663 599 "TARGET_32BIT &&
bb6ae783
RE
600 !(const_ok_for_arm (INTVAL (operands[2]))
601 || const_ok_for_arm (-INTVAL (operands[2])))
602 && const_ok_for_arm (~INTVAL (operands[2]))"
603 [(set (match_dup 3) (match_dup 2))
604 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
605 ""
606)
091426d3 607
e0079468
PB
608;; The r/r/k alternative is required when reloading the address
609;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
610;; put the duplicated register first, and not try the commutative version.
bb6ae783 611(define_insn_and_split "*arm_addsi3"
e0079468
PB
612 [(set (match_operand:SI 0 "s_register_operand" "=r, !k, r,r, !k,r")
613 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,!k, r,rk,!k,rk")
614 (match_operand:SI 2 "reg_or_int_operand" "rI, rI,!k,L, L,?n")))]
5b3e6663 615 "TARGET_32BIT"
68df59d3
RE
616 "@
617 add%?\\t%0, %1, %2
f5c630c3 618 add%?\\t%0, %1, %2
e0079468 619 add%?\\t%0, %2, %1
f5c630c3 620 sub%?\\t%0, %1, #%n2
091426d3
RE
621 sub%?\\t%0, %1, #%n2
622 #"
5b3e6663 623 "TARGET_32BIT &&
bb6ae783
RE
624 GET_CODE (operands[2]) == CONST_INT
625 && !(const_ok_for_arm (INTVAL (operands[2]))
626 || const_ok_for_arm (-INTVAL (operands[2])))"
627 [(clobber (const_int 0))]
628 "
a406f566
MM
629 arm_split_constant (PLUS, SImode, curr_insn,
630 INTVAL (operands[2]), operands[0],
bb6ae783
RE
631 operands[1], 0);
632 DONE;
633 "
e0079468 634 [(set_attr "length" "4,4,4,4,4,16")
cca0a211 635 (set_attr "predicable" "yes")]
d5b7b3ae
RE
636)
637
638;; Register group 'k' is a single register group containing only the stack
639;; register. Trying to reload it will always fail catastrophically,
640;; so never allow those alternatives to match if reloading is needed.
641
5b3e6663 642(define_insn "*thumb1_addsi3"
f5c630c3 643 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k")
d5b7b3ae 644 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
f5c630c3 645 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O")))]
5b3e6663 646 "TARGET_THUMB1"
d5b7b3ae 647 "*
cca0a211 648 static const char * const asms[] =
d5b7b3ae
RE
649 {
650 \"add\\t%0, %0, %2\",
651 \"sub\\t%0, %0, #%n2\",
652 \"add\\t%0, %1, %2\",
653 \"add\\t%0, %0, %2\",
654 \"add\\t%0, %0, %2\",
655 \"add\\t%0, %1, %2\",
656 \"add\\t%0, %1, %2\"
657 };
658 if ((which_alternative == 2 || which_alternative == 6)
659 && GET_CODE (operands[2]) == CONST_INT
660 && INTVAL (operands[2]) < 0)
661 return \"sub\\t%0, %1, #%n2\";
662 return asms[which_alternative];
663 "
664 [(set_attr "length" "2")]
665)
666
667;; Reloading and elimination of the frame pointer can
668;; sometimes cause this optimization to be missed.
bb6ae783 669(define_peephole2
3053b100 670 [(set (match_operand:SI 0 "arm_general_register_operand" "")
12249385 671 (match_operand:SI 1 "const_int_operand" ""))
d5b7b3ae 672 (set (match_dup 0)
3053b100 673 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
5b3e6663 674 "TARGET_THUMB1
d5b7b3ae
RE
675 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
676 && (INTVAL (operands[1]) & 3) == 0"
3053b100 677 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
bb6ae783 678 ""
d5b7b3ae 679)
3a33f76f 680
5b3e6663 681;; ??? Make Thumb-2 variants which prefer low regs
4cdb3ed4 682(define_insn "*addsi3_compare0"
48a08b9c 683 [(set (reg:CC_NOOV CC_REGNUM)
68df59d3 684 (compare:CC_NOOV
5895f793
RE
685 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
686 (match_operand:SI 2 "arm_add_operand" "rI,L"))
68df59d3
RE
687 (const_int 0)))
688 (set (match_operand:SI 0 "s_register_operand" "=r,r")
ff9940b0 689 (plus:SI (match_dup 1) (match_dup 2)))]
5b3e6663 690 "TARGET_32BIT"
68df59d3 691 "@
5b3e6663
PB
692 add%.\\t%0, %1, %2
693 sub%.\\t%0, %1, #%n2"
d5b7b3ae
RE
694 [(set_attr "conds" "set")]
695)
ff9940b0 696
589fe0fc 697(define_insn "*addsi3_compare0_scratch"
48a08b9c 698 [(set (reg:CC_NOOV CC_REGNUM)
589fe0fc 699 (compare:CC_NOOV
5895f793
RE
700 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
701 (match_operand:SI 1 "arm_add_operand" "rI,L"))
589fe0fc 702 (const_int 0)))]
5b3e6663 703 "TARGET_32BIT"
d5b7b3ae
RE
704 "@
705 cmn%?\\t%0, %1
706 cmp%?\\t%0, #%n1"
cca0a211
RE
707 [(set_attr "conds" "set")]
708)
d5b7b3ae 709
1ac3e311
RE
710(define_insn "*compare_negsi_si"
711 [(set (reg:CC_Z CC_REGNUM)
712 (compare:CC_Z
713 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
714 (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 715 "TARGET_32BIT"
1ac3e311 716 "cmn%?\\t%1, %0"
cca0a211
RE
717 [(set_attr "conds" "set")]
718)
589fe0fc 719
f9b9980e
RE
720;; This is the canonicalization of addsi3_compare0_for_combiner when the
721;; addend is a constant.
722(define_insn "*cmpsi2_addneg"
723 [(set (reg:CC CC_REGNUM)
724 (compare:CC
725 (match_operand:SI 1 "s_register_operand" "r,r")
726 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
727 (set (match_operand:SI 0 "s_register_operand" "=r,r")
728 (plus:SI (match_dup 1)
729 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
5b3e6663 730 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
f9b9980e 731 "@
5b3e6663
PB
732 sub%.\\t%0, %1, %2
733 add%.\\t%0, %1, #%n2"
f9b9980e
RE
734 [(set_attr "conds" "set")]
735)
736
737;; Convert the sequence
738;; sub rd, rn, #1
739;; cmn rd, #1 (equivalent to cmp rd, #-1)
740;; bne dest
741;; into
742;; subs rd, rn, #1
743;; bcs dest ((unsigned)rn >= 1)
744;; similarly for the beq variant using bcc.
745;; This is a common looping idiom (while (n--))
746(define_peephole2
3053b100
RE
747 [(set (match_operand:SI 0 "arm_general_register_operand" "")
748 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
f9b9980e
RE
749 (const_int -1)))
750 (set (match_operand 2 "cc_register" "")
751 (compare (match_dup 0) (const_int -1)))
752 (set (pc)
753 (if_then_else (match_operator 3 "equality_operator"
754 [(match_dup 2) (const_int 0)])
755 (match_operand 4 "" "")
756 (match_operand 5 "" "")))]
5b3e6663 757 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
f9b9980e
RE
758 [(parallel[
759 (set (match_dup 2)
760 (compare:CC
761 (match_dup 1) (const_int 1)))
762 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
763 (set (pc)
764 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
765 (match_dup 4)
766 (match_dup 5)))]
767 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
768 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
769 ? GEU : LTU),
770 VOIDmode,
771 operands[2], const0_rtx);"
772)
773
a0b632ec
RE
774;; The next four insns work because they compare the result with one of
775;; the operands, and we know that the use of the condition code is
776;; either GEU or LTU, so we can use the carry flag from the addition
777;; instead of doing the compare a second time.
778(define_insn "*addsi3_compare_op1"
48a08b9c 779 [(set (reg:CC_C CC_REGNUM)
a0b632ec
RE
780 (compare:CC_C
781 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
782 (match_operand:SI 2 "arm_add_operand" "rI,L"))
783 (match_dup 1)))
784 (set (match_operand:SI 0 "s_register_operand" "=r,r")
785 (plus:SI (match_dup 1) (match_dup 2)))]
5b3e6663 786 "TARGET_32BIT"
a0b632ec 787 "@
5b3e6663
PB
788 add%.\\t%0, %1, %2
789 sub%.\\t%0, %1, #%n2"
cca0a211
RE
790 [(set_attr "conds" "set")]
791)
a0b632ec
RE
792
793(define_insn "*addsi3_compare_op2"
48a08b9c 794 [(set (reg:CC_C CC_REGNUM)
a0b632ec
RE
795 (compare:CC_C
796 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
797 (match_operand:SI 2 "arm_add_operand" "rI,L"))
798 (match_dup 2)))
68df59d3 799 (set (match_operand:SI 0 "s_register_operand" "=r,r")
ff9940b0 800 (plus:SI (match_dup 1) (match_dup 2)))]
5b3e6663 801 "TARGET_32BIT"
68df59d3 802 "@
5b3e6663
PB
803 add%.\\t%0, %1, %2
804 sub%.\\t%0, %1, #%n2"
cca0a211
RE
805 [(set_attr "conds" "set")]
806)
ff9940b0 807
a0b632ec 808(define_insn "*compare_addsi2_op0"
48a08b9c 809 [(set (reg:CC_C CC_REGNUM)
a0b632ec
RE
810 (compare:CC_C
811 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
812 (match_operand:SI 1 "arm_add_operand" "rI,L"))
813 (match_dup 0)))]
5b3e6663 814 "TARGET_32BIT"
a0b632ec
RE
815 "@
816 cmn%?\\t%0, %1
817 cmp%?\\t%0, #%n1"
cca0a211
RE
818 [(set_attr "conds" "set")]
819)
a0b632ec
RE
820
821(define_insn "*compare_addsi2_op1"
48a08b9c 822 [(set (reg:CC_C CC_REGNUM)
a0b632ec
RE
823 (compare:CC_C
824 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
825 (match_operand:SI 1 "arm_add_operand" "rI,L"))
826 (match_dup 1)))]
5b3e6663 827 "TARGET_32BIT"
a0b632ec
RE
828 "@
829 cmn%?\\t%0, %1
830 cmp%?\\t%0, #%n1"
cca0a211
RE
831 [(set_attr "conds" "set")]
832)
a0b632ec
RE
833
834(define_insn "*addsi3_carryin"
835 [(set (match_operand:SI 0 "s_register_operand" "=r")
48a08b9c 836 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
a0b632ec
RE
837 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
838 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
5b3e6663 839 "TARGET_32BIT"
a0b632ec 840 "adc%?\\t%0, %1, %2"
d5b7b3ae
RE
841 [(set_attr "conds" "use")]
842)
a0b632ec 843
3a8de233 844(define_insn "*addsi3_carryin_shift"
1cc82d13 845 [(set (match_operand:SI 0 "s_register_operand" "=r")
48a08b9c 846 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
3a8de233
JL
847 (plus:SI
848 (match_operator:SI 2 "shift_operator"
1cc82d13
RE
849 [(match_operand:SI 3 "s_register_operand" "r")
850 (match_operand:SI 4 "reg_or_int_operand" "rM")])
851 (match_operand:SI 1 "s_register_operand" "r"))))]
5b3e6663 852 "TARGET_32BIT"
3a8de233 853 "adc%?\\t%0, %1, %3%S2"
9b66ebb1
PB
854 [(set_attr "conds" "use")
855 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
856 (const_string "alu_shift")
857 (const_string "alu_shift_reg")))]
3a8de233
JL
858)
859
a0b632ec
RE
860(define_insn "*addsi3_carryin_alt1"
861 [(set (match_operand:SI 0 "s_register_operand" "=r")
862 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
863 (match_operand:SI 2 "arm_rhs_operand" "rI"))
48a08b9c 864 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
5b3e6663 865 "TARGET_32BIT"
a0b632ec 866 "adc%?\\t%0, %1, %2"
d5b7b3ae
RE
867 [(set_attr "conds" "use")]
868)
a0b632ec
RE
869
870(define_insn "*addsi3_carryin_alt2"
871 [(set (match_operand:SI 0 "s_register_operand" "=r")
48a08b9c 872 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
a0b632ec
RE
873 (match_operand:SI 1 "s_register_operand" "r"))
874 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
5b3e6663 875 "TARGET_32BIT"
a0b632ec 876 "adc%?\\t%0, %1, %2"
cca0a211
RE
877 [(set_attr "conds" "use")]
878)
a0b632ec
RE
879
880(define_insn "*addsi3_carryin_alt3"
881 [(set (match_operand:SI 0 "s_register_operand" "=r")
48a08b9c 882 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
a0b632ec
RE
883 (match_operand:SI 2 "arm_rhs_operand" "rI"))
884 (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 885 "TARGET_32BIT"
a0b632ec 886 "adc%?\\t%0, %1, %2"
d5b7b3ae
RE
887 [(set_attr "conds" "use")]
888)
a0b632ec 889
5b3e6663
PB
890(define_expand "incscc"
891 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
892 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
893 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
894 (match_operand:SI 1 "s_register_operand" "0,?r")))]
895 "TARGET_32BIT"
896 ""
897)
898
899(define_insn "*arm_incscc"
ff9940b0 900 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 901 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
d5b7b3ae 902 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
ff9940b0 903 (match_operand:SI 1 "s_register_operand" "0,?r")))]
d5b7b3ae 904 "TARGET_ARM"
68df59d3
RE
905 "@
906 add%d2\\t%0, %1, #1
907 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
05ed98a1 908 [(set_attr "conds" "use")
5895f793
RE
909 (set_attr "length" "4,8")]
910)
ff9940b0 911
de9315db
RE
912; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
913(define_split
914 [(set (match_operand:SI 0 "s_register_operand" "")
915 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
916 (match_operand:SI 2 "s_register_operand" ""))
917 (const_int -1)))
918 (clobber (match_operand:SI 3 "s_register_operand" ""))]
5b3e6663 919 "TARGET_32BIT"
de9315db
RE
920 [(set (match_dup 3) (match_dup 1))
921 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
922 "
923 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
924")
925
37f74dcf
RE
926(define_expand "addsf3"
927 [(set (match_operand:SF 0 "s_register_operand" "")
928 (plus:SF (match_operand:SF 1 "s_register_operand" "")
9b66ebb1 929 (match_operand:SF 2 "arm_float_add_operand" "")))]
5b3e6663 930 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 931 "
9b66ebb1 932 if (TARGET_MAVERICK
37f74dcf
RE
933 && !cirrus_fp_register (operands[2], SFmode))
934 operands[2] = force_reg (SFmode, operands[2]);
935")
936
37f74dcf
RE
937(define_expand "adddf3"
938 [(set (match_operand:DF 0 "s_register_operand" "")
939 (plus:DF (match_operand:DF 1 "s_register_operand" "")
9b66ebb1 940 (match_operand:DF 2 "arm_float_add_operand" "")))]
5b3e6663 941 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 942 "
9b66ebb1 943 if (TARGET_MAVERICK
37f74dcf
RE
944 && !cirrus_fp_register (operands[2], DFmode))
945 operands[2] = force_reg (DFmode, operands[2]);
946")
947
d5b7b3ae
RE
948(define_expand "subdi3"
949 [(parallel
950 [(set (match_operand:DI 0 "s_register_operand" "")
951 (minus:DI (match_operand:DI 1 "s_register_operand" "")
952 (match_operand:DI 2 "s_register_operand" "")))
48a08b9c 953 (clobber (reg:CC CC_REGNUM))])]
d5b7b3ae
RE
954 "TARGET_EITHER"
955 "
9b66ebb1 956 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
5b3e6663 957 && TARGET_32BIT
9b6b54e2
NC
958 && cirrus_fp_register (operands[0], DImode)
959 && cirrus_fp_register (operands[1], DImode))
960 {
961 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
962 DONE;
963 }
964
5b3e6663 965 if (TARGET_THUMB1)
d5b7b3ae
RE
966 {
967 if (GET_CODE (operands[1]) != REG)
968 operands[1] = force_reg (SImode, operands[1]);
969 if (GET_CODE (operands[2]) != REG)
970 operands[2] = force_reg (SImode, operands[2]);
971 }
972 "
973)
974
975(define_insn "*arm_subdi3"
976 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
ff9940b0
RE
977 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
978 (match_operand:DI 2 "s_register_operand" "r,0,0")))
48a08b9c 979 (clobber (reg:CC CC_REGNUM))]
5b3e6663 980 "TARGET_32BIT"
3dafc5c3 981 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
d5b7b3ae
RE
982 [(set_attr "conds" "clob")
983 (set_attr "length" "8")]
984)
985
986(define_insn "*thumb_subdi3"
987 [(set (match_operand:DI 0 "register_operand" "=l")
988 (minus:DI (match_operand:DI 1 "register_operand" "0")
989 (match_operand:DI 2 "register_operand" "l")))
48a08b9c 990 (clobber (reg:CC CC_REGNUM))]
5b3e6663 991 "TARGET_THUMB1"
d5b7b3ae
RE
992 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
993 [(set_attr "length" "4")]
994)
ff9940b0 995
4cdb3ed4 996(define_insn "*subdi_di_zesidi"
d5b7b3ae
RE
997 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
998 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
ff9940b0 999 (zero_extend:DI
d5b7b3ae 1000 (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 1001 (clobber (reg:CC CC_REGNUM))]
5b3e6663 1002 "TARGET_32BIT"
3dafc5c3 1003 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
d5b7b3ae
RE
1004 [(set_attr "conds" "clob")
1005 (set_attr "length" "8")]
1006)
ff9940b0 1007
4cdb3ed4 1008(define_insn "*subdi_di_sesidi"
d5b7b3ae
RE
1009 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1010 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
ff9940b0 1011 (sign_extend:DI
d5b7b3ae 1012 (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 1013 (clobber (reg:CC CC_REGNUM))]
5b3e6663 1014 "TARGET_32BIT"
3dafc5c3 1015 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
d5b7b3ae
RE
1016 [(set_attr "conds" "clob")
1017 (set_attr "length" "8")]
1018)
ff9940b0 1019
4cdb3ed4 1020(define_insn "*subdi_zesidi_di"
d5b7b3ae 1021 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
ff9940b0 1022 (minus:DI (zero_extend:DI
d5b7b3ae
RE
1023 (match_operand:SI 2 "s_register_operand" "r,r"))
1024 (match_operand:DI 1 "s_register_operand" "?r,0")))
48a08b9c 1025 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 1026 "TARGET_ARM"
3dafc5c3 1027 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
d5b7b3ae
RE
1028 [(set_attr "conds" "clob")
1029 (set_attr "length" "8")]
1030)
ff9940b0 1031
4cdb3ed4 1032(define_insn "*subdi_sesidi_di"
d5b7b3ae 1033 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
ff9940b0 1034 (minus:DI (sign_extend:DI
d5b7b3ae
RE
1035 (match_operand:SI 2 "s_register_operand" "r,r"))
1036 (match_operand:DI 1 "s_register_operand" "?r,0")))
48a08b9c 1037 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 1038 "TARGET_ARM"
3dafc5c3 1039 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
d5b7b3ae
RE
1040 [(set_attr "conds" "clob")
1041 (set_attr "length" "8")]
1042)
ff9940b0 1043
4cdb3ed4 1044(define_insn "*subdi_zesidi_zesidi"
d5b7b3ae 1045 [(set (match_operand:DI 0 "s_register_operand" "=r")
ff9940b0 1046 (minus:DI (zero_extend:DI
d5b7b3ae 1047 (match_operand:SI 1 "s_register_operand" "r"))
ff9940b0 1048 (zero_extend:DI
d5b7b3ae 1049 (match_operand:SI 2 "s_register_operand" "r"))))
48a08b9c 1050 (clobber (reg:CC CC_REGNUM))]
5b3e6663
PB
1051 "TARGET_32BIT"
1052 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
d5b7b3ae
RE
1053 [(set_attr "conds" "clob")
1054 (set_attr "length" "8")]
1055)
3a33f76f 1056
091426d3 1057(define_expand "subsi3"
d5b7b3ae 1058 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
1059 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1060 (match_operand:SI 2 "s_register_operand" "")))]
d5b7b3ae 1061 "TARGET_EITHER"
091426d3
RE
1062 "
1063 if (GET_CODE (operands[1]) == CONST_INT)
1064 {
5b3e6663 1065 if (TARGET_32BIT)
d5b7b3ae 1066 {
a406f566
MM
1067 arm_split_constant (MINUS, SImode, NULL_RTX,
1068 INTVAL (operands[1]), operands[0],
b3a13419 1069 operands[2], optimize && can_create_pseudo_p ());
d5b7b3ae
RE
1070 DONE;
1071 }
5b3e6663 1072 else /* TARGET_THUMB1 */
d5b7b3ae 1073 operands[1] = force_reg (SImode, operands[1]);
091426d3 1074 }
d5b7b3ae
RE
1075 "
1076)
091426d3 1077
5b3e6663 1078(define_insn "*thumb1_subsi3_insn"
d5b7b3ae
RE
1079 [(set (match_operand:SI 0 "register_operand" "=l")
1080 (minus:SI (match_operand:SI 1 "register_operand" "l")
1081 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 1082 "TARGET_THUMB1"
d5b7b3ae
RE
1083 "sub\\t%0, %1, %2"
1084 [(set_attr "length" "2")]
1085)
1086
5b3e6663 1087; ??? Check Thumb-2 split length
bb6ae783 1088(define_insn_and_split "*arm_subsi3_insn"
f5c630c3
PB
1089 [(set (match_operand:SI 0 "s_register_operand" "=r,rk,r")
1090 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,!k,?n")
1091 (match_operand:SI 2 "s_register_operand" "r, r, r")))]
5b3e6663 1092 "TARGET_32BIT"
0f447ef2 1093 "@
091426d3 1094 rsb%?\\t%0, %2, %1
f5c630c3 1095 sub%?\\t%0, %1, %2
091426d3 1096 #"
5b3e6663 1097 "TARGET_32BIT
bb6ae783
RE
1098 && GET_CODE (operands[1]) == CONST_INT
1099 && !const_ok_for_arm (INTVAL (operands[1]))"
091426d3
RE
1100 [(clobber (const_int 0))]
1101 "
a406f566
MM
1102 arm_split_constant (MINUS, SImode, curr_insn,
1103 INTVAL (operands[1]), operands[0], operands[2], 0);
091426d3 1104 DONE;
d5b7b3ae 1105 "
f5c630c3 1106 [(set_attr "length" "4,4,16")
bb6ae783
RE
1107 (set_attr "predicable" "yes")]
1108)
1109
1110(define_peephole2
1111 [(match_scratch:SI 3 "r")
3053b100 1112 (set (match_operand:SI 0 "arm_general_register_operand" "")
bb6ae783 1113 (minus:SI (match_operand:SI 1 "const_int_operand" "")
3053b100 1114 (match_operand:SI 2 "arm_general_register_operand" "")))]
5b3e6663 1115 "TARGET_32BIT
bb6ae783
RE
1116 && !const_ok_for_arm (INTVAL (operands[1]))
1117 && const_ok_for_arm (~INTVAL (operands[1]))"
1118 [(set (match_dup 3) (match_dup 1))
1119 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1120 ""
d5b7b3ae 1121)
3a33f76f 1122
4cdb3ed4 1123(define_insn "*subsi3_compare0"
48a08b9c 1124 [(set (reg:CC_NOOV CC_REGNUM)
5895f793
RE
1125 (compare:CC_NOOV
1126 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1127 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1128 (const_int 0)))
ff9940b0
RE
1129 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1130 (minus:SI (match_dup 1) (match_dup 2)))]
5b3e6663 1131 "TARGET_32BIT"
0f447ef2 1132 "@
5b3e6663
PB
1133 sub%.\\t%0, %1, %2
1134 rsb%.\\t%0, %2, %1"
d5b7b3ae
RE
1135 [(set_attr "conds" "set")]
1136)
ff9940b0 1137
5b3e6663
PB
1138(define_expand "decscc"
1139 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1140 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1141 (match_operator:SI 2 "arm_comparison_operator"
1142 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1143 "TARGET_32BIT"
1144 ""
1145)
1146
1147(define_insn "*arm_decscc"
d5b7b3ae
RE
1148 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1149 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
05ed98a1 1150 (match_operator:SI 2 "arm_comparison_operator"
d5b7b3ae
RE
1151 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1152 "TARGET_ARM"
0f447ef2 1153 "@
5895f793
RE
1154 sub%d2\\t%0, %1, #1
1155 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
d5b7b3ae
RE
1156 [(set_attr "conds" "use")
1157 (set_attr "length" "*,8")]
1158)
ff9940b0 1159
37f74dcf
RE
1160(define_expand "subsf3"
1161 [(set (match_operand:SF 0 "s_register_operand" "")
9b66ebb1
PB
1162 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1163 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1164 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 1165 "
9b66ebb1 1166 if (TARGET_MAVERICK)
37f74dcf
RE
1167 {
1168 if (!cirrus_fp_register (operands[1], SFmode))
1169 operands[1] = force_reg (SFmode, operands[1]);
1170 if (!cirrus_fp_register (operands[2], SFmode))
1171 operands[2] = force_reg (SFmode, operands[2]);
1172 }
1173")
1174
37f74dcf
RE
1175(define_expand "subdf3"
1176 [(set (match_operand:DF 0 "s_register_operand" "")
9b66ebb1
PB
1177 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1178 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1179 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 1180 "
9b66ebb1 1181 if (TARGET_MAVERICK)
37f74dcf
RE
1182 {
1183 if (!cirrus_fp_register (operands[1], DFmode))
1184 operands[1] = force_reg (DFmode, operands[1]);
1185 if (!cirrus_fp_register (operands[2], DFmode))
1186 operands[2] = force_reg (DFmode, operands[2]);
1187 }
1188")
1189
3a33f76f
RK
1190\f
1191;; Multiplication insns
1192
d5b7b3ae
RE
1193(define_expand "mulsi3"
1194 [(set (match_operand:SI 0 "s_register_operand" "")
1195 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1196 (match_operand:SI 1 "s_register_operand" "")))]
1197 "TARGET_EITHER"
1198 ""
1199)
1200
ff9940b0 1201;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
d5b7b3ae
RE
1202(define_insn "*arm_mulsi3"
1203 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
ff9940b0
RE
1204 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1205 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
d6c397b0 1206 "TARGET_32BIT && !arm_arch6"
4cdb3ed4 1207 "mul%?\\t%0, %2, %1"
9b66ebb1 1208 [(set_attr "insn" "mul")
cca0a211 1209 (set_attr "predicable" "yes")]
d5b7b3ae
RE
1210)
1211
d6c397b0
PB
1212(define_insn "*arm_mulsi3_v6"
1213 [(set (match_operand:SI 0 "s_register_operand" "=r")
1214 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1215 (match_operand:SI 2 "s_register_operand" "r")))]
1216 "TARGET_32BIT && arm_arch6"
1217 "mul%?\\t%0, %1, %2"
1218 [(set_attr "insn" "mul")
1219 (set_attr "predicable" "yes")]
1220)
1221
5895f793
RE
1222; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1223; 1 and 2; are the same, because reload will make operand 0 match
1224; operand 1 without realizing that this conflicts with operand 2. We fix
1225; this by adding another alternative to match this case, and then `reload'
1226; it ourselves. This alternative must come first.
d5b7b3ae
RE
1227(define_insn "*thumb_mulsi3"
1228 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1229 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1230 (match_operand:SI 2 "register_operand" "l,l,l")))]
d6c397b0 1231 "TARGET_THUMB1 && !arm_arch6"
d5b7b3ae
RE
1232 "*
1233 if (which_alternative < 2)
d08e2ccb 1234 return \"mov\\t%0, %1\;mul\\t%0, %2\";
d5b7b3ae 1235 else
d08e2ccb 1236 return \"mul\\t%0, %2\";
d5b7b3ae
RE
1237 "
1238 [(set_attr "length" "4,4,2")
9b66ebb1 1239 (set_attr "insn" "mul")]
d5b7b3ae 1240)
3a33f76f 1241
d6c397b0
PB
1242(define_insn "*thumb_mulsi3_v6"
1243 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1244 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1245 (match_operand:SI 2 "register_operand" "l,0,0")))]
1246 "TARGET_THUMB1 && arm_arch6"
1247 "@
1248 mul\\t%0, %2
1249 mul\\t%0, %1
1250 mul\\t%0, %1"
1251 [(set_attr "length" "2")
1252 (set_attr "insn" "mul")]
1253)
1254
4cdb3ed4 1255(define_insn "*mulsi3_compare0"
48a08b9c 1256 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
1257 (compare:CC_NOOV (mult:SI
1258 (match_operand:SI 2 "s_register_operand" "r,r")
1259 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1260 (const_int 0)))
1261 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1262 (mult:SI (match_dup 2) (match_dup 1)))]
d6c397b0
PB
1263 "TARGET_ARM && !arm_arch6"
1264 "mul%.\\t%0, %2, %1"
1265 [(set_attr "conds" "set")
1266 (set_attr "insn" "muls")]
1267)
1268
1269(define_insn "*mulsi3_compare0_v6"
1270 [(set (reg:CC_NOOV CC_REGNUM)
1271 (compare:CC_NOOV (mult:SI
1272 (match_operand:SI 2 "s_register_operand" "r")
1273 (match_operand:SI 1 "s_register_operand" "r"))
1274 (const_int 0)))
1275 (set (match_operand:SI 0 "s_register_operand" "=r")
1276 (mult:SI (match_dup 2) (match_dup 1)))]
1277 "TARGET_ARM && arm_arch6 && optimize_size"
5b3e6663 1278 "mul%.\\t%0, %2, %1"
d5b7b3ae 1279 [(set_attr "conds" "set")
9b66ebb1 1280 (set_attr "insn" "muls")]
d5b7b3ae 1281)
ff9940b0 1282
4cdb3ed4 1283(define_insn "*mulsi_compare0_scratch"
48a08b9c 1284 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
1285 (compare:CC_NOOV (mult:SI
1286 (match_operand:SI 2 "s_register_operand" "r,r")
1287 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1288 (const_int 0)))
1289 (clobber (match_scratch:SI 0 "=&r,&r"))]
d6c397b0
PB
1290 "TARGET_ARM && !arm_arch6"
1291 "mul%.\\t%0, %2, %1"
1292 [(set_attr "conds" "set")
1293 (set_attr "insn" "muls")]
1294)
1295
1296(define_insn "*mulsi_compare0_scratch_v6"
1297 [(set (reg:CC_NOOV CC_REGNUM)
1298 (compare:CC_NOOV (mult:SI
1299 (match_operand:SI 2 "s_register_operand" "r")
1300 (match_operand:SI 1 "s_register_operand" "r"))
1301 (const_int 0)))
1302 (clobber (match_scratch:SI 0 "=r"))]
1303 "TARGET_ARM && arm_arch6 && optimize_size"
5b3e6663 1304 "mul%.\\t%0, %2, %1"
d5b7b3ae 1305 [(set_attr "conds" "set")
9b66ebb1 1306 (set_attr "insn" "muls")]
d5b7b3ae 1307)
ff9940b0 1308
3a33f76f
RK
1309;; Unnamed templates to match MLA instruction.
1310
4cdb3ed4 1311(define_insn "*mulsi3addsi"
ff9940b0 1312 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
fd3f89a9 1313 (plus:SI
ff9940b0
RE
1314 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1315 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1316 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
d6c397b0
PB
1317 "TARGET_32BIT && !arm_arch6"
1318 "mla%?\\t%0, %2, %1, %3"
1319 [(set_attr "insn" "mla")
1320 (set_attr "predicable" "yes")]
1321)
1322
1323(define_insn "*mulsi3addsi_v6"
1324 [(set (match_operand:SI 0 "s_register_operand" "=r")
1325 (plus:SI
1326 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1327 (match_operand:SI 1 "s_register_operand" "r"))
1328 (match_operand:SI 3 "s_register_operand" "r")))]
1329 "TARGET_32BIT && arm_arch6"
4cdb3ed4 1330 "mla%?\\t%0, %2, %1, %3"
9b66ebb1 1331 [(set_attr "insn" "mla")
cca0a211
RE
1332 (set_attr "predicable" "yes")]
1333)
3a33f76f 1334
4cdb3ed4 1335(define_insn "*mulsi3addsi_compare0"
48a08b9c 1336 [(set (reg:CC_NOOV CC_REGNUM)
5895f793
RE
1337 (compare:CC_NOOV
1338 (plus:SI (mult:SI
1339 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1340 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1341 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1342 (const_int 0)))
ff9940b0
RE
1343 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1344 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1345 (match_dup 3)))]
d6c397b0
PB
1346 "TARGET_ARM && arm_arch6"
1347 "mla%.\\t%0, %2, %1, %3"
1348 [(set_attr "conds" "set")
1349 (set_attr "insn" "mlas")]
1350)
1351
1352(define_insn "*mulsi3addsi_compare0_v6"
1353 [(set (reg:CC_NOOV CC_REGNUM)
1354 (compare:CC_NOOV
1355 (plus:SI (mult:SI
1356 (match_operand:SI 2 "s_register_operand" "r")
1357 (match_operand:SI 1 "s_register_operand" "r"))
1358 (match_operand:SI 3 "s_register_operand" "r"))
1359 (const_int 0)))
1360 (set (match_operand:SI 0 "s_register_operand" "=r")
1361 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1362 (match_dup 3)))]
1363 "TARGET_ARM && arm_arch6 && optimize_size"
5b3e6663 1364 "mla%.\\t%0, %2, %1, %3"
cca0a211 1365 [(set_attr "conds" "set")
9b66ebb1 1366 (set_attr "insn" "mlas")]
cca0a211 1367)
ff9940b0 1368
4cdb3ed4 1369(define_insn "*mulsi3addsi_compare0_scratch"
48a08b9c 1370 [(set (reg:CC_NOOV CC_REGNUM)
5895f793
RE
1371 (compare:CC_NOOV
1372 (plus:SI (mult:SI
1373 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1374 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1375 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1376 (const_int 0)))
ff9940b0 1377 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
d6c397b0
PB
1378 "TARGET_ARM && !arm_arch6"
1379 "mla%.\\t%0, %2, %1, %3"
1380 [(set_attr "conds" "set")
1381 (set_attr "insn" "mlas")]
1382)
1383
1384(define_insn "*mulsi3addsi_compare0_scratch_v6"
1385 [(set (reg:CC_NOOV CC_REGNUM)
1386 (compare:CC_NOOV
1387 (plus:SI (mult:SI
1388 (match_operand:SI 2 "s_register_operand" "r")
1389 (match_operand:SI 1 "s_register_operand" "r"))
1390 (match_operand:SI 3 "s_register_operand" "r"))
1391 (const_int 0)))
1392 (clobber (match_scratch:SI 0 "=r"))]
1393 "TARGET_ARM && arm_arch6 && optimize_size"
5b3e6663 1394 "mla%.\\t%0, %2, %1, %3"
d5b7b3ae 1395 [(set_attr "conds" "set")
9b66ebb1 1396 (set_attr "insn" "mlas")]
d5b7b3ae 1397)
4cdb3ed4 1398
26b53f80
PB
1399(define_insn "*mulsi3subsi"
1400 [(set (match_operand:SI 0 "s_register_operand" "=r")
1401 (minus:SI
1402 (match_operand:SI 3 "s_register_operand" "r")
1403 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1404 (match_operand:SI 1 "s_register_operand" "r"))))]
1405 "TARGET_32BIT && arm_arch_thumb2"
1406 "mls%?\\t%0, %2, %1, %3"
1407 [(set_attr "insn" "mla")
1408 (set_attr "predicable" "yes")]
1409)
1410
839a4992 1411;; Unnamed template to match long long multiply-accumulate (smlal)
9e3fc430
CP
1412
1413(define_insn "*mulsidi3adddi"
b082bfdb 1414 [(set (match_operand:DI 0 "s_register_operand" "=&r")
9e3fc430 1415 (plus:DI
5895f793 1416 (mult:DI
b082bfdb
RE
1417 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1418 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1419 (match_operand:DI 1 "s_register_operand" "0")))]
d6c397b0
PB
1420 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1421 "smlal%?\\t%Q0, %R0, %3, %2"
1422 [(set_attr "insn" "smlal")
1423 (set_attr "predicable" "yes")]
1424)
1425
1426(define_insn "*mulsidi3adddi_v6"
1427 [(set (match_operand:DI 0 "s_register_operand" "=r")
1428 (plus:DI
1429 (mult:DI
1430 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1431 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1432 (match_operand:DI 1 "s_register_operand" "0")))]
1433 "TARGET_32BIT && arm_arch6"
b082bfdb 1434 "smlal%?\\t%Q0, %R0, %3, %2"
9b66ebb1 1435 [(set_attr "insn" "smlal")
cca0a211
RE
1436 (set_attr "predicable" "yes")]
1437)
9e3fc430 1438
fc7a6a0d
ZW
1439;; 32x32->64 widening multiply.
1440;; As with mulsi3, the only difference between the v3-5 and v6+
1441;; versions of these patterns is the requirement that the output not
1442;; overlap the inputs, but that still means we have to have a named
1443;; expander and two different starred insns.
1444
1445(define_expand "mulsidi3"
1446 [(set (match_operand:DI 0 "s_register_operand" "")
1447 (mult:DI
1448 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1449 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1450 "TARGET_32BIT && arm_arch3m"
1451 ""
1452)
1453
1454(define_insn "*mulsidi3_nov6"
4cdb3ed4 1455 [(set (match_operand:DI 0 "s_register_operand" "=&r")
5895f793
RE
1456 (mult:DI
1457 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1458 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
d6c397b0
PB
1459 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1460 "smull%?\\t%Q0, %R0, %1, %2"
1461 [(set_attr "insn" "smull")
1462 (set_attr "predicable" "yes")]
1463)
1464
fc7a6a0d 1465(define_insn "*mulsidi3_v6"
d6c397b0
PB
1466 [(set (match_operand:DI 0 "s_register_operand" "=r")
1467 (mult:DI
1468 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1469 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1470 "TARGET_32BIT && arm_arch6"
3dafc5c3 1471 "smull%?\\t%Q0, %R0, %1, %2"
9b66ebb1 1472 [(set_attr "insn" "smull")
cca0a211
RE
1473 (set_attr "predicable" "yes")]
1474)
4cdb3ed4 1475
fc7a6a0d
ZW
1476(define_expand "umulsidi3"
1477 [(set (match_operand:DI 0 "s_register_operand" "")
1478 (mult:DI
1479 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1480 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1481 "TARGET_32BIT && arm_arch3m"
1482 ""
1483)
1484
1485(define_insn "*umulsidi3_nov6"
4cdb3ed4 1486 [(set (match_operand:DI 0 "s_register_operand" "=&r")
5895f793
RE
1487 (mult:DI
1488 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1489 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
d6c397b0
PB
1490 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1491 "umull%?\\t%Q0, %R0, %1, %2"
1492 [(set_attr "insn" "umull")
1493 (set_attr "predicable" "yes")]
1494)
1495
fc7a6a0d 1496(define_insn "*umulsidi3_v6"
d6c397b0
PB
1497 [(set (match_operand:DI 0 "s_register_operand" "=r")
1498 (mult:DI
1499 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1500 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1501 "TARGET_32BIT && arm_arch6"
3dafc5c3 1502 "umull%?\\t%Q0, %R0, %1, %2"
9b66ebb1 1503 [(set_attr "insn" "umull")
cca0a211
RE
1504 (set_attr "predicable" "yes")]
1505)
3a33f76f 1506
839a4992 1507;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
9e3fc430
CP
1508
1509(define_insn "*umulsidi3adddi"
a67ded0f 1510 [(set (match_operand:DI 0 "s_register_operand" "=&r")
9e3fc430 1511 (plus:DI
5895f793 1512 (mult:DI
b082bfdb
RE
1513 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1514 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1515 (match_operand:DI 1 "s_register_operand" "0")))]
d6c397b0
PB
1516 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1517 "umlal%?\\t%Q0, %R0, %3, %2"
1518 [(set_attr "insn" "umlal")
1519 (set_attr "predicable" "yes")]
1520)
1521
1522(define_insn "*umulsidi3adddi_v6"
1523 [(set (match_operand:DI 0 "s_register_operand" "=r")
1524 (plus:DI
1525 (mult:DI
1526 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1527 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1528 (match_operand:DI 1 "s_register_operand" "0")))]
1529 "TARGET_32BIT && arm_arch6"
b082bfdb 1530 "umlal%?\\t%Q0, %R0, %3, %2"
9b66ebb1 1531 [(set_attr "insn" "umlal")
cca0a211
RE
1532 (set_attr "predicable" "yes")]
1533)
9e3fc430 1534
fc7a6a0d
ZW
1535(define_expand "smulsi3_highpart"
1536 [(parallel
1537 [(set (match_operand:SI 0 "s_register_operand" "")
1538 (truncate:SI
1539 (lshiftrt:DI
1540 (mult:DI
1541 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1542 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1543 (const_int 32))))
1544 (clobber (match_scratch:SI 3 ""))])]
1545 "TARGET_32BIT && arm_arch3m"
1546 ""
1547)
1548
1549(define_insn "*smulsi3_highpart_nov6"
7a0a1f09
RE
1550 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1551 (truncate:SI
1552 (lshiftrt:DI
5895f793
RE
1553 (mult:DI
1554 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1555 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
7a0a1f09
RE
1556 (const_int 32))))
1557 (clobber (match_scratch:SI 3 "=&r,&r"))]
d6c397b0
PB
1558 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1559 "smull%?\\t%3, %0, %2, %1"
1560 [(set_attr "insn" "smull")
1561 (set_attr "predicable" "yes")]
1562)
1563
fc7a6a0d 1564(define_insn "*smulsi3_highpart_v6"
d6c397b0
PB
1565 [(set (match_operand:SI 0 "s_register_operand" "=r")
1566 (truncate:SI
1567 (lshiftrt:DI
1568 (mult:DI
1569 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1570 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1571 (const_int 32))))
1572 (clobber (match_scratch:SI 3 "=r"))]
1573 "TARGET_32BIT && arm_arch6"
7a0a1f09 1574 "smull%?\\t%3, %0, %2, %1"
9b66ebb1 1575 [(set_attr "insn" "smull")
cca0a211 1576 (set_attr "predicable" "yes")]
d5b7b3ae 1577)
7a0a1f09 1578
fc7a6a0d
ZW
1579(define_expand "umulsi3_highpart"
1580 [(parallel
1581 [(set (match_operand:SI 0 "s_register_operand" "")
1582 (truncate:SI
1583 (lshiftrt:DI
1584 (mult:DI
1585 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1586 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1587 (const_int 32))))
1588 (clobber (match_scratch:SI 3 ""))])]
1589 "TARGET_32BIT && arm_arch3m"
1590 ""
1591)
1592
1593(define_insn "*umulsi3_highpart_nov6"
7a0a1f09
RE
1594 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1595 (truncate:SI
1596 (lshiftrt:DI
5895f793
RE
1597 (mult:DI
1598 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1599 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
7a0a1f09
RE
1600 (const_int 32))))
1601 (clobber (match_scratch:SI 3 "=&r,&r"))]
d6c397b0
PB
1602 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1603 "umull%?\\t%3, %0, %2, %1"
1604 [(set_attr "insn" "umull")
1605 (set_attr "predicable" "yes")]
1606)
1607
fc7a6a0d 1608(define_insn "*umulsi3_highpart_v6"
d6c397b0
PB
1609 [(set (match_operand:SI 0 "s_register_operand" "=r")
1610 (truncate:SI
1611 (lshiftrt:DI
1612 (mult:DI
1613 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1614 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1615 (const_int 32))))
1616 (clobber (match_scratch:SI 3 "=r"))]
1617 "TARGET_32BIT && arm_arch6"
7a0a1f09 1618 "umull%?\\t%3, %0, %2, %1"
9b66ebb1 1619 [(set_attr "insn" "umull")
cca0a211 1620 (set_attr "predicable" "yes")]
d5b7b3ae 1621)
7a0a1f09 1622
d19fb8e3
NC
1623(define_insn "mulhisi3"
1624 [(set (match_operand:SI 0 "s_register_operand" "=r")
1625 (mult:SI (sign_extend:SI
1626 (match_operand:HI 1 "s_register_operand" "%r"))
1627 (sign_extend:SI
1628 (match_operand:HI 2 "s_register_operand" "r"))))]
5b3e6663 1629 "TARGET_DSP_MULTIPLY"
859230d4 1630 "smulbb%?\\t%0, %1, %2"
9b66ebb1 1631 [(set_attr "insn" "smulxy")
b8c53e96
RE
1632 (set_attr "predicable" "yes")]
1633)
1634
1635(define_insn "*mulhisi3tb"
1636 [(set (match_operand:SI 0 "s_register_operand" "=r")
1637 (mult:SI (ashiftrt:SI
1638 (match_operand:SI 1 "s_register_operand" "r")
1639 (const_int 16))
1640 (sign_extend:SI
1641 (match_operand:HI 2 "s_register_operand" "r"))))]
5b3e6663 1642 "TARGET_DSP_MULTIPLY"
b8c53e96 1643 "smultb%?\\t%0, %1, %2"
9b66ebb1 1644 [(set_attr "insn" "smulxy")
b8c53e96
RE
1645 (set_attr "predicable" "yes")]
1646)
1647
1648(define_insn "*mulhisi3bt"
1649 [(set (match_operand:SI 0 "s_register_operand" "=r")
1650 (mult:SI (sign_extend:SI
1651 (match_operand:HI 1 "s_register_operand" "r"))
1652 (ashiftrt:SI
1653 (match_operand:SI 2 "s_register_operand" "r")
1654 (const_int 16))))]
5b3e6663 1655 "TARGET_DSP_MULTIPLY"
b8c53e96 1656 "smulbt%?\\t%0, %1, %2"
9b66ebb1 1657 [(set_attr "insn" "smulxy")
b8c53e96
RE
1658 (set_attr "predicable" "yes")]
1659)
1660
1661(define_insn "*mulhisi3tt"
1662 [(set (match_operand:SI 0 "s_register_operand" "=r")
1663 (mult:SI (ashiftrt:SI
1664 (match_operand:SI 1 "s_register_operand" "r")
1665 (const_int 16))
1666 (ashiftrt:SI
1667 (match_operand:SI 2 "s_register_operand" "r")
1668 (const_int 16))))]
5b3e6663 1669 "TARGET_DSP_MULTIPLY"
b8c53e96 1670 "smultt%?\\t%0, %1, %2"
9b66ebb1 1671 [(set_attr "insn" "smulxy")
b8c53e96 1672 (set_attr "predicable" "yes")]
d19fb8e3
NC
1673)
1674
1675(define_insn "*mulhisi3addsi"
1676 [(set (match_operand:SI 0 "s_register_operand" "=r")
1677 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1678 (mult:SI (sign_extend:SI
1679 (match_operand:HI 2 "s_register_operand" "%r"))
1680 (sign_extend:SI
1681 (match_operand:HI 3 "s_register_operand" "r")))))]
5b3e6663 1682 "TARGET_DSP_MULTIPLY"
859230d4 1683 "smlabb%?\\t%0, %2, %3, %1"
9b66ebb1 1684 [(set_attr "insn" "smlaxy")
b8c53e96 1685 (set_attr "predicable" "yes")]
d19fb8e3
NC
1686)
1687
1688(define_insn "*mulhidi3adddi"
1689 [(set (match_operand:DI 0 "s_register_operand" "=r")
1690 (plus:DI
1691 (match_operand:DI 1 "s_register_operand" "0")
1692 (mult:DI (sign_extend:DI
1693 (match_operand:HI 2 "s_register_operand" "%r"))
1694 (sign_extend:DI
1695 (match_operand:HI 3 "s_register_operand" "r")))))]
5b3e6663 1696 "TARGET_DSP_MULTIPLY"
d19fb8e3 1697 "smlalbb%?\\t%Q0, %R0, %2, %3"
9b66ebb1 1698 [(set_attr "insn" "smlalxy")
b8c53e96 1699 (set_attr "predicable" "yes")])
d19fb8e3 1700
37f74dcf
RE
1701(define_expand "mulsf3"
1702 [(set (match_operand:SF 0 "s_register_operand" "")
1703 (mult:SF (match_operand:SF 1 "s_register_operand" "")
9b66ebb1 1704 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1705 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 1706 "
9b66ebb1 1707 if (TARGET_MAVERICK
37f74dcf
RE
1708 && !cirrus_fp_register (operands[2], SFmode))
1709 operands[2] = force_reg (SFmode, operands[2]);
1710")
1711
37f74dcf
RE
1712(define_expand "muldf3"
1713 [(set (match_operand:DF 0 "s_register_operand" "")
1714 (mult:DF (match_operand:DF 1 "s_register_operand" "")
9b66ebb1 1715 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1716 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 1717 "
9b66ebb1 1718 if (TARGET_MAVERICK
37f74dcf
RE
1719 && !cirrus_fp_register (operands[2], DFmode))
1720 operands[2] = force_reg (DFmode, operands[2]);
1721")
3a33f76f
RK
1722\f
1723;; Division insns
1724
82955615
RE
1725(define_expand "divsf3"
1726 [(set (match_operand:SF 0 "s_register_operand" "")
9b66ebb1
PB
1727 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1728 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1729 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
82955615 1730 "")
ff9940b0 1731
82955615
RE
1732(define_expand "divdf3"
1733 [(set (match_operand:DF 0 "s_register_operand" "")
9b66ebb1
PB
1734 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1735 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1736 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
82955615 1737 "")
3a33f76f
RK
1738\f
1739;; Modulo insns
1740
82955615
RE
1741(define_expand "modsf3"
1742 [(set (match_operand:SF 0 "s_register_operand" "")
1743 (mod:SF (match_operand:SF 1 "s_register_operand" "")
9b66ebb1 1744 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1745 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
82955615 1746 "")
ff9940b0 1747
82955615
RE
1748(define_expand "moddf3"
1749 [(set (match_operand:DF 0 "s_register_operand" "")
1750 (mod:DF (match_operand:DF 1 "s_register_operand" "")
9b66ebb1 1751 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1752 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
82955615 1753 "")
3a33f76f
RK
1754\f
1755;; Boolean and,ior,xor insns
1756
6ab589e0
JL
1757;; Split up double word logical operations
1758
1759;; Split up simple DImode logical operations. Simply perform the logical
1760;; operation on the upper and lower halves of the registers.
1761(define_split
1762 [(set (match_operand:DI 0 "s_register_operand" "")
1763 (match_operator:DI 6 "logical_binary_operator"
1764 [(match_operand:DI 1 "s_register_operand" "")
1765 (match_operand:DI 2 "s_register_operand" "")]))]
5b3e6663
PB
1766 "TARGET_32BIT && reload_completed
1767 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
6ab589e0
JL
1768 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1769 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1770 "
5895f793
RE
1771 {
1772 operands[3] = gen_highpart (SImode, operands[0]);
1773 operands[0] = gen_lowpart (SImode, operands[0]);
1774 operands[4] = gen_highpart (SImode, operands[1]);
1775 operands[1] = gen_lowpart (SImode, operands[1]);
1776 operands[5] = gen_highpart (SImode, operands[2]);
1777 operands[2] = gen_lowpart (SImode, operands[2]);
1778 }"
1779)
6ab589e0 1780
6ab589e0
JL
1781(define_split
1782 [(set (match_operand:DI 0 "s_register_operand" "")
1783 (match_operator:DI 6 "logical_binary_operator"
1784 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1785 (match_operand:DI 1 "s_register_operand" "")]))]
5b3e6663 1786 "TARGET_32BIT && reload_completed"
6ab589e0
JL
1787 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1788 (set (match_dup 3) (match_op_dup:SI 6
1789 [(ashiftrt:SI (match_dup 2) (const_int 31))
1790 (match_dup 4)]))]
1791 "
5895f793
RE
1792 {
1793 operands[3] = gen_highpart (SImode, operands[0]);
1794 operands[0] = gen_lowpart (SImode, operands[0]);
1795 operands[4] = gen_highpart (SImode, operands[1]);
1796 operands[1] = gen_lowpart (SImode, operands[1]);
1797 operands[5] = gen_highpart (SImode, operands[2]);
1798 operands[2] = gen_lowpart (SImode, operands[2]);
1799 }"
1800)
6ab589e0 1801
6ab589e0
JL
1802;; The zero extend of operand 2 means we can just copy the high part of
1803;; operand1 into operand0.
1804(define_split
1805 [(set (match_operand:DI 0 "s_register_operand" "")
1806 (ior:DI
1807 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1808 (match_operand:DI 1 "s_register_operand" "")))]
5b3e6663 1809 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
6ab589e0
JL
1810 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1811 (set (match_dup 3) (match_dup 4))]
1812 "
5895f793
RE
1813 {
1814 operands[4] = gen_highpart (SImode, operands[1]);
1815 operands[3] = gen_highpart (SImode, operands[0]);
1816 operands[0] = gen_lowpart (SImode, operands[0]);
1817 operands[1] = gen_lowpart (SImode, operands[1]);
1818 }"
1819)
6ab589e0
JL
1820
1821;; The zero extend of operand 2 means we can just copy the high part of
1822;; operand1 into operand0.
1823(define_split
1824 [(set (match_operand:DI 0 "s_register_operand" "")
1825 (xor:DI
1826 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1827 (match_operand:DI 1 "s_register_operand" "")))]
5b3e6663 1828 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
6ab589e0
JL
1829 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1830 (set (match_dup 3) (match_dup 4))]
1831 "
5895f793
RE
1832 {
1833 operands[4] = gen_highpart (SImode, operands[1]);
1834 operands[3] = gen_highpart (SImode, operands[0]);
1835 operands[0] = gen_lowpart (SImode, operands[0]);
1836 operands[1] = gen_lowpart (SImode, operands[1]);
1837 }"
1838)
6ab589e0 1839
3a33f76f 1840(define_insn "anddi3"
d5b7b3ae
RE
1841 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1842 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1843 (match_operand:DI 2 "s_register_operand" "r,r")))]
5b3e6663 1844 "TARGET_32BIT && ! TARGET_IWMMXT"
6ab589e0 1845 "#"
5895f793
RE
1846 [(set_attr "length" "8")]
1847)
3a33f76f 1848
bb6ae783 1849(define_insn_and_split "*anddi_zesidi_di"
ff9940b0
RE
1850 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1851 (and:DI (zero_extend:DI
1852 (match_operand:SI 2 "s_register_operand" "r,r"))
1853 (match_operand:DI 1 "s_register_operand" "?r,0")))]
5b3e6663 1854 "TARGET_32BIT"
6ab589e0 1855 "#"
5b3e6663 1856 "TARGET_32BIT && reload_completed"
bb6ae783
RE
1857 ; The zero extend of operand 2 clears the high word of the output
1858 ; operand.
1859 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1860 (set (match_dup 3) (const_int 0))]
1861 "
1862 {
1863 operands[3] = gen_highpart (SImode, operands[0]);
1864 operands[0] = gen_lowpart (SImode, operands[0]);
1865 operands[1] = gen_lowpart (SImode, operands[1]);
1866 }"
5895f793
RE
1867 [(set_attr "length" "8")]
1868)
3a33f76f 1869
4cdb3ed4 1870(define_insn "*anddi_sesdi_di"
d5b7b3ae 1871 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
ff9940b0
RE
1872 (and:DI (sign_extend:DI
1873 (match_operand:SI 2 "s_register_operand" "r,r"))
d5b7b3ae 1874 (match_operand:DI 1 "s_register_operand" "?r,0")))]
5b3e6663 1875 "TARGET_32BIT"
6ab589e0 1876 "#"
d5b7b3ae
RE
1877 [(set_attr "length" "8")]
1878)
3a33f76f 1879
091426d3 1880(define_expand "andsi3"
d5b7b3ae 1881 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
1882 (and:SI (match_operand:SI 1 "s_register_operand" "")
1883 (match_operand:SI 2 "reg_or_int_operand" "")))]
d5b7b3ae 1884 "TARGET_EITHER"
091426d3 1885 "
5b3e6663 1886 if (TARGET_32BIT)
091426d3 1887 {
d5b7b3ae
RE
1888 if (GET_CODE (operands[2]) == CONST_INT)
1889 {
a406f566
MM
1890 arm_split_constant (AND, SImode, NULL_RTX,
1891 INTVAL (operands[2]), operands[0],
b3a13419 1892 operands[1], optimize && can_create_pseudo_p ());
d56993f2 1893
d5b7b3ae
RE
1894 DONE;
1895 }
091426d3 1896 }
5b3e6663 1897 else /* TARGET_THUMB1 */
d5b7b3ae
RE
1898 {
1899 if (GET_CODE (operands[2]) != CONST_INT)
1900 operands[2] = force_reg (SImode, operands[2]);
1901 else
1902 {
1903 int i;
1904
5895f793 1905 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
d5b7b3ae 1906 {
5895f793
RE
1907 operands[2] = force_reg (SImode,
1908 GEN_INT (~INTVAL (operands[2])));
d5b7b3ae
RE
1909
1910 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1911
1912 DONE;
1913 }
091426d3 1914
d5b7b3ae
RE
1915 for (i = 9; i <= 31; i++)
1916 {
1917 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1918 {
1919 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1920 const0_rtx));
1921 DONE;
1922 }
5895f793
RE
1923 else if ((((HOST_WIDE_INT) 1) << i) - 1
1924 == ~INTVAL (operands[2]))
d5b7b3ae
RE
1925 {
1926 rtx shift = GEN_INT (i);
1927 rtx reg = gen_reg_rtx (SImode);
1928
1929 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1930 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1931
1932 DONE;
1933 }
1934 }
1935
1936 operands[2] = force_reg (SImode, operands[2]);
1937 }
5895f793
RE
1938 }
1939 "
d5b7b3ae
RE
1940)
1941
5b3e6663 1942; ??? Check split length for Thumb-2
bb6ae783 1943(define_insn_and_split "*arm_andsi3_insn"
d5b7b3ae 1944 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
091426d3
RE
1945 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1946 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
5b3e6663 1947 "TARGET_32BIT"
68df59d3
RE
1948 "@
1949 and%?\\t%0, %1, %2
091426d3
RE
1950 bic%?\\t%0, %1, #%B2
1951 #"
5b3e6663 1952 "TARGET_32BIT
bb6ae783
RE
1953 && GET_CODE (operands[2]) == CONST_INT
1954 && !(const_ok_for_arm (INTVAL (operands[2]))
1955 || const_ok_for_arm (~INTVAL (operands[2])))"
1956 [(clobber (const_int 0))]
1957 "
a406f566
MM
1958 arm_split_constant (AND, SImode, curr_insn,
1959 INTVAL (operands[2]), operands[0], operands[1], 0);
bb6ae783
RE
1960 DONE;
1961 "
cca0a211
RE
1962 [(set_attr "length" "4,4,16")
1963 (set_attr "predicable" "yes")]
d5b7b3ae
RE
1964)
1965
5b3e6663 1966(define_insn "*thumb1_andsi3_insn"
d5b7b3ae
RE
1967 [(set (match_operand:SI 0 "register_operand" "=l")
1968 (and:SI (match_operand:SI 1 "register_operand" "%0")
1969 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 1970 "TARGET_THUMB1"
d5b7b3ae
RE
1971 "and\\t%0, %0, %2"
1972 [(set_attr "length" "2")]
1973)
091426d3 1974
4cdb3ed4 1975(define_insn "*andsi3_compare0"
48a08b9c 1976 [(set (reg:CC_NOOV CC_REGNUM)
68df59d3
RE
1977 (compare:CC_NOOV
1978 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1979 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1980 (const_int 0)))
d5b7b3ae 1981 (set (match_operand:SI 0 "s_register_operand" "=r,r")
ff9940b0 1982 (and:SI (match_dup 1) (match_dup 2)))]
5b3e6663 1983 "TARGET_32BIT"
68df59d3 1984 "@
5b3e6663
PB
1985 and%.\\t%0, %1, %2
1986 bic%.\\t%0, %1, #%B2"
d5b7b3ae
RE
1987 [(set_attr "conds" "set")]
1988)
ff9940b0 1989
4cdb3ed4 1990(define_insn "*andsi3_compare0_scratch"
48a08b9c 1991 [(set (reg:CC_NOOV CC_REGNUM)
68df59d3
RE
1992 (compare:CC_NOOV
1993 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1994 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1995 (const_int 0)))
c77e04ae 1996 (clobber (match_scratch:SI 2 "=X,r"))]
5b3e6663 1997 "TARGET_32BIT"
68df59d3
RE
1998 "@
1999 tst%?\\t%0, %1
5b3e6663 2000 bic%.\\t%2, %0, #%B1"
cca0a211
RE
2001 [(set_attr "conds" "set")]
2002)
ff9940b0 2003
4cdb3ed4 2004(define_insn "*zeroextractsi_compare0_scratch"
48a08b9c 2005 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
2006 (compare:CC_NOOV (zero_extract:SI
2007 (match_operand:SI 0 "s_register_operand" "r")
0502226c
RE
2008 (match_operand 1 "const_int_operand" "n")
2009 (match_operand 2 "const_int_operand" "n"))
ff9940b0 2010 (const_int 0)))]
5b3e6663 2011 "TARGET_32BIT
d5b7b3ae
RE
2012 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2013 && INTVAL (operands[1]) > 0
2014 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2015 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
ff9940b0 2016 "*
d2ceebd1
RE
2017 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2018 << INTVAL (operands[2]));
c63165be 2019 output_asm_insn (\"tst%?\\t%0, %1\", operands);
0f447ef2 2020 return \"\";
cca0a211
RE
2021 "
2022 [(set_attr "conds" "set")]
2023)
ff9940b0 2024
2a2789d8 2025(define_insn_and_split "*ne_zeroextractsi"
dfa08768
RE
2026 [(set (match_operand:SI 0 "s_register_operand" "=r")
2027 (ne:SI (zero_extract:SI
2028 (match_operand:SI 1 "s_register_operand" "r")
2029 (match_operand:SI 2 "const_int_operand" "n")
2030 (match_operand:SI 3 "const_int_operand" "n"))
872e50d3
RE
2031 (const_int 0)))
2032 (clobber (reg:CC CC_REGNUM))]
5b3e6663 2033 "TARGET_32BIT
d5b7b3ae
RE
2034 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2035 && INTVAL (operands[2]) > 0
2036 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2037 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2a2789d8 2038 "#"
5b3e6663 2039 "TARGET_32BIT
2a2789d8
RE
2040 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2041 && INTVAL (operands[2]) > 0
2042 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2043 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2044 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2045 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2046 (const_int 0)))
2047 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2048 (set (match_dup 0)
2049 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2050 (match_dup 0) (const_int 1)))]
2051 "
2052 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2053 << INTVAL (operands[3]));
2054 "
2055 [(set_attr "conds" "clob")
5b3e6663
PB
2056 (set (attr "length")
2057 (if_then_else (eq_attr "is_thumb" "yes")
2058 (const_int 12)
2059 (const_int 8)))]
2a2789d8
RE
2060)
2061
2062(define_insn_and_split "*ne_zeroextractsi_shifted"
2063 [(set (match_operand:SI 0 "s_register_operand" "=r")
2064 (ne:SI (zero_extract:SI
2065 (match_operand:SI 1 "s_register_operand" "r")
2066 (match_operand:SI 2 "const_int_operand" "n")
2067 (const_int 0))
2068 (const_int 0)))
2069 (clobber (reg:CC CC_REGNUM))]
2070 "TARGET_ARM"
2071 "#"
2072 "TARGET_ARM"
2073 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2074 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2075 (const_int 0)))
2076 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2077 (set (match_dup 0)
2078 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2079 (match_dup 0) (const_int 1)))]
2080 "
2081 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2082 "
2083 [(set_attr "conds" "clob")
2084 (set_attr "length" "8")]
2085)
2086
2087(define_insn_and_split "*ite_ne_zeroextractsi"
2088 [(set (match_operand:SI 0 "s_register_operand" "=r")
2089 (if_then_else:SI (ne (zero_extract:SI
2090 (match_operand:SI 1 "s_register_operand" "r")
2091 (match_operand:SI 2 "const_int_operand" "n")
2092 (match_operand:SI 3 "const_int_operand" "n"))
2093 (const_int 0))
2094 (match_operand:SI 4 "arm_not_operand" "rIK")
2095 (const_int 0)))
2096 (clobber (reg:CC CC_REGNUM))]
2097 "TARGET_ARM
2098 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2099 && INTVAL (operands[2]) > 0
2100 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
69260355
RE
2101 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2102 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2a2789d8
RE
2103 "#"
2104 "TARGET_ARM
2105 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2106 && INTVAL (operands[2]) > 0
2107 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
69260355
RE
2108 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2109 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2a2789d8
RE
2110 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2111 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2112 (const_int 0)))
2113 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2114 (set (match_dup 0)
2115 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2116 (match_dup 0) (match_dup 4)))]
2117 "
dfa08768 2118 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2a2789d8
RE
2119 << INTVAL (operands[3]));
2120 "
2121 [(set_attr "conds" "clob")
2122 (set_attr "length" "8")]
2123)
2124
2125(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2126 [(set (match_operand:SI 0 "s_register_operand" "=r")
2127 (if_then_else:SI (ne (zero_extract:SI
2128 (match_operand:SI 1 "s_register_operand" "r")
2129 (match_operand:SI 2 "const_int_operand" "n")
2130 (const_int 0))
2131 (const_int 0))
2132 (match_operand:SI 3 "arm_not_operand" "rIK")
2133 (const_int 0)))
2134 (clobber (reg:CC CC_REGNUM))]
69260355 2135 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2a2789d8 2136 "#"
69260355 2137 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2a2789d8
RE
2138 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2139 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2140 (const_int 0)))
2141 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2142 (set (match_dup 0)
2143 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2144 (match_dup 0) (match_dup 3)))]
2145 "
2146 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
cca0a211
RE
2147 "
2148 [(set_attr "conds" "clob")
5895f793
RE
2149 (set_attr "length" "8")]
2150)
ff9940b0 2151
defc0463
RE
2152(define_split
2153 [(set (match_operand:SI 0 "s_register_operand" "")
2154 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2155 (match_operand:SI 2 "const_int_operand" "")
2156 (match_operand:SI 3 "const_int_operand" "")))
2157 (clobber (match_operand:SI 4 "s_register_operand" ""))]
5b3e6663 2158 "TARGET_THUMB1"
defc0463
RE
2159 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2160 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2161 "{
2162 HOST_WIDE_INT temp = INTVAL (operands[2]);
2163
2164 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2165 operands[3] = GEN_INT (32 - temp);
2166 }"
2167)
2168
5b3e6663 2169;; ??? Use Thumb-2 has bitfield insert/extract instructions.
da5cafa7
RE
2170(define_split
2171 [(set (match_operand:SI 0 "s_register_operand" "")
2172 (match_operator:SI 1 "shiftable_operator"
2173 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2174 (match_operand:SI 3 "const_int_operand" "")
2175 (match_operand:SI 4 "const_int_operand" ""))
2176 (match_operand:SI 5 "s_register_operand" "")]))
2177 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2178 "TARGET_ARM"
2179 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2180 (set (match_dup 0)
2181 (match_op_dup 1
2182 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2183 (match_dup 5)]))]
2184 "{
2185 HOST_WIDE_INT temp = INTVAL (operands[3]);
2186
2187 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2188 operands[4] = GEN_INT (32 - temp);
2189 }"
2190)
2191
defc0463
RE
2192(define_split
2193 [(set (match_operand:SI 0 "s_register_operand" "")
2194 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2195 (match_operand:SI 2 "const_int_operand" "")
2196 (match_operand:SI 3 "const_int_operand" "")))]
5b3e6663 2197 "TARGET_THUMB1"
defc0463
RE
2198 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2199 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2200 "{
2201 HOST_WIDE_INT temp = INTVAL (operands[2]);
2202
2203 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2204 operands[3] = GEN_INT (32 - temp);
2205 }"
2206)
2207
da5cafa7
RE
2208(define_split
2209 [(set (match_operand:SI 0 "s_register_operand" "")
2210 (match_operator:SI 1 "shiftable_operator"
2211 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2212 (match_operand:SI 3 "const_int_operand" "")
2213 (match_operand:SI 4 "const_int_operand" ""))
2214 (match_operand:SI 5 "s_register_operand" "")]))
2215 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2216 "TARGET_ARM"
2217 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2218 (set (match_dup 0)
2219 (match_op_dup 1
2220 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2221 (match_dup 5)]))]
2222 "{
2223 HOST_WIDE_INT temp = INTVAL (operands[3]);
2224
2225 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2226 operands[4] = GEN_INT (32 - temp);
2227 }"
2228)
2229
da959950
NC
2230;;; ??? This pattern is bogus. If operand3 has bits outside the range
2231;;; represented by the bitfield, then this will produce incorrect results.
2232;;; Somewhere, the value needs to be truncated. On targets like the m68k,
43a88a8c
KH
2233;;; which have a real bit-field insert instruction, the truncation happens
2234;;; in the bit-field insert instruction itself. Since arm does not have a
2235;;; bit-field insert instruction, we would have to emit code here to truncate
da959950
NC
2236;;; the value before we insert. This loses some of the advantage of having
2237;;; this insv pattern, so this pattern needs to be reevalutated.
2238
f54fd62e
RE
2239(define_expand "insv"
2240 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2241 (match_operand:SI 1 "general_operand" "")
2242 (match_operand:SI 2 "general_operand" ""))
7730c3ff 2243 (match_operand:SI 3 "reg_or_int_operand" ""))]
ef87d898 2244 "TARGET_ARM || arm_arch_thumb2"
f54fd62e 2245 "
5895f793
RE
2246 {
2247 int start_bit = INTVAL (operands[2]);
2248 int width = INTVAL (operands[1]);
2249 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2250 rtx target, subtarget;
2251
ef87d898
PB
2252 if (arm_arch_thumb2)
2253 {
2254 bool use_bfi = TRUE;
2255
2256 if (GET_CODE (operands[3]) == CONST_INT)
2257 {
2258 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2259
2260 if (val == 0)
2261 {
2262 emit_insn (gen_insv_zero (operands[0], operands[1],
2263 operands[2]));
2264 DONE;
2265 }
2266
2267 /* See if the set can be done with a single orr instruction. */
2268 if (val == mask && const_ok_for_arm (val << start_bit))
2269 use_bfi = FALSE;
2270 }
2271
2272 if (use_bfi)
2273 {
2274 if (GET_CODE (operands[3]) != REG)
2275 operands[3] = force_reg (SImode, operands[3]);
2276
2277 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2278 operands[3]));
2279 DONE;
2280 }
2281 }
2282
ee93c1c6 2283 target = copy_rtx (operands[0]);
5895f793
RE
2284 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2285 subreg as the final target. */
2286 if (GET_CODE (target) == SUBREG)
2287 {
2288 subtarget = gen_reg_rtx (SImode);
2289 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2290 < GET_MODE_SIZE (SImode))
2291 target = SUBREG_REG (target);
2292 }
2293 else
2294 subtarget = target;
f54fd62e 2295
5895f793
RE
2296 if (GET_CODE (operands[3]) == CONST_INT)
2297 {
2298 /* Since we are inserting a known constant, we may be able to
2299 reduce the number of bits that we have to clear so that
2300 the mask becomes simple. */
2301 /* ??? This code does not check to see if the new mask is actually
2302 simpler. It may not be. */
2303 rtx op1 = gen_reg_rtx (SImode);
2304 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2305 start of this pattern. */
2306 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2307 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2308
c2540bbb
DJ
2309 emit_insn (gen_andsi3 (op1, operands[0],
2310 gen_int_mode (~mask2, SImode)));
5895f793 2311 emit_insn (gen_iorsi3 (subtarget, op1,
b65e6318 2312 gen_int_mode (op3_value << start_bit, SImode)));
5895f793
RE
2313 }
2314 else if (start_bit == 0
2315 && !(const_ok_for_arm (mask)
2316 || const_ok_for_arm (~mask)))
2317 {
2318 /* A Trick, since we are setting the bottom bits in the word,
2319 we can shift operand[3] up, operand[0] down, OR them together
2320 and rotate the result back again. This takes 3 insns, and
093354e0 2321 the third might be mergeable into another op. */
5895f793
RE
2322 /* The shift up copes with the possibility that operand[3] is
2323 wider than the bitfield. */
2324 rtx op0 = gen_reg_rtx (SImode);
2325 rtx op1 = gen_reg_rtx (SImode);
2326
2327 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2328 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2329 emit_insn (gen_iorsi3 (op1, op1, op0));
2330 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2331 }
2332 else if ((width + start_bit == 32)
2333 && !(const_ok_for_arm (mask)
2334 || const_ok_for_arm (~mask)))
2335 {
2336 /* Similar trick, but slightly less efficient. */
f54fd62e 2337
5895f793
RE
2338 rtx op0 = gen_reg_rtx (SImode);
2339 rtx op1 = gen_reg_rtx (SImode);
f54fd62e 2340
5895f793
RE
2341 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2342 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2343 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2344 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2345 }
2346 else
2347 {
c2540bbb 2348 rtx op0 = gen_int_mode (mask, SImode);
5895f793
RE
2349 rtx op1 = gen_reg_rtx (SImode);
2350 rtx op2 = gen_reg_rtx (SImode);
f54fd62e 2351
5895f793
RE
2352 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2353 {
2354 rtx tmp = gen_reg_rtx (SImode);
f54fd62e 2355
5895f793
RE
2356 emit_insn (gen_movsi (tmp, op0));
2357 op0 = tmp;
2358 }
f54fd62e 2359
5895f793
RE
2360 /* Mask out any bits in operand[3] that are not needed. */
2361 emit_insn (gen_andsi3 (op1, operands[3], op0));
f54fd62e 2362
5895f793
RE
2363 if (GET_CODE (op0) == CONST_INT
2364 && (const_ok_for_arm (mask << start_bit)
2365 || const_ok_for_arm (~(mask << start_bit))))
2366 {
c2540bbb 2367 op0 = gen_int_mode (~(mask << start_bit), SImode);
5895f793
RE
2368 emit_insn (gen_andsi3 (op2, operands[0], op0));
2369 }
2370 else
2371 {
2372 if (GET_CODE (op0) == CONST_INT)
2373 {
2374 rtx tmp = gen_reg_rtx (SImode);
f54fd62e 2375
5895f793
RE
2376 emit_insn (gen_movsi (tmp, op0));
2377 op0 = tmp;
2378 }
2379
2380 if (start_bit != 0)
2381 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
da959950 2382
5895f793
RE
2383 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2384 }
f54fd62e 2385
5895f793
RE
2386 if (start_bit != 0)
2387 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
f54fd62e 2388
5895f793
RE
2389 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2390 }
7a0a1f09 2391
5895f793
RE
2392 if (subtarget != target)
2393 {
2394 /* If TARGET is still a SUBREG, then it must be wider than a word,
2395 so we must be careful only to set the subword we were asked to. */
2396 if (GET_CODE (target) == SUBREG)
2397 emit_move_insn (target, subtarget);
2398 else
2399 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2400 }
f54fd62e 2401
5895f793
RE
2402 DONE;
2403 }"
2404)
f54fd62e 2405
ef87d898
PB
2406(define_insn "insv_zero"
2407 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2408 (match_operand:SI 1 "const_int_operand" "M")
2409 (match_operand:SI 2 "const_int_operand" "M"))
2410 (const_int 0))]
2411 "arm_arch_thumb2"
2412 "bfc%?\t%0, %2, %1"
2413 [(set_attr "length" "4")
2414 (set_attr "predicable" "yes")]
2415)
2416
2417(define_insn "insv_t2"
2418 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2419 (match_operand:SI 1 "const_int_operand" "M")
2420 (match_operand:SI 2 "const_int_operand" "M"))
2421 (match_operand:SI 3 "s_register_operand" "r"))]
2422 "arm_arch_thumb2"
2423 "bfi%?\t%0, %3, %2, %1"
2424 [(set_attr "length" "4")
2425 (set_attr "predicable" "yes")]
2426)
2427
5895f793 2428; constants for op 2 will never be given to these patterns.
bb6ae783 2429(define_insn_and_split "*anddi_notdi_di"
ff9940b0 2430 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
bb6ae783
RE
2431 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2432 (match_operand:DI 2 "s_register_operand" "0,r")))]
5b3e6663 2433 "TARGET_32BIT"
6ab589e0 2434 "#"
5b3e6663 2435 "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
bb6ae783
RE
2436 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2437 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2438 "
2439 {
2440 operands[3] = gen_highpart (SImode, operands[0]);
2441 operands[0] = gen_lowpart (SImode, operands[0]);
2442 operands[4] = gen_highpart (SImode, operands[1]);
2443 operands[1] = gen_lowpart (SImode, operands[1]);
2444 operands[5] = gen_highpart (SImode, operands[2]);
2445 operands[2] = gen_lowpart (SImode, operands[2]);
2446 }"
cca0a211
RE
2447 [(set_attr "length" "8")
2448 (set_attr "predicable" "yes")]
2449)
ff9940b0 2450
bb6ae783 2451(define_insn_and_split "*anddi_notzesidi_di"
ff9940b0
RE
2452 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2453 (and:DI (not:DI (zero_extend:DI
2454 (match_operand:SI 2 "s_register_operand" "r,r")))
0f447ef2 2455 (match_operand:DI 1 "s_register_operand" "0,?r")))]
5b3e6663 2456 "TARGET_32BIT"
0f447ef2 2457 "@
3dafc5c3 2458 bic%?\\t%Q0, %Q1, %2
6ab589e0 2459 #"
bb6ae783
RE
2460 ; (not (zero_extend ...)) allows us to just copy the high word from
2461 ; operand1 to operand0.
5b3e6663 2462 "TARGET_32BIT
bb6ae783
RE
2463 && reload_completed
2464 && operands[0] != operands[1]"
1dda7ee4 2465 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
bb6ae783
RE
2466 (set (match_dup 3) (match_dup 4))]
2467 "
2468 {
2469 operands[3] = gen_highpart (SImode, operands[0]);
2470 operands[0] = gen_lowpart (SImode, operands[0]);
2471 operands[4] = gen_highpart (SImode, operands[1]);
2472 operands[1] = gen_lowpart (SImode, operands[1]);
2473 }"
cca0a211
RE
2474 [(set_attr "length" "4,8")
2475 (set_attr "predicable" "yes")]
2476)
ff9940b0 2477
bb6ae783 2478(define_insn_and_split "*anddi_notsesidi_di"
ff9940b0
RE
2479 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2480 (and:DI (not:DI (sign_extend:DI
2481 (match_operand:SI 2 "s_register_operand" "r,r")))
1dda7ee4 2482 (match_operand:DI 1 "s_register_operand" "0,r")))]
5b3e6663 2483 "TARGET_32BIT"
6ab589e0 2484 "#"
5b3e6663 2485 "TARGET_32BIT && reload_completed"
1dda7ee4 2486 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
bb6ae783
RE
2487 (set (match_dup 3) (and:SI (not:SI
2488 (ashiftrt:SI (match_dup 2) (const_int 31)))
2489 (match_dup 4)))]
2490 "
2491 {
2492 operands[3] = gen_highpart (SImode, operands[0]);
2493 operands[0] = gen_lowpart (SImode, operands[0]);
2494 operands[4] = gen_highpart (SImode, operands[1]);
2495 operands[1] = gen_lowpart (SImode, operands[1]);
2496 }"
cca0a211
RE
2497 [(set_attr "length" "8")
2498 (set_attr "predicable" "yes")]
2499)
ff9940b0 2500
f54fd62e 2501(define_insn "andsi_notsi_si"
ff9940b0
RE
2502 [(set (match_operand:SI 0 "s_register_operand" "=r")
2503 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2504 (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 2505 "TARGET_32BIT"
cca0a211
RE
2506 "bic%?\\t%0, %1, %2"
2507 [(set_attr "predicable" "yes")]
2508)
3a33f76f 2509
d5b7b3ae
RE
2510(define_insn "bicsi3"
2511 [(set (match_operand:SI 0 "register_operand" "=l")
2512 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2513 (match_operand:SI 2 "register_operand" "0")))]
5b3e6663 2514 "TARGET_THUMB1"
d5b7b3ae
RE
2515 "bic\\t%0, %0, %1"
2516 [(set_attr "length" "2")]
2517)
2518
f54fd62e 2519(define_insn "andsi_not_shiftsi_si"
9b66ebb1
PB
2520 [(set (match_operand:SI 0 "s_register_operand" "=r")
2521 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2522 [(match_operand:SI 2 "s_register_operand" "r")
2523 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2524 (match_operand:SI 1 "s_register_operand" "r")))]
d5b7b3ae 2525 "TARGET_ARM"
b020fd92 2526 "bic%?\\t%0, %1, %2%S4"
ca68ea18 2527 [(set_attr "predicable" "yes")
d19fb8e3 2528 (set_attr "shift" "2")
9b66ebb1
PB
2529 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2530 (const_string "alu_shift")
2531 (const_string "alu_shift_reg")))]
b020fd92 2532)
f54fd62e 2533
4cdb3ed4 2534(define_insn "*andsi_notsi_si_compare0"
48a08b9c 2535 [(set (reg:CC_NOOV CC_REGNUM)
0f447ef2
RE
2536 (compare:CC_NOOV
2537 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2538 (match_operand:SI 1 "s_register_operand" "r"))
2539 (const_int 0)))
ff9940b0
RE
2540 (set (match_operand:SI 0 "s_register_operand" "=r")
2541 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
5b3e6663
PB
2542 "TARGET_32BIT"
2543 "bic%.\\t%0, %1, %2"
cca0a211
RE
2544 [(set_attr "conds" "set")]
2545)
ff9940b0 2546
4cdb3ed4 2547(define_insn "*andsi_notsi_si_compare0_scratch"
48a08b9c 2548 [(set (reg:CC_NOOV CC_REGNUM)
0f447ef2
RE
2549 (compare:CC_NOOV
2550 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2551 (match_operand:SI 1 "s_register_operand" "r"))
2552 (const_int 0)))
ff9940b0 2553 (clobber (match_scratch:SI 0 "=r"))]
5b3e6663
PB
2554 "TARGET_32BIT"
2555 "bic%.\\t%0, %1, %2"
cca0a211
RE
2556 [(set_attr "conds" "set")]
2557)
ff9940b0
RE
2558
2559(define_insn "iordi3"
d5b7b3ae
RE
2560 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2561 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2562 (match_operand:DI 2 "s_register_operand" "r,r")))]
5b3e6663 2563 "TARGET_32BIT && ! TARGET_IWMMXT"
6ab589e0 2564 "#"
cca0a211
RE
2565 [(set_attr "length" "8")
2566 (set_attr "predicable" "yes")]
d5b7b3ae 2567)
ff9940b0 2568
4cdb3ed4 2569(define_insn "*iordi_zesidi_di"
ff9940b0
RE
2570 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2571 (ior:DI (zero_extend:DI
2572 (match_operand:SI 2 "s_register_operand" "r,r"))
0f447ef2 2573 (match_operand:DI 1 "s_register_operand" "0,?r")))]
5b3e6663 2574 "TARGET_32BIT"
0f447ef2 2575 "@
3dafc5c3 2576 orr%?\\t%Q0, %Q1, %2
6ab589e0 2577 #"
cca0a211
RE
2578 [(set_attr "length" "4,8")
2579 (set_attr "predicable" "yes")]
d5b7b3ae 2580)
ff9940b0 2581
4cdb3ed4 2582(define_insn "*iordi_sesidi_di"
ff9940b0
RE
2583 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2584 (ior:DI (sign_extend:DI
2585 (match_operand:SI 2 "s_register_operand" "r,r"))
2586 (match_operand:DI 1 "s_register_operand" "?r,0")))]
5b3e6663 2587 "TARGET_32BIT"
6ab589e0 2588 "#"
cca0a211
RE
2589 [(set_attr "length" "8")
2590 (set_attr "predicable" "yes")]
d5b7b3ae 2591)
ff9940b0 2592
091426d3 2593(define_expand "iorsi3"
d5b7b3ae 2594 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
2595 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2596 (match_operand:SI 2 "reg_or_int_operand" "")))]
d5b7b3ae 2597 "TARGET_EITHER"
091426d3
RE
2598 "
2599 if (GET_CODE (operands[2]) == CONST_INT)
2600 {
5b3e6663 2601 if (TARGET_32BIT)
d5b7b3ae 2602 {
a406f566
MM
2603 arm_split_constant (IOR, SImode, NULL_RTX,
2604 INTVAL (operands[2]), operands[0], operands[1],
b3a13419 2605 optimize && can_create_pseudo_p ());
d5b7b3ae
RE
2606 DONE;
2607 }
5b3e6663 2608 else /* TARGET_THUMB1 */
d5b7b3ae 2609 operands [2] = force_reg (SImode, operands [2]);
091426d3 2610 }
d5b7b3ae
RE
2611 "
2612)
091426d3 2613
bb6ae783 2614(define_insn_and_split "*arm_iorsi3"
d5b7b3ae 2615 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
091426d3
RE
2616 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2617 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
5b3e6663 2618 "TARGET_32BIT"
091426d3
RE
2619 "@
2620 orr%?\\t%0, %1, %2
2621 #"
5b3e6663 2622 "TARGET_32BIT
bb6ae783
RE
2623 && GET_CODE (operands[2]) == CONST_INT
2624 && !const_ok_for_arm (INTVAL (operands[2]))"
2625 [(clobber (const_int 0))]
2626 "
a406f566
MM
2627 arm_split_constant (IOR, SImode, curr_insn,
2628 INTVAL (operands[2]), operands[0], operands[1], 0);
bb6ae783
RE
2629 DONE;
2630 "
cca0a211
RE
2631 [(set_attr "length" "4,16")
2632 (set_attr "predicable" "yes")]
d5b7b3ae
RE
2633)
2634
5b3e6663 2635(define_insn "*thumb1_iorsi3"
d5b7b3ae
RE
2636 [(set (match_operand:SI 0 "register_operand" "=l")
2637 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2638 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 2639 "TARGET_THUMB1"
d5b7b3ae
RE
2640 "orr\\t%0, %0, %2"
2641 [(set_attr "length" "2")]
2642)
ff9940b0 2643
bb6ae783
RE
2644(define_peephole2
2645 [(match_scratch:SI 3 "r")
3053b100
RE
2646 (set (match_operand:SI 0 "arm_general_register_operand" "")
2647 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
091426d3 2648 (match_operand:SI 2 "const_int_operand" "")))]
5b3e6663 2649 "TARGET_32BIT
bb6ae783
RE
2650 && !const_ok_for_arm (INTVAL (operands[2]))
2651 && const_ok_for_arm (~INTVAL (operands[2]))"
2652 [(set (match_dup 3) (match_dup 2))
2653 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2654 ""
5895f793 2655)
bb6ae783 2656
4cdb3ed4 2657(define_insn "*iorsi3_compare0"
48a08b9c 2658 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
2659 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2660 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2661 (const_int 0)))
2662 (set (match_operand:SI 0 "s_register_operand" "=r")
2663 (ior:SI (match_dup 1) (match_dup 2)))]
5b3e6663
PB
2664 "TARGET_32BIT"
2665 "orr%.\\t%0, %1, %2"
d5b7b3ae
RE
2666 [(set_attr "conds" "set")]
2667)
ff9940b0 2668
4cdb3ed4 2669(define_insn "*iorsi3_compare0_scratch"
48a08b9c 2670 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
2671 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2672 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2673 (const_int 0)))
2674 (clobber (match_scratch:SI 0 "=r"))]
5b3e6663
PB
2675 "TARGET_32BIT"
2676 "orr%.\\t%0, %1, %2"
cca0a211
RE
2677 [(set_attr "conds" "set")]
2678)
ff9940b0
RE
2679
2680(define_insn "xordi3"
d5b7b3ae
RE
2681 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2682 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2683 (match_operand:DI 2 "s_register_operand" "r,r")))]
5b3e6663 2684 "TARGET_32BIT && !TARGET_IWMMXT"
6ab589e0 2685 "#"
cca0a211
RE
2686 [(set_attr "length" "8")
2687 (set_attr "predicable" "yes")]
d5b7b3ae 2688)
ff9940b0 2689
4cdb3ed4 2690(define_insn "*xordi_zesidi_di"
ff9940b0
RE
2691 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2692 (xor:DI (zero_extend:DI
2693 (match_operand:SI 2 "s_register_operand" "r,r"))
0f447ef2 2694 (match_operand:DI 1 "s_register_operand" "0,?r")))]
5b3e6663 2695 "TARGET_32BIT"
0f447ef2 2696 "@
3dafc5c3 2697 eor%?\\t%Q0, %Q1, %2
6ab589e0 2698 #"
cca0a211
RE
2699 [(set_attr "length" "4,8")
2700 (set_attr "predicable" "yes")]
d5b7b3ae 2701)
ff9940b0 2702
4cdb3ed4 2703(define_insn "*xordi_sesidi_di"
ff9940b0
RE
2704 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2705 (xor:DI (sign_extend:DI
2706 (match_operand:SI 2 "s_register_operand" "r,r"))
2707 (match_operand:DI 1 "s_register_operand" "?r,0")))]
5b3e6663 2708 "TARGET_32BIT"
6ab589e0 2709 "#"
cca0a211
RE
2710 [(set_attr "length" "8")
2711 (set_attr "predicable" "yes")]
d5b7b3ae 2712)
ff9940b0 2713
d5b7b3ae
RE
2714(define_expand "xorsi3"
2715 [(set (match_operand:SI 0 "s_register_operand" "")
2716 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2717 (match_operand:SI 2 "arm_rhs_operand" "")))]
2718 "TARGET_EITHER"
5b3e6663 2719 "if (TARGET_THUMB1)
d5b7b3ae
RE
2720 if (GET_CODE (operands[2]) == CONST_INT)
2721 operands[2] = force_reg (SImode, operands[2]);
2722 "
2723)
2724
2725(define_insn "*arm_xorsi3"
2726 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff9940b0
RE
2727 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2728 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
5b3e6663 2729 "TARGET_32BIT"
d5b7b3ae 2730 "eor%?\\t%0, %1, %2"
cca0a211 2731 [(set_attr "predicable" "yes")]
d5b7b3ae
RE
2732)
2733
5b3e6663 2734(define_insn "*thumb1_xorsi3"
d5b7b3ae
RE
2735 [(set (match_operand:SI 0 "register_operand" "=l")
2736 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2737 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 2738 "TARGET_THUMB1"
d5b7b3ae
RE
2739 "eor\\t%0, %0, %2"
2740 [(set_attr "length" "2")]
2741)
ff9940b0 2742
4cdb3ed4 2743(define_insn "*xorsi3_compare0"
48a08b9c 2744 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
2745 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2746 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2747 (const_int 0)))
2748 (set (match_operand:SI 0 "s_register_operand" "=r")
2749 (xor:SI (match_dup 1) (match_dup 2)))]
5b3e6663
PB
2750 "TARGET_32BIT"
2751 "eor%.\\t%0, %1, %2"
cca0a211
RE
2752 [(set_attr "conds" "set")]
2753)
ff9940b0 2754
4cdb3ed4 2755(define_insn "*xorsi3_compare0_scratch"
48a08b9c 2756 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
2757 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2758 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2759 (const_int 0)))]
5b3e6663 2760 "TARGET_32BIT"
c63165be 2761 "teq%?\\t%0, %1"
d5b7b3ae
RE
2762 [(set_attr "conds" "set")]
2763)
ff9940b0 2764
5895f793
RE
2765; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2766; (NOT D) we can sometimes merge the final NOT into one of the following
2767; insns.
ff9940b0
RE
2768
2769(define_split
12249385
RE
2770 [(set (match_operand:SI 0 "s_register_operand" "")
2771 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2772 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2773 (match_operand:SI 3 "arm_rhs_operand" "")))
2774 (clobber (match_operand:SI 4 "s_register_operand" ""))]
5b3e6663 2775 "TARGET_32BIT"
ff9940b0
RE
2776 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2777 (not:SI (match_dup 3))))
2778 (set (match_dup 0) (not:SI (match_dup 4)))]
2779 ""
2780)
2781
4cdb3ed4 2782(define_insn "*andsi_iorsi3_notsi"
ff9940b0
RE
2783 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2784 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2785 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2786 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
5b3e6663 2787 "TARGET_32BIT"
c63165be 2788 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
cca0a211 2789 [(set_attr "length" "8")
5b3e6663 2790 (set_attr "ce_count" "2")
cca0a211 2791 (set_attr "predicable" "yes")]
d5b7b3ae 2792)
ff9940b0 2793
5b3e6663
PB
2794; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2795; insns are available?
da5cafa7
RE
2796(define_split
2797 [(set (match_operand:SI 0 "s_register_operand" "")
2798 (match_operator:SI 1 "logical_binary_operator"
2799 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2800 (match_operand:SI 3 "const_int_operand" "")
2801 (match_operand:SI 4 "const_int_operand" ""))
2802 (match_operator:SI 9 "logical_binary_operator"
2803 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2804 (match_operand:SI 6 "const_int_operand" ""))
2805 (match_operand:SI 7 "s_register_operand" "")])]))
2806 (clobber (match_operand:SI 8 "s_register_operand" ""))]
5b3e6663 2807 "TARGET_32BIT
da5cafa7
RE
2808 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2809 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2810 [(set (match_dup 8)
2811 (match_op_dup 1
2812 [(ashift:SI (match_dup 2) (match_dup 4))
2813 (match_dup 5)]))
2814 (set (match_dup 0)
2815 (match_op_dup 1
2816 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2817 (match_dup 7)]))]
2818 "
2819 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2820")
2821
2822(define_split
2823 [(set (match_operand:SI 0 "s_register_operand" "")
2824 (match_operator:SI 1 "logical_binary_operator"
2825 [(match_operator:SI 9 "logical_binary_operator"
2826 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2827 (match_operand:SI 6 "const_int_operand" ""))
2828 (match_operand:SI 7 "s_register_operand" "")])
2829 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2830 (match_operand:SI 3 "const_int_operand" "")
2831 (match_operand:SI 4 "const_int_operand" ""))]))
2832 (clobber (match_operand:SI 8 "s_register_operand" ""))]
5b3e6663 2833 "TARGET_32BIT
da5cafa7
RE
2834 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2835 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2836 [(set (match_dup 8)
2837 (match_op_dup 1
2838 [(ashift:SI (match_dup 2) (match_dup 4))
2839 (match_dup 5)]))
2840 (set (match_dup 0)
2841 (match_op_dup 1
2842 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2843 (match_dup 7)]))]
2844 "
2845 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2846")
2847
2848(define_split
2849 [(set (match_operand:SI 0 "s_register_operand" "")
2850 (match_operator:SI 1 "logical_binary_operator"
2851 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2852 (match_operand:SI 3 "const_int_operand" "")
2853 (match_operand:SI 4 "const_int_operand" ""))
2854 (match_operator:SI 9 "logical_binary_operator"
2855 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2856 (match_operand:SI 6 "const_int_operand" ""))
2857 (match_operand:SI 7 "s_register_operand" "")])]))
2858 (clobber (match_operand:SI 8 "s_register_operand" ""))]
5b3e6663 2859 "TARGET_32BIT
da5cafa7
RE
2860 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2861 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2862 [(set (match_dup 8)
2863 (match_op_dup 1
2864 [(ashift:SI (match_dup 2) (match_dup 4))
2865 (match_dup 5)]))
2866 (set (match_dup 0)
2867 (match_op_dup 1
2868 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2869 (match_dup 7)]))]
2870 "
2871 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2872")
2873
2874(define_split
2875 [(set (match_operand:SI 0 "s_register_operand" "")
2876 (match_operator:SI 1 "logical_binary_operator"
2877 [(match_operator:SI 9 "logical_binary_operator"
2878 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2879 (match_operand:SI 6 "const_int_operand" ""))
2880 (match_operand:SI 7 "s_register_operand" "")])
2881 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2882 (match_operand:SI 3 "const_int_operand" "")
2883 (match_operand:SI 4 "const_int_operand" ""))]))
2884 (clobber (match_operand:SI 8 "s_register_operand" ""))]
5b3e6663 2885 "TARGET_32BIT
da5cafa7
RE
2886 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2887 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2888 [(set (match_dup 8)
2889 (match_op_dup 1
2890 [(ashift:SI (match_dup 2) (match_dup 4))
2891 (match_dup 5)]))
2892 (set (match_dup 0)
2893 (match_op_dup 1
2894 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2895 (match_dup 7)]))]
2896 "
2897 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2898")
ff9940b0
RE
2899\f
2900
2901;; Minimum and maximum insns
2902
0a484e3e
RE
2903(define_expand "smaxsi3"
2904 [(parallel [
2905 (set (match_operand:SI 0 "s_register_operand" "")
2906 (smax:SI (match_operand:SI 1 "s_register_operand" "")
2907 (match_operand:SI 2 "arm_rhs_operand" "")))
2908 (clobber (reg:CC CC_REGNUM))])]
5b3e6663 2909 "TARGET_32BIT"
0a484e3e 2910 "
0cb381f0 2911 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
0a484e3e
RE
2912 {
2913 /* No need for a clobber of the condition code register here. */
2914 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2915 gen_rtx_SMAX (SImode, operands[1],
2916 operands[2])));
2917 DONE;
2918 }
2919")
2920
2921(define_insn "*smax_0"
2922 [(set (match_operand:SI 0 "s_register_operand" "=r")
2923 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2924 (const_int 0)))]
5b3e6663 2925 "TARGET_32BIT"
0a484e3e
RE
2926 "bic%?\\t%0, %1, %1, asr #31"
2927 [(set_attr "predicable" "yes")]
2928)
2929
0cb381f0
NP
2930(define_insn "*smax_m1"
2931 [(set (match_operand:SI 0 "s_register_operand" "=r")
2932 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2933 (const_int -1)))]
5b3e6663 2934 "TARGET_32BIT"
0cb381f0
NP
2935 "orr%?\\t%0, %1, %1, asr #31"
2936 [(set_attr "predicable" "yes")]
2937)
2938
5b3e6663 2939(define_insn "*arm_smax_insn"
0a484e3e
RE
2940 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2941 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2942 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
48a08b9c 2943 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 2944 "TARGET_ARM"
0f447ef2
RE
2945 "@
2946 cmp\\t%1, %2\;movlt\\t%0, %2
0f447ef2 2947 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
d5b7b3ae 2948 [(set_attr "conds" "clob")
0a484e3e 2949 (set_attr "length" "8,12")]
d5b7b3ae 2950)
ff9940b0 2951
0a484e3e
RE
2952(define_expand "sminsi3"
2953 [(parallel [
2954 (set (match_operand:SI 0 "s_register_operand" "")
2955 (smin:SI (match_operand:SI 1 "s_register_operand" "")
2956 (match_operand:SI 2 "arm_rhs_operand" "")))
2957 (clobber (reg:CC CC_REGNUM))])]
5b3e6663 2958 "TARGET_32BIT"
0a484e3e
RE
2959 "
2960 if (operands[2] == const0_rtx)
2961 {
2962 /* No need for a clobber of the condition code register here. */
2963 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2964 gen_rtx_SMIN (SImode, operands[1],
2965 operands[2])));
2966 DONE;
2967 }
2968")
2969
2970(define_insn "*smin_0"
2971 [(set (match_operand:SI 0 "s_register_operand" "=r")
2972 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2973 (const_int 0)))]
5b3e6663 2974 "TARGET_32BIT"
0a484e3e
RE
2975 "and%?\\t%0, %1, %1, asr #31"
2976 [(set_attr "predicable" "yes")]
2977)
2978
5b3e6663 2979(define_insn "*arm_smin_insn"
0a484e3e
RE
2980 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2981 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2982 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
48a08b9c 2983 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 2984 "TARGET_ARM"
0f447ef2
RE
2985 "@
2986 cmp\\t%1, %2\;movge\\t%0, %2
0f447ef2 2987 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
cca0a211 2988 [(set_attr "conds" "clob")
0a484e3e 2989 (set_attr "length" "8,12")]
cca0a211 2990)
ff9940b0 2991
5b3e6663
PB
2992(define_expand "umaxsi3"
2993 [(parallel [
2994 (set (match_operand:SI 0 "s_register_operand" "")
2995 (umax:SI (match_operand:SI 1 "s_register_operand" "")
2996 (match_operand:SI 2 "arm_rhs_operand" "")))
2997 (clobber (reg:CC CC_REGNUM))])]
2998 "TARGET_32BIT"
2999 ""
3000)
3001
3002(define_insn "*arm_umaxsi3"
ff9940b0
RE
3003 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3004 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3005 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
48a08b9c 3006 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3007 "TARGET_ARM"
0f447ef2
RE
3008 "@
3009 cmp\\t%1, %2\;movcc\\t%0, %2
3010 cmp\\t%1, %2\;movcs\\t%0, %1
3011 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
cca0a211
RE
3012 [(set_attr "conds" "clob")
3013 (set_attr "length" "8,8,12")]
3014)
ff9940b0 3015
5b3e6663
PB
3016(define_expand "uminsi3"
3017 [(parallel [
3018 (set (match_operand:SI 0 "s_register_operand" "")
3019 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3020 (match_operand:SI 2 "arm_rhs_operand" "")))
3021 (clobber (reg:CC CC_REGNUM))])]
3022 "TARGET_32BIT"
3023 ""
3024)
3025
3026(define_insn "*arm_uminsi3"
ff9940b0
RE
3027 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3028 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3029 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
48a08b9c 3030 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3031 "TARGET_ARM"
0f447ef2
RE
3032 "@
3033 cmp\\t%1, %2\;movcs\\t%0, %2
3034 cmp\\t%1, %2\;movcc\\t%0, %1
3035 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
cca0a211
RE
3036 [(set_attr "conds" "clob")
3037 (set_attr "length" "8,8,12")]
3038)
ff9940b0 3039
f54fd62e 3040(define_insn "*store_minmaxsi"
ff9940b0
RE
3041 [(set (match_operand:SI 0 "memory_operand" "=m")
3042 (match_operator:SI 3 "minmax_operator"
3043 [(match_operand:SI 1 "s_register_operand" "r")
3044 (match_operand:SI 2 "s_register_operand" "r")]))
48a08b9c 3045 (clobber (reg:CC CC_REGNUM))]
5b3e6663 3046 "TARGET_32BIT"
ff9940b0 3047 "*
0f4c242b
KH
3048 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3049 operands[1], operands[2]);
0f447ef2 3050 output_asm_insn (\"cmp\\t%1, %2\", operands);
5b3e6663
PB
3051 if (TARGET_THUMB2)
3052 output_asm_insn (\"ite\t%d3\", operands);
0f447ef2
RE
3053 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3054 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3055 return \"\";
cca0a211
RE
3056 "
3057 [(set_attr "conds" "clob")
5b3e6663
PB
3058 (set (attr "length")
3059 (if_then_else (eq_attr "is_thumb" "yes")
3060 (const_int 14)
3061 (const_int 12)))
cca0a211
RE
3062 (set_attr "type" "store1")]
3063)
ff9940b0 3064
f54fd62e
RE
3065; Reject the frame pointer in operand[1], since reloading this after
3066; it has been eliminated can cause carnage.
4cdb3ed4 3067(define_insn "*minmax_arithsi"
ff9940b0
RE
3068 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3069 (match_operator:SI 4 "shiftable_operator"
3070 [(match_operator:SI 5 "minmax_operator"
3071 [(match_operand:SI 2 "s_register_operand" "r,r")
3072 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3073 (match_operand:SI 1 "s_register_operand" "0,?r")]))
48a08b9c 3074 (clobber (reg:CC CC_REGNUM))]
5b3e6663 3075 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
ff9940b0 3076 "*
cca0a211
RE
3077 {
3078 enum rtx_code code = GET_CODE (operands[4]);
5b3e6663
PB
3079 bool need_else;
3080
3081 if (which_alternative != 0 || operands[3] != const0_rtx
3082 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3083 need_else = true;
3084 else
3085 need_else = false;
cca0a211 3086
0f4c242b
KH
3087 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3088 operands[2], operands[3]);
cca0a211 3089 output_asm_insn (\"cmp\\t%2, %3\", operands);
5b3e6663
PB
3090 if (TARGET_THUMB2)
3091 {
3092 if (need_else)
3093 output_asm_insn (\"ite\\t%d5\", operands);
3094 else
3095 output_asm_insn (\"it\\t%d5\", operands);
3096 }
cca0a211 3097 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
5b3e6663 3098 if (need_else)
cca0a211
RE
3099 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3100 return \"\";
5895f793 3101 }"
cca0a211 3102 [(set_attr "conds" "clob")
5b3e6663
PB
3103 (set (attr "length")
3104 (if_then_else (eq_attr "is_thumb" "yes")
3105 (const_int 14)
3106 (const_int 12)))]
cca0a211 3107)
ff9940b0 3108
3a33f76f
RK
3109\f
3110;; Shift and rotation insns
3111
9b66ebb1
PB
3112(define_expand "ashldi3"
3113 [(set (match_operand:DI 0 "s_register_operand" "")
3114 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3115 (match_operand:SI 2 "reg_or_int_operand" "")))]
5b3e6663 3116 "TARGET_32BIT"
9b66ebb1
PB
3117 "
3118 if (GET_CODE (operands[2]) == CONST_INT)
3119 {
3120 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3121 {
3122 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3123 DONE;
3124 }
3125 /* Ideally we shouldn't fail here if we could know that operands[1]
3126 ends up already living in an iwmmxt register. Otherwise it's
3127 cheaper to have the alternate code being generated than moving
ff482c8d 3128 values to iwmmxt regs and back. */
9b66ebb1
PB
3129 FAIL;
3130 }
3131 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3132 FAIL;
3133 "
3134)
3135
3136(define_insn "arm_ashldi3_1bit"
3137 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3138 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3139 (const_int 1)))
3140 (clobber (reg:CC CC_REGNUM))]
5b3e6663 3141 "TARGET_32BIT"
9b66ebb1
PB
3142 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3143 [(set_attr "conds" "clob")
3144 (set_attr "length" "8")]
3145)
3146
091426d3 3147(define_expand "ashlsi3"
d5b7b3ae 3148 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
3149 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3150 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 3151 "TARGET_EITHER"
091426d3
RE
3152 "
3153 if (GET_CODE (operands[2]) == CONST_INT
3154 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3155 {
3156 emit_insn (gen_movsi (operands[0], const0_rtx));
3157 DONE;
3158 }
d5b7b3ae
RE
3159 "
3160)
3161
5b3e6663 3162(define_insn "*thumb1_ashlsi3"
d5b7b3ae
RE
3163 [(set (match_operand:SI 0 "register_operand" "=l,l")
3164 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3165 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
5b3e6663 3166 "TARGET_THUMB1"
d5b7b3ae
RE
3167 "lsl\\t%0, %1, %2"
3168 [(set_attr "length" "2")]
3169)
3a33f76f 3170
9b66ebb1
PB
3171(define_expand "ashrdi3"
3172 [(set (match_operand:DI 0 "s_register_operand" "")
3173 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3174 (match_operand:SI 2 "reg_or_int_operand" "")))]
5b3e6663 3175 "TARGET_32BIT"
9b66ebb1
PB
3176 "
3177 if (GET_CODE (operands[2]) == CONST_INT)
3178 {
3179 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3180 {
3181 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3182 DONE;
3183 }
3184 /* Ideally we shouldn't fail here if we could know that operands[1]
3185 ends up already living in an iwmmxt register. Otherwise it's
3186 cheaper to have the alternate code being generated than moving
ff482c8d 3187 values to iwmmxt regs and back. */
9b66ebb1
PB
3188 FAIL;
3189 }
3190 else if (!TARGET_REALLY_IWMMXT)
3191 FAIL;
3192 "
3193)
3194
3195(define_insn "arm_ashrdi3_1bit"
3196 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3197 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3198 (const_int 1)))
3199 (clobber (reg:CC CC_REGNUM))]
5b3e6663 3200 "TARGET_32BIT"
9b66ebb1
PB
3201 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3202 [(set_attr "conds" "clob")
3203 (set_attr "length" "8")]
3204)
3205
091426d3 3206(define_expand "ashrsi3"
d5b7b3ae 3207 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
3208 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3209 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 3210 "TARGET_EITHER"
091426d3
RE
3211 "
3212 if (GET_CODE (operands[2]) == CONST_INT
3213 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3214 operands[2] = GEN_INT (31);
d5b7b3ae
RE
3215 "
3216)
3217
5b3e6663 3218(define_insn "*thumb1_ashrsi3"
d5b7b3ae
RE
3219 [(set (match_operand:SI 0 "register_operand" "=l,l")
3220 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3221 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
5b3e6663 3222 "TARGET_THUMB1"
d5b7b3ae
RE
3223 "asr\\t%0, %1, %2"
3224 [(set_attr "length" "2")]
3225)
3a33f76f 3226
9b66ebb1
PB
3227(define_expand "lshrdi3"
3228 [(set (match_operand:DI 0 "s_register_operand" "")
3229 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3230 (match_operand:SI 2 "reg_or_int_operand" "")))]
5b3e6663 3231 "TARGET_32BIT"
9b66ebb1
PB
3232 "
3233 if (GET_CODE (operands[2]) == CONST_INT)
3234 {
3235 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3236 {
3237 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3238 DONE;
3239 }
3240 /* Ideally we shouldn't fail here if we could know that operands[1]
3241 ends up already living in an iwmmxt register. Otherwise it's
3242 cheaper to have the alternate code being generated than moving
ff482c8d 3243 values to iwmmxt regs and back. */
9b66ebb1
PB
3244 FAIL;
3245 }
3246 else if (!TARGET_REALLY_IWMMXT)
3247 FAIL;
3248 "
3249)
3250
3251(define_insn "arm_lshrdi3_1bit"
3252 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3253 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3254 (const_int 1)))
3255 (clobber (reg:CC CC_REGNUM))]
5b3e6663 3256 "TARGET_32BIT"
9b66ebb1
PB
3257 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3258 [(set_attr "conds" "clob")
3259 (set_attr "length" "8")]
3260)
3261
091426d3 3262(define_expand "lshrsi3"
d5b7b3ae 3263 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
3264 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3265 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 3266 "TARGET_EITHER"
091426d3
RE
3267 "
3268 if (GET_CODE (operands[2]) == CONST_INT
3269 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3270 {
3271 emit_insn (gen_movsi (operands[0], const0_rtx));
3272 DONE;
3273 }
d5b7b3ae
RE
3274 "
3275)
3276
5b3e6663 3277(define_insn "*thumb1_lshrsi3"
d5b7b3ae
RE
3278 [(set (match_operand:SI 0 "register_operand" "=l,l")
3279 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3280 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
5b3e6663 3281 "TARGET_THUMB1"
d5b7b3ae
RE
3282 "lsr\\t%0, %1, %2"
3283 [(set_attr "length" "2")]
3284)
3a33f76f 3285
091426d3 3286(define_expand "rotlsi3"
d5b7b3ae 3287 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
3288 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3289 (match_operand:SI 2 "reg_or_int_operand" "")))]
5b3e6663 3290 "TARGET_32BIT"
091426d3
RE
3291 "
3292 if (GET_CODE (operands[2]) == CONST_INT)
3293 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3294 else
3a33f76f 3295 {
091426d3
RE
3296 rtx reg = gen_reg_rtx (SImode);
3297 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3298 operands[2] = reg;
3a33f76f 3299 }
d5b7b3ae
RE
3300 "
3301)
ff9940b0 3302
091426d3 3303(define_expand "rotrsi3"
d5b7b3ae 3304 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
3305 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3306 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 3307 "TARGET_EITHER"
091426d3 3308 "
5b3e6663 3309 if (TARGET_32BIT)
d5b7b3ae
RE
3310 {
3311 if (GET_CODE (operands[2]) == CONST_INT
3312 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3313 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3314 }
5b3e6663 3315 else /* TARGET_THUMB1 */
d5b7b3ae
RE
3316 {
3317 if (GET_CODE (operands [2]) == CONST_INT)
3318 operands [2] = force_reg (SImode, operands[2]);
3319 }
3320 "
3321)
091426d3 3322
5b3e6663 3323(define_insn "*thumb1_rotrsi3"
d5b7b3ae
RE
3324 [(set (match_operand:SI 0 "register_operand" "=l")
3325 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3326 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 3327 "TARGET_THUMB1"
d5b7b3ae
RE
3328 "ror\\t%0, %0, %2"
3329 [(set_attr "length" "2")]
3330)
3331
3332(define_insn "*arm_shiftsi3"
3333 [(set (match_operand:SI 0 "s_register_operand" "=r")
3334 (match_operator:SI 3 "shift_operator"
3335 [(match_operand:SI 1 "s_register_operand" "r")
091426d3 3336 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
5b3e6663
PB
3337 "TARGET_32BIT"
3338 "* return arm_output_shift(operands, 0);"
ca68ea18 3339 [(set_attr "predicable" "yes")
d19fb8e3 3340 (set_attr "shift" "1")
9b66ebb1
PB
3341 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3342 (const_string "alu_shift")
3343 (const_string "alu_shift_reg")))]
b020fd92 3344)
091426d3 3345
4cdb3ed4 3346(define_insn "*shiftsi3_compare0"
48a08b9c 3347 [(set (reg:CC_NOOV CC_REGNUM)
091426d3
RE
3348 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3349 [(match_operand:SI 1 "s_register_operand" "r")
3350 (match_operand:SI 2 "arm_rhs_operand" "rM")])
ff9940b0
RE
3351 (const_int 0)))
3352 (set (match_operand:SI 0 "s_register_operand" "=r")
091426d3 3353 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
5b3e6663
PB
3354 "TARGET_32BIT"
3355 "* return arm_output_shift(operands, 1);"
ca68ea18 3356 [(set_attr "conds" "set")
d19fb8e3 3357 (set_attr "shift" "1")
9b66ebb1
PB
3358 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3359 (const_string "alu_shift")
3360 (const_string "alu_shift_reg")))]
cca0a211 3361)
ff9940b0 3362
4cdb3ed4 3363(define_insn "*shiftsi3_compare0_scratch"
48a08b9c 3364 [(set (reg:CC_NOOV CC_REGNUM)
091426d3
RE
3365 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3366 [(match_operand:SI 1 "s_register_operand" "r")
3367 (match_operand:SI 2 "arm_rhs_operand" "rM")])
ff9940b0
RE
3368 (const_int 0)))
3369 (clobber (match_scratch:SI 0 "=r"))]
5b3e6663
PB
3370 "TARGET_32BIT"
3371 "* return arm_output_shift(operands, 1);"
ca68ea18 3372 [(set_attr "conds" "set")
9b66ebb1 3373 (set_attr "shift" "1")]
cca0a211 3374)
ff9940b0 3375
5b3e6663 3376(define_insn "*arm_notsi_shiftsi"
ff9940b0 3377 [(set (match_operand:SI 0 "s_register_operand" "=r")
091426d3
RE
3378 (not:SI (match_operator:SI 3 "shift_operator"
3379 [(match_operand:SI 1 "s_register_operand" "r")
3380 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
d5b7b3ae 3381 "TARGET_ARM"
b020fd92 3382 "mvn%?\\t%0, %1%S3"
ca68ea18 3383 [(set_attr "predicable" "yes")
d19fb8e3 3384 (set_attr "shift" "1")
9b66ebb1
PB
3385 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3386 (const_string "alu_shift")
3387 (const_string "alu_shift_reg")))]
cca0a211 3388)
ff9940b0 3389
5b3e6663 3390(define_insn "*arm_notsi_shiftsi_compare0"
48a08b9c 3391 [(set (reg:CC_NOOV CC_REGNUM)
091426d3
RE
3392 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3393 [(match_operand:SI 1 "s_register_operand" "r")
3394 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
ff9940b0
RE
3395 (const_int 0)))
3396 (set (match_operand:SI 0 "s_register_operand" "=r")
091426d3 3397 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5b7b3ae 3398 "TARGET_ARM"
5b3e6663 3399 "mvn%.\\t%0, %1%S3"
ca68ea18 3400 [(set_attr "conds" "set")
d19fb8e3 3401 (set_attr "shift" "1")
9b66ebb1
PB
3402 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3403 (const_string "alu_shift")
3404 (const_string "alu_shift_reg")))]
cca0a211 3405)
ff9940b0 3406
5b3e6663 3407(define_insn "*arm_not_shiftsi_compare0_scratch"
48a08b9c 3408 [(set (reg:CC_NOOV CC_REGNUM)
091426d3
RE
3409 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3410 [(match_operand:SI 1 "s_register_operand" "r")
3411 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
ff9940b0
RE
3412 (const_int 0)))
3413 (clobber (match_scratch:SI 0 "=r"))]
d5b7b3ae 3414 "TARGET_ARM"
5b3e6663 3415 "mvn%.\\t%0, %1%S3"
ca68ea18 3416 [(set_attr "conds" "set")
d19fb8e3 3417 (set_attr "shift" "1")
9b66ebb1
PB
3418 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3419 (const_string "alu_shift")
3420 (const_string "alu_shift_reg")))]
cca0a211 3421)
ff9940b0 3422
d5b7b3ae
RE
3423;; We don't really have extzv, but defining this using shifts helps
3424;; to reduce register pressure later on.
3425
3426(define_expand "extzv"
3427 [(set (match_dup 4)
3428 (ashift:SI (match_operand:SI 1 "register_operand" "")
3429 (match_operand:SI 2 "const_int_operand" "")))
3430 (set (match_operand:SI 0 "register_operand" "")
3431 (lshiftrt:SI (match_dup 4)
5895f793 3432 (match_operand:SI 3 "const_int_operand" "")))]
ef87d898 3433 "TARGET_THUMB1 || arm_arch_thumb2"
d5b7b3ae
RE
3434 "
3435 {
3436 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3437 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3438
ef87d898
PB
3439 if (arm_arch_thumb2)
3440 {
3441 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3442 operands[3]));
3443 DONE;
3444 }
3445
d5b7b3ae
RE
3446 operands[3] = GEN_INT (rshift);
3447
3448 if (lshift == 0)
3449 {
3450 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3451 DONE;
3452 }
3453
3454 operands[2] = GEN_INT (lshift);
3455 operands[4] = gen_reg_rtx (SImode);
5895f793 3456 }"
d5b7b3ae
RE
3457)
3458
ef87d898
PB
3459(define_insn "extv"
3460 [(set (match_operand:SI 0 "s_register_operand" "=r")
3461 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3462 (match_operand:SI 2 "const_int_operand" "M")
3463 (match_operand:SI 3 "const_int_operand" "M")))]
3464 "arm_arch_thumb2"
3465 "sbfx%?\t%0, %1, %3, %2"
3466 [(set_attr "length" "4")
3467 (set_attr "predicable" "yes")]
3468)
3469
3470(define_insn "extzv_t2"
3471 [(set (match_operand:SI 0 "s_register_operand" "=r")
3472 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3473 (match_operand:SI 2 "const_int_operand" "M")
3474 (match_operand:SI 3 "const_int_operand" "M")))]
3475 "arm_arch_thumb2"
3476 "ubfx%?\t%0, %1, %3, %2"
3477 [(set_attr "length" "4")
3478 (set_attr "predicable" "yes")]
3479)
3480
3a33f76f
RK
3481\f
3482;; Unary arithmetic insns
3483
d5b7b3ae
RE
3484(define_expand "negdi2"
3485 [(parallel
3486 [(set (match_operand:DI 0 "s_register_operand" "")
3487 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
48a08b9c 3488 (clobber (reg:CC CC_REGNUM))])]
d5b7b3ae
RE
3489 "TARGET_EITHER"
3490 "
5b3e6663 3491 if (TARGET_THUMB1)
d5b7b3ae
RE
3492 {
3493 if (GET_CODE (operands[1]) != REG)
3494 operands[1] = force_reg (SImode, operands[1]);
3495 }
5895f793 3496 "
d5b7b3ae
RE
3497)
3498
3499;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3500;; The second alternative is to allow the common case of a *full* overlap.
3501(define_insn "*arm_negdi2"
3502 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3503 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
48a08b9c 3504 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3505 "TARGET_ARM"
3dafc5c3 3506 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
d5b7b3ae
RE
3507 [(set_attr "conds" "clob")
3508 (set_attr "length" "8")]
3509)
3a33f76f 3510
5b3e6663 3511(define_insn "*thumb1_negdi2"
d5b7b3ae
RE
3512 [(set (match_operand:DI 0 "register_operand" "=&l")
3513 (neg:DI (match_operand:DI 1 "register_operand" "l")))
48a08b9c 3514 (clobber (reg:CC CC_REGNUM))]
5b3e6663 3515 "TARGET_THUMB1"
d5b7b3ae
RE
3516 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3517 [(set_attr "length" "6")]
3518)
3519
3520(define_expand "negsi2"
3521 [(set (match_operand:SI 0 "s_register_operand" "")
3522 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3523 "TARGET_EITHER"
3a33f76f 3524 ""
d5b7b3ae
RE
3525)
3526
3527(define_insn "*arm_negsi2"
3528 [(set (match_operand:SI 0 "s_register_operand" "=r")
3529 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 3530 "TARGET_32BIT"
d5b7b3ae 3531 "rsb%?\\t%0, %1, #0"
cca0a211 3532 [(set_attr "predicable" "yes")]
d5b7b3ae
RE
3533)
3534
5b3e6663 3535(define_insn "*thumb1_negsi2"
d5b7b3ae
RE
3536 [(set (match_operand:SI 0 "register_operand" "=l")
3537 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
5b3e6663 3538 "TARGET_THUMB1"
d5b7b3ae
RE
3539 "neg\\t%0, %1"
3540 [(set_attr "length" "2")]
3541)
3a33f76f 3542
37f74dcf
RE
3543(define_expand "negsf2"
3544 [(set (match_operand:SF 0 "s_register_operand" "")
3545 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
5b3e6663 3546 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
37f74dcf
RE
3547 ""
3548)
3549
3550(define_expand "negdf2"
3551 [(set (match_operand:DF 0 "s_register_operand" "")
3552 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
5b3e6663 3553 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
37f74dcf
RE
3554 "")
3555
ff9940b0
RE
3556;; abssi2 doesn't really clobber the condition codes if a different register
3557;; is being set. To keep things simple, assume during rtl manipulations that
3558;; it does, but tell the final scan operator the truth. Similarly for
3559;; (neg (abs...))
3560
37f74dcf
RE
3561(define_expand "abssi2"
3562 [(parallel
3563 [(set (match_operand:SI 0 "s_register_operand" "")
3564 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ecaf6f07
RE
3565 (clobber (match_dup 2))])]
3566 "TARGET_EITHER"
3567 "
5b3e6663 3568 if (TARGET_THUMB1)
ecaf6f07
RE
3569 operands[2] = gen_rtx_SCRATCH (SImode);
3570 else
3571 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3572")
37f74dcf 3573
9b6b54e2 3574(define_insn "*arm_abssi2"
ecaf6f07 3575 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
ff9940b0 3576 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
48a08b9c 3577 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3578 "TARGET_ARM"
0f447ef2
RE
3579 "@
3580 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
c63165be 3581 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
d5b7b3ae 3582 [(set_attr "conds" "clob,*")
d19fb8e3 3583 (set_attr "shift" "1")
cca0a211 3584 ;; predicable can't be set based on the variant, so left as no
d5b7b3ae
RE
3585 (set_attr "length" "8")]
3586)
ff9940b0 3587
5b3e6663 3588(define_insn_and_split "*thumb1_abssi2"
ecaf6f07
RE
3589 [(set (match_operand:SI 0 "s_register_operand" "=l")
3590 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3591 (clobber (match_scratch:SI 2 "=&l"))]
5b3e6663 3592 "TARGET_THUMB1"
ecaf6f07 3593 "#"
5b3e6663 3594 "TARGET_THUMB1 && reload_completed"
ecaf6f07
RE
3595 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3596 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3597 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3598 ""
3599 [(set_attr "length" "6")]
3600)
3601
3602(define_insn "*arm_neg_abssi2"
ff9940b0
RE
3603 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3604 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
48a08b9c 3605 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3606 "TARGET_ARM"
0f447ef2
RE
3607 "@
3608 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
c63165be 3609 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
d5b7b3ae 3610 [(set_attr "conds" "clob,*")
d19fb8e3 3611 (set_attr "shift" "1")
cca0a211 3612 ;; predicable can't be set based on the variant, so left as no
d5b7b3ae
RE
3613 (set_attr "length" "8")]
3614)
3a33f76f 3615
5b3e6663 3616(define_insn_and_split "*thumb1_neg_abssi2"
ecaf6f07
RE
3617 [(set (match_operand:SI 0 "s_register_operand" "=l")
3618 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3619 (clobber (match_scratch:SI 2 "=&l"))]
5b3e6663 3620 "TARGET_THUMB1"
ecaf6f07 3621 "#"
5b3e6663 3622 "TARGET_THUMB1 && reload_completed"
ecaf6f07
RE
3623 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3624 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3625 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3626 ""
3627 [(set_attr "length" "6")]
3628)
3629
37f74dcf
RE
3630(define_expand "abssf2"
3631 [(set (match_operand:SF 0 "s_register_operand" "")
3632 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
5b3e6663 3633 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf
RE
3634 "")
3635
37f74dcf
RE
3636(define_expand "absdf2"
3637 [(set (match_operand:DF 0 "s_register_operand" "")
3638 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
5b3e6663 3639 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf
RE
3640 "")
3641
82955615
RE
3642(define_expand "sqrtsf2"
3643 [(set (match_operand:SF 0 "s_register_operand" "")
3644 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
5b3e6663 3645 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
82955615 3646 "")
ff9940b0 3647
82955615
RE
3648(define_expand "sqrtdf2"
3649 [(set (match_operand:DF 0 "s_register_operand" "")
3650 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
5b3e6663 3651 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
82955615 3652 "")
ff9940b0 3653
bb6ae783 3654(define_insn_and_split "one_cmpldi2"
ff9940b0
RE
3655 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3656 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
5b3e6663 3657 "TARGET_32BIT"
6ab589e0 3658 "#"
5b3e6663 3659 "TARGET_32BIT && reload_completed"
bb6ae783
RE
3660 [(set (match_dup 0) (not:SI (match_dup 1)))
3661 (set (match_dup 2) (not:SI (match_dup 3)))]
3662 "
3663 {
3664 operands[2] = gen_highpart (SImode, operands[0]);
3665 operands[0] = gen_lowpart (SImode, operands[0]);
3666 operands[3] = gen_highpart (SImode, operands[1]);
3667 operands[1] = gen_lowpart (SImode, operands[1]);
3668 }"
cca0a211
RE
3669 [(set_attr "length" "8")
3670 (set_attr "predicable" "yes")]
d5b7b3ae 3671)
3a33f76f 3672
d5b7b3ae
RE
3673(define_expand "one_cmplsi2"
3674 [(set (match_operand:SI 0 "s_register_operand" "")
3675 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3676 "TARGET_EITHER"
3a33f76f 3677 ""
d5b7b3ae
RE
3678)
3679
3680(define_insn "*arm_one_cmplsi2"
3681 [(set (match_operand:SI 0 "s_register_operand" "=r")
3682 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 3683 "TARGET_32BIT"
d5b7b3ae 3684 "mvn%?\\t%0, %1"
cca0a211 3685 [(set_attr "predicable" "yes")]
d5b7b3ae
RE
3686)
3687
5b3e6663 3688(define_insn "*thumb1_one_cmplsi2"
d5b7b3ae
RE
3689 [(set (match_operand:SI 0 "register_operand" "=l")
3690 (not:SI (match_operand:SI 1 "register_operand" "l")))]
5b3e6663 3691 "TARGET_THUMB1"
d5b7b3ae
RE
3692 "mvn\\t%0, %1"
3693 [(set_attr "length" "2")]
3694)
ff9940b0 3695
4cdb3ed4 3696(define_insn "*notsi_compare0"
48a08b9c 3697 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
3698 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3699 (const_int 0)))
3700 (set (match_operand:SI 0 "s_register_operand" "=r")
3701 (not:SI (match_dup 1)))]
5b3e6663
PB
3702 "TARGET_32BIT"
3703 "mvn%.\\t%0, %1"
d5b7b3ae
RE
3704 [(set_attr "conds" "set")]
3705)
ff9940b0 3706
4cdb3ed4 3707(define_insn "*notsi_compare0_scratch"
48a08b9c 3708 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
3709 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3710 (const_int 0)))
3711 (clobber (match_scratch:SI 0 "=r"))]
5b3e6663
PB
3712 "TARGET_32BIT"
3713 "mvn%.\\t%0, %1"
d5b7b3ae
RE
3714 [(set_attr "conds" "set")]
3715)
3a33f76f
RK
3716\f
3717;; Fixed <--> Floating conversion insns
3718
37f74dcf
RE
3719(define_expand "floatsisf2"
3720 [(set (match_operand:SF 0 "s_register_operand" "")
3721 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
5b3e6663 3722 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 3723 "
9b66ebb1 3724 if (TARGET_MAVERICK)
37f74dcf
RE
3725 {
3726 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3727 DONE;
3728 }
3729")
3730
37f74dcf
RE
3731(define_expand "floatsidf2"
3732 [(set (match_operand:DF 0 "s_register_operand" "")
3733 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
5b3e6663 3734 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 3735 "
9b66ebb1 3736 if (TARGET_MAVERICK)
37f74dcf
RE
3737 {
3738 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3739 DONE;
3740 }
3741")
3742
37f74dcf
RE
3743(define_expand "fix_truncsfsi2"
3744 [(set (match_operand:SI 0 "s_register_operand" "")
17136dde 3745 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
5b3e6663 3746 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 3747 "
9b66ebb1 3748 if (TARGET_MAVERICK)
37f74dcf
RE
3749 {
3750 if (!cirrus_fp_register (operands[0], SImode))
3751 operands[0] = force_reg (SImode, operands[0]);
3752 if (!cirrus_fp_register (operands[1], SFmode))
3753 operands[1] = force_reg (SFmode, operands[0]);
3754 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3755 DONE;
3756 }
3757")
3758
37f74dcf
RE
3759(define_expand "fix_truncdfsi2"
3760 [(set (match_operand:SI 0 "s_register_operand" "")
17136dde 3761 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
5b3e6663 3762 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 3763 "
9b66ebb1 3764 if (TARGET_MAVERICK)
37f74dcf
RE
3765 {
3766 if (!cirrus_fp_register (operands[1], DFmode))
3767 operands[1] = force_reg (DFmode, operands[0]);
3768 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3769 DONE;
3770 }
3771")
3772
3a7a2719 3773;; Truncation insns
3a33f76f 3774
37f74dcf
RE
3775(define_expand "truncdfsf2"
3776 [(set (match_operand:SF 0 "s_register_operand" "")
3777 (float_truncate:SF
3778 (match_operand:DF 1 "s_register_operand" "")))]
5b3e6663 3779 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf
RE
3780 ""
3781)
3a33f76f 3782\f
ff9940b0 3783;; Zero and sign extension instructions.
3a33f76f 3784
5b3e6663
PB
3785(define_expand "zero_extendsidi2"
3786 [(set (match_operand:DI 0 "s_register_operand" "")
3787 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3788 "TARGET_32BIT"
3789 ""
3790)
3791
3792(define_insn "*arm_zero_extendsidi2"
ff9940b0
RE
3793 [(set (match_operand:DI 0 "s_register_operand" "=r")
3794 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
d5b7b3ae 3795 "TARGET_ARM"
ff9940b0 3796 "*
cca0a211
RE
3797 if (REGNO (operands[1])
3798 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3799 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3800 return \"mov%?\\t%R0, #0\";
3801 "
3802 [(set_attr "length" "8")
3803 (set_attr "predicable" "yes")]
3804)
ff9940b0 3805
5b3e6663
PB
3806(define_expand "zero_extendqidi2"
3807 [(set (match_operand:DI 0 "s_register_operand" "")
3808 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3809 "TARGET_32BIT"
3810 ""
3811)
3812
3813(define_insn "*arm_zero_extendqidi2"
d5b7b3ae 3814 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
ff9940b0 3815 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
d5b7b3ae 3816 "TARGET_ARM"
0f447ef2 3817 "@
3dafc5c3 3818 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
5b3e6663 3819 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
d5b7b3ae 3820 [(set_attr "length" "8")
cca0a211 3821 (set_attr "predicable" "yes")
9b66ebb1 3822 (set_attr "type" "*,load_byte")
d5b7b3ae
RE
3823 (set_attr "pool_range" "*,4092")
3824 (set_attr "neg_pool_range" "*,4084")]
3825)
ff9940b0 3826
5b3e6663
PB
3827(define_expand "extendsidi2"
3828 [(set (match_operand:DI 0 "s_register_operand" "")
3829 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3830 "TARGET_32BIT"
3831 ""
3832)
3833
3834(define_insn "*arm_extendsidi2"
ff9940b0
RE
3835 [(set (match_operand:DI 0 "s_register_operand" "=r")
3836 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
d5b7b3ae 3837 "TARGET_ARM"
ff9940b0 3838 "*
cca0a211
RE
3839 if (REGNO (operands[1])
3840 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3841 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3842 return \"mov%?\\t%R0, %Q0, asr #31\";
d5b7b3ae
RE
3843 "
3844 [(set_attr "length" "8")
d19fb8e3 3845 (set_attr "shift" "1")
cca0a211
RE
3846 (set_attr "predicable" "yes")]
3847)
ff9940b0
RE
3848
3849(define_expand "zero_extendhisi2"
d5b7b3ae 3850 [(set (match_dup 2)
cca0a211
RE
3851 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3852 (const_int 16)))
ff9940b0 3853 (set (match_operand:SI 0 "s_register_operand" "")
091426d3 3854 (lshiftrt:SI (match_dup 2) (const_int 16)))]
d5b7b3ae 3855 "TARGET_EITHER"
ff9940b0 3856 "
d5b7b3ae 3857 {
5b3e6663 3858 if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
d5b7b3ae 3859 {
9b66ebb1
PB
3860 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3861 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3862 DONE;
d5b7b3ae 3863 }
d5b7b3ae 3864
61f0ccff 3865 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
9b66ebb1
PB
3866 {
3867 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3868 DONE;
3869 }
d5b7b3ae 3870
9b66ebb1
PB
3871 if (!s_register_operand (operands[1], HImode))
3872 operands[1] = copy_to_mode_reg (HImode, operands[1]);
d5b7b3ae 3873
9b66ebb1
PB
3874 if (arm_arch6)
3875 {
3876 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3877 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3878 DONE;
d5b7b3ae 3879 }
9b66ebb1
PB
3880
3881 operands[1] = gen_lowpart (SImode, operands[1]);
3882 operands[2] = gen_reg_rtx (SImode);
d5b7b3ae
RE
3883 }"
3884)
3885
5b3e6663 3886(define_insn "*thumb1_zero_extendhisi2"
9b66ebb1
PB
3887 [(set (match_operand:SI 0 "register_operand" "=l")
3888 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
5b3e6663 3889 "TARGET_THUMB1 && !arm_arch6"
d5b7b3ae
RE
3890 "*
3891 rtx mem = XEXP (operands[1], 0);
3892
3893 if (GET_CODE (mem) == CONST)
3894 mem = XEXP (mem, 0);
3895
3896 if (GET_CODE (mem) == LABEL_REF)
3897 return \"ldr\\t%0, %1\";
3898
3899 if (GET_CODE (mem) == PLUS)
4cdb3ed4 3900 {
d5b7b3ae
RE
3901 rtx a = XEXP (mem, 0);
3902 rtx b = XEXP (mem, 1);
3903
3904 /* This can happen due to bugs in reload. */
3905 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3906 {
3907 rtx ops[2];
3908 ops[0] = operands[0];
3909 ops[1] = a;
3910
3911 output_asm_insn (\"mov %0, %1\", ops);
3912
3913 XEXP (mem, 0) = operands[0];
3914 }
3915
3916 else if ( GET_CODE (a) == LABEL_REF
3917 && GET_CODE (b) == CONST_INT)
3918 return \"ldr\\t%0, %1\";
988337ca 3919 }
d5b7b3ae
RE
3920
3921 return \"ldrh\\t%0, %1\";
3922 "
3923 [(set_attr "length" "4")
9b66ebb1 3924 (set_attr "type" "load_byte")
d5b7b3ae
RE
3925 (set_attr "pool_range" "60")]
3926)
ff9940b0 3927
5b3e6663 3928(define_insn "*thumb1_zero_extendhisi2_v6"
9b66ebb1
PB
3929 [(set (match_operand:SI 0 "register_operand" "=l,l")
3930 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
5b3e6663 3931 "TARGET_THUMB1 && arm_arch6"
9b66ebb1
PB
3932 "*
3933 rtx mem;
3934
3935 if (which_alternative == 0)
3936 return \"uxth\\t%0, %1\";
3937
3938 mem = XEXP (operands[1], 0);
3939
3940 if (GET_CODE (mem) == CONST)
3941 mem = XEXP (mem, 0);
3942
3943 if (GET_CODE (mem) == LABEL_REF)
3944 return \"ldr\\t%0, %1\";
3945
3946 if (GET_CODE (mem) == PLUS)
3947 {
3948 rtx a = XEXP (mem, 0);
3949 rtx b = XEXP (mem, 1);
3950
3951 /* This can happen due to bugs in reload. */
3952 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3953 {
3954 rtx ops[2];
3955 ops[0] = operands[0];
3956 ops[1] = a;
3957
3958 output_asm_insn (\"mov %0, %1\", ops);
3959
3960 XEXP (mem, 0) = operands[0];
3961 }
3962
3963 else if ( GET_CODE (a) == LABEL_REF
3964 && GET_CODE (b) == CONST_INT)
3965 return \"ldr\\t%0, %1\";
3966 }
3967
3968 return \"ldrh\\t%0, %1\";
3969 "
3970 [(set_attr "length" "2,4")
3971 (set_attr "type" "alu_shift,load_byte")
3972 (set_attr "pool_range" "*,60")]
3973)
3974
d5b7b3ae 3975(define_insn "*arm_zero_extendhisi2"
9b66ebb1
PB
3976 [(set (match_operand:SI 0 "s_register_operand" "=r")
3977 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3978 "TARGET_ARM && arm_arch4 && !arm_arch6"
5b3e6663 3979 "ldr%(h%)\\t%0, %1"
9b66ebb1 3980 [(set_attr "type" "load_byte")
cca0a211 3981 (set_attr "predicable" "yes")
d5b7b3ae
RE
3982 (set_attr "pool_range" "256")
3983 (set_attr "neg_pool_range" "244")]
3984)
4cdb3ed4 3985
9b66ebb1
PB
3986(define_insn "*arm_zero_extendhisi2_v6"
3987 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3988 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3989 "TARGET_ARM && arm_arch6"
3990 "@
3991 uxth%?\\t%0, %1
5b3e6663 3992 ldr%(h%)\\t%0, %1"
9b66ebb1
PB
3993 [(set_attr "type" "alu_shift,load_byte")
3994 (set_attr "predicable" "yes")
3995 (set_attr "pool_range" "*,256")
3996 (set_attr "neg_pool_range" "*,244")]
3997)
3998
3999(define_insn "*arm_zero_extendhisi2addsi"
4000 [(set (match_operand:SI 0 "s_register_operand" "=r")
4001 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4002 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 4003 "TARGET_INT_SIMD"
9b66ebb1
PB
4004 "uxtah%?\\t%0, %2, %1"
4005 [(set_attr "type" "alu_shift")
4006 (set_attr "predicable" "yes")]
4007)
4008
091426d3 4009(define_expand "zero_extendqisi2"
d5b7b3ae
RE
4010 [(set (match_operand:SI 0 "s_register_operand" "")
4011 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4012 "TARGET_EITHER"
091426d3 4013 "
9b66ebb1 4014 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
091426d3 4015 {
d5b7b3ae
RE
4016 if (TARGET_ARM)
4017 {
5895f793
RE
4018 emit_insn (gen_andsi3 (operands[0],
4019 gen_lowpart (SImode, operands[1]),
d5b7b3ae
RE
4020 GEN_INT (255)));
4021 }
4022 else /* TARGET_THUMB */
4023 {
4024 rtx temp = gen_reg_rtx (SImode);
4025 rtx ops[3];
4026
4027 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4028 operands[1] = gen_lowpart (SImode, operands[1]);
4029
4030 ops[0] = temp;
4031 ops[1] = operands[1];
4032 ops[2] = GEN_INT (24);
4033
5895f793
RE
4034 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4035 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
d5b7b3ae
RE
4036
4037 ops[0] = operands[0];
4038 ops[1] = temp;
4039 ops[2] = GEN_INT (24);
4040
5895f793
RE
4041 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4042 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
d5b7b3ae 4043 }
091426d3
RE
4044 DONE;
4045 }
5895f793
RE
4046 "
4047)
ff9940b0 4048
5b3e6663 4049(define_insn "*thumb1_zero_extendqisi2"
9b66ebb1
PB
4050 [(set (match_operand:SI 0 "register_operand" "=l")
4051 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
5b3e6663 4052 "TARGET_THUMB1 && !arm_arch6"
d5b7b3ae
RE
4053 "ldrb\\t%0, %1"
4054 [(set_attr "length" "2")
9b66ebb1 4055 (set_attr "type" "load_byte")
d5b7b3ae
RE
4056 (set_attr "pool_range" "32")]
4057)
4058
5b3e6663 4059(define_insn "*thumb1_zero_extendqisi2_v6"
9b66ebb1
PB
4060 [(set (match_operand:SI 0 "register_operand" "=l,l")
4061 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
5b3e6663 4062 "TARGET_THUMB1 && arm_arch6"
9b66ebb1
PB
4063 "@
4064 uxtb\\t%0, %1
4065 ldrb\\t%0, %1"
4066 [(set_attr "length" "2,2")
4067 (set_attr "type" "alu_shift,load_byte")
4068 (set_attr "pool_range" "*,32")]
4069)
4070
d5b7b3ae 4071(define_insn "*arm_zero_extendqisi2"
9b66ebb1
PB
4072 [(set (match_operand:SI 0 "s_register_operand" "=r")
4073 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4074 "TARGET_ARM && !arm_arch6"
5b3e6663 4075 "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
9b66ebb1 4076 [(set_attr "type" "load_byte")
cca0a211 4077 (set_attr "predicable" "yes")
d5b7b3ae
RE
4078 (set_attr "pool_range" "4096")
4079 (set_attr "neg_pool_range" "4084")]
4080)
091426d3 4081
9b66ebb1
PB
4082(define_insn "*arm_zero_extendqisi2_v6"
4083 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4084 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4085 "TARGET_ARM && arm_arch6"
4086 "@
5b3e6663
PB
4087 uxtb%(%)\\t%0, %1
4088 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
9b66ebb1
PB
4089 [(set_attr "type" "alu_shift,load_byte")
4090 (set_attr "predicable" "yes")
4091 (set_attr "pool_range" "*,4096")
4092 (set_attr "neg_pool_range" "*,4084")]
4093)
4094
4095(define_insn "*arm_zero_extendqisi2addsi"
4096 [(set (match_operand:SI 0 "s_register_operand" "=r")
4097 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4098 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 4099 "TARGET_INT_SIMD"
9b66ebb1
PB
4100 "uxtab%?\\t%0, %2, %1"
4101 [(set_attr "predicable" "yes")
c956e102 4102 (set_attr "insn" "xtab")
9b66ebb1
PB
4103 (set_attr "type" "alu_shift")]
4104)
4105
091426d3
RE
4106(define_split
4107 [(set (match_operand:SI 0 "s_register_operand" "")
4108 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4109 (clobber (match_operand:SI 2 "s_register_operand" ""))]
5b3e6663 4110 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
091426d3
RE
4111 [(set (match_dup 2) (match_dup 1))
4112 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
d5b7b3ae
RE
4113 ""
4114)
ff9940b0 4115
174ddc67
RS
4116(define_split
4117 [(set (match_operand:SI 0 "s_register_operand" "")
4118 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4119 (clobber (match_operand:SI 2 "s_register_operand" ""))]
5b3e6663 4120 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
174ddc67
RS
4121 [(set (match_dup 2) (match_dup 1))
4122 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4123 ""
4124)
4125
4cdb3ed4 4126(define_insn "*compareqi_eq0"
48a08b9c 4127 [(set (reg:CC_Z CC_REGNUM)
0502226c 4128 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
091426d3 4129 (const_int 0)))]
5b3e6663 4130 "TARGET_32BIT"
091426d3 4131 "tst\\t%0, #255"
d5b7b3ae
RE
4132 [(set_attr "conds" "set")]
4133)
3a33f76f 4134
3a33f76f 4135(define_expand "extendhisi2"
fd3f89a9 4136 [(set (match_dup 2)
988337ca 4137 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3a33f76f 4138 (const_int 16)))
ff9940b0 4139 (set (match_operand:SI 0 "s_register_operand" "")
fd3f89a9
TG
4140 (ashiftrt:SI (match_dup 2)
4141 (const_int 16)))]
d5b7b3ae 4142 "TARGET_EITHER"
3a33f76f 4143 "
d5b7b3ae 4144 {
9b66ebb1 4145 if (GET_CODE (operands[1]) == MEM)
d5b7b3ae 4146 {
5b3e6663 4147 if (TARGET_THUMB1)
9b66ebb1 4148 {
5b3e6663 4149 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
9b66ebb1
PB
4150 DONE;
4151 }
4152 else if (arm_arch4)
4153 {
9b66ebb1
PB
4154 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4155 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4156 DONE;
4157 }
d5b7b3ae 4158 }
6cc8c0b3 4159
61f0ccff 4160 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
d5b7b3ae
RE
4161 {
4162 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4163 DONE;
4164 }
9b66ebb1 4165
5895f793 4166 if (!s_register_operand (operands[1], HImode))
d5b7b3ae 4167 operands[1] = copy_to_mode_reg (HImode, operands[1]);
d5b7b3ae 4168
9b66ebb1 4169 if (arm_arch6)
d5b7b3ae 4170 {
5b3e6663
PB
4171 if (TARGET_THUMB1)
4172 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
9b66ebb1
PB
4173 else
4174 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4175 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4176
d5b7b3ae
RE
4177 DONE;
4178 }
9b66ebb1
PB
4179
4180 operands[1] = gen_lowpart (SImode, operands[1]);
4181 operands[2] = gen_reg_rtx (SImode);
d5b7b3ae
RE
4182 }"
4183)
4184
5b3e6663 4185(define_insn "thumb1_extendhisi2"
9b66ebb1
PB
4186 [(set (match_operand:SI 0 "register_operand" "=l")
4187 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
4188 (clobber (match_scratch:SI 2 "=&l"))]
5b3e6663 4189 "TARGET_THUMB1 && !arm_arch6"
d5b7b3ae
RE
4190 "*
4191 {
4192 rtx ops[4];
4193 rtx mem = XEXP (operands[1], 0);
4194
4195 /* This code used to try to use 'V', and fix the address only if it was
4196 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4197 range of QImode offsets, and offsettable_address_p does a QImode
4198 address check. */
4199
4200 if (GET_CODE (mem) == CONST)
4201 mem = XEXP (mem, 0);
4202
4203 if (GET_CODE (mem) == LABEL_REF)
4204 return \"ldr\\t%0, %1\";
4205
4206 if (GET_CODE (mem) == PLUS)
4207 {
4208 rtx a = XEXP (mem, 0);
4209 rtx b = XEXP (mem, 1);
4210
4211 if (GET_CODE (a) == LABEL_REF
4212 && GET_CODE (b) == CONST_INT)
4213 return \"ldr\\t%0, %1\";
4214
4215 if (GET_CODE (b) == REG)
4216 return \"ldrsh\\t%0, %1\";
4217
4218 ops[1] = a;
4219 ops[2] = b;
4220 }
4221 else
4222 {
4223 ops[1] = mem;
4224 ops[2] = const0_rtx;
4225 }
e6d29d15
NS
4226
4227 gcc_assert (GET_CODE (ops[1]) == REG);
d5b7b3ae
RE
4228
4229 ops[0] = operands[0];
4230 ops[3] = operands[2];
4231 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4232 return \"\";
4233 }"
4234 [(set_attr "length" "4")
9b66ebb1 4235 (set_attr "type" "load_byte")
d5b7b3ae
RE
4236 (set_attr "pool_range" "1020")]
4237)
988337ca 4238
9b66ebb1
PB
4239;; We used to have an early-clobber on the scratch register here.
4240;; However, there's a bug somewhere in reload which means that this
4241;; can be partially ignored during spill allocation if the memory
e6d29d15 4242;; address also needs reloading; this causes us to die later on when
9b66ebb1
PB
4243;; we try to verify the operands. Fortunately, we don't really need
4244;; the early-clobber: we can always use operand 0 if operand 2
4245;; overlaps the address.
5b3e6663 4246(define_insn "*thumb1_extendhisi2_insn_v6"
9b66ebb1
PB
4247 [(set (match_operand:SI 0 "register_operand" "=l,l")
4248 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4249 (clobber (match_scratch:SI 2 "=X,l"))]
5b3e6663 4250 "TARGET_THUMB1 && arm_arch6"
9b66ebb1
PB
4251 "*
4252 {
4253 rtx ops[4];
4254 rtx mem;
4255
4256 if (which_alternative == 0)
4257 return \"sxth\\t%0, %1\";
4258
4259 mem = XEXP (operands[1], 0);
4260
4261 /* This code used to try to use 'V', and fix the address only if it was
4262 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4263 range of QImode offsets, and offsettable_address_p does a QImode
4264 address check. */
4265
4266 if (GET_CODE (mem) == CONST)
4267 mem = XEXP (mem, 0);
4268
4269 if (GET_CODE (mem) == LABEL_REF)
4270 return \"ldr\\t%0, %1\";
4271
4272 if (GET_CODE (mem) == PLUS)
4273 {
4274 rtx a = XEXP (mem, 0);
4275 rtx b = XEXP (mem, 1);
4276
4277 if (GET_CODE (a) == LABEL_REF
4278 && GET_CODE (b) == CONST_INT)
4279 return \"ldr\\t%0, %1\";
4280
4281 if (GET_CODE (b) == REG)
4282 return \"ldrsh\\t%0, %1\";
4283
4284 ops[1] = a;
4285 ops[2] = b;
4286 }
4287 else
4288 {
4289 ops[1] = mem;
4290 ops[2] = const0_rtx;
4291 }
4292
e6d29d15 4293 gcc_assert (GET_CODE (ops[1]) == REG);
9b66ebb1
PB
4294
4295 ops[0] = operands[0];
4296 if (reg_mentioned_p (operands[2], ops[1]))
4297 ops[3] = ops[0];
4298 else
4299 ops[3] = operands[2];
4300 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4301 return \"\";
4302 }"
4303 [(set_attr "length" "2,4")
4304 (set_attr "type" "alu_shift,load_byte")
4305 (set_attr "pool_range" "*,1020")]
4306)
4307
5b3e6663 4308;; This pattern will only be used when ldsh is not available
988337ca 4309(define_expand "extendhisi2_mem"
34757369 4310 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
988337ca 4311 (set (match_dup 3)
34757369 4312 (zero_extend:SI (match_dup 7)))
988337ca
RE
4313 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4314 (set (match_operand:SI 0 "" "")
4315 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
d5b7b3ae 4316 "TARGET_ARM"
988337ca 4317 "
5895f793
RE
4318 {
4319 rtx mem1, mem2;
4320 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4321
31fa16b6
RE
4322 mem1 = change_address (operands[1], QImode, addr);
4323 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5895f793
RE
4324 operands[0] = gen_lowpart (SImode, operands[0]);
4325 operands[1] = mem1;
4326 operands[2] = gen_reg_rtx (SImode);
4327 operands[3] = gen_reg_rtx (SImode);
4328 operands[6] = gen_reg_rtx (SImode);
4329 operands[7] = mem2;
988337ca 4330
5895f793
RE
4331 if (BYTES_BIG_ENDIAN)
4332 {
4333 operands[4] = operands[2];
4334 operands[5] = operands[3];
4335 }
4336 else
4337 {
4338 operands[4] = operands[3];
4339 operands[5] = operands[2];
4340 }
4341 }"
4342)
3a33f76f 4343
9b66ebb1
PB
4344(define_insn "*arm_extendhisi2"
4345 [(set (match_operand:SI 0 "s_register_operand" "=r")
4346 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4347 "TARGET_ARM && arm_arch4 && !arm_arch6"
5b3e6663 4348 "ldr%(sh%)\\t%0, %1"
9b66ebb1 4349 [(set_attr "type" "load_byte")
cca0a211 4350 (set_attr "predicable" "yes")
d5b7b3ae
RE
4351 (set_attr "pool_range" "256")
4352 (set_attr "neg_pool_range" "244")]
4353)
4cdb3ed4 4354
5b3e6663 4355;; ??? Check Thumb-2 pool range
9b66ebb1
PB
4356(define_insn "*arm_extendhisi2_v6"
4357 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4358 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
5b3e6663 4359 "TARGET_32BIT && arm_arch6"
9b66ebb1
PB
4360 "@
4361 sxth%?\\t%0, %1
5b3e6663 4362 ldr%(sh%)\\t%0, %1"
9b66ebb1
PB
4363 [(set_attr "type" "alu_shift,load_byte")
4364 (set_attr "predicable" "yes")
4365 (set_attr "pool_range" "*,256")
4366 (set_attr "neg_pool_range" "*,244")]
4367)
4368
4369(define_insn "*arm_extendhisi2addsi"
4370 [(set (match_operand:SI 0 "s_register_operand" "=r")
4371 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4372 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 4373 "TARGET_INT_SIMD"
9b66ebb1
PB
4374 "sxtah%?\\t%0, %2, %1"
4375)
4376
fd3f89a9
TG
4377(define_expand "extendqihi2"
4378 [(set (match_dup 2)
01577df7 4379 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
fd3f89a9 4380 (const_int 24)))
ff9940b0 4381 (set (match_operand:HI 0 "s_register_operand" "")
fd3f89a9
TG
4382 (ashiftrt:SI (match_dup 2)
4383 (const_int 24)))]
d5b7b3ae 4384 "TARGET_ARM"
fd3f89a9 4385 "
5895f793
RE
4386 {
4387 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4388 {
4389 emit_insn (gen_rtx_SET (VOIDmode,
4390 operands[0],
4391 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4392 DONE;
4393 }
4394 if (!s_register_operand (operands[1], QImode))
4395 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4396 operands[0] = gen_lowpart (SImode, operands[0]);
4397 operands[1] = gen_lowpart (SImode, operands[1]);
4398 operands[2] = gen_reg_rtx (SImode);
4399 }"
4400)
4cdb3ed4 4401
5b3e6663 4402(define_insn "*arm_extendqihi_insn"
1e1ab407 4403 [(set (match_operand:HI 0 "s_register_operand" "=r")
01577df7 4404 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
d5b7b3ae 4405 "TARGET_ARM && arm_arch4"
5b3e6663 4406 "ldr%(sb%)\\t%0, %1"
9b66ebb1 4407 [(set_attr "type" "load_byte")
cca0a211 4408 (set_attr "predicable" "yes")
d5b7b3ae
RE
4409 (set_attr "pool_range" "256")
4410 (set_attr "neg_pool_range" "244")]
4411)
4d818c85 4412
3a33f76f 4413(define_expand "extendqisi2"
fd3f89a9 4414 [(set (match_dup 2)
01577df7 4415 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
3a33f76f 4416 (const_int 24)))
ff9940b0 4417 (set (match_operand:SI 0 "s_register_operand" "")
fd3f89a9
TG
4418 (ashiftrt:SI (match_dup 2)
4419 (const_int 24)))]
d5b7b3ae 4420 "TARGET_EITHER"
3a33f76f 4421 "
d5b7b3ae 4422 {
9b66ebb1 4423 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
d5b7b3ae 4424 {
9b66ebb1 4425 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
d5b7b3ae
RE
4426 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4427 DONE;
4428 }
9b66ebb1 4429
5895f793 4430 if (!s_register_operand (operands[1], QImode))
d5b7b3ae 4431 operands[1] = copy_to_mode_reg (QImode, operands[1]);
d5b7b3ae 4432
9b66ebb1
PB
4433 if (arm_arch6)
4434 {
4435 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4436 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4437 DONE;
d5b7b3ae 4438 }
9b66ebb1
PB
4439
4440 operands[1] = gen_lowpart (SImode, operands[1]);
4441 operands[2] = gen_reg_rtx (SImode);
d5b7b3ae
RE
4442 }"
4443)
4cdb3ed4 4444
9b66ebb1
PB
4445(define_insn "*arm_extendqisi"
4446 [(set (match_operand:SI 0 "s_register_operand" "=r")
01577df7 4447 (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
9b66ebb1 4448 "TARGET_ARM && arm_arch4 && !arm_arch6"
5b3e6663 4449 "ldr%(sb%)\\t%0, %1"
9b66ebb1 4450 [(set_attr "type" "load_byte")
cca0a211 4451 (set_attr "predicable" "yes")
d5b7b3ae
RE
4452 (set_attr "pool_range" "256")
4453 (set_attr "neg_pool_range" "244")]
4454)
4d818c85 4455
9b66ebb1
PB
4456(define_insn "*arm_extendqisi_v6"
4457 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
01577df7
RE
4458 (sign_extend:SI
4459 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
9b66ebb1 4460 "TARGET_ARM && arm_arch6"
1e1ab407
RE
4461 "@
4462 sxtb%?\\t%0, %1
5b3e6663 4463 ldr%(sb%)\\t%0, %1"
9b66ebb1
PB
4464 [(set_attr "type" "alu_shift,load_byte")
4465 (set_attr "predicable" "yes")
9b66ebb1
PB
4466 (set_attr "pool_range" "*,256")
4467 (set_attr "neg_pool_range" "*,244")]
4468)
4469
4470(define_insn "*arm_extendqisi2addsi"
4471 [(set (match_operand:SI 0 "s_register_operand" "=r")
4472 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4473 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 4474 "TARGET_INT_SIMD"
9b66ebb1
PB
4475 "sxtab%?\\t%0, %2, %1"
4476 [(set_attr "type" "alu_shift")
c956e102 4477 (set_attr "insn" "xtab")
9b66ebb1
PB
4478 (set_attr "predicable" "yes")]
4479)
4480
5b3e6663 4481(define_insn "*thumb1_extendqisi2"
9b66ebb1
PB
4482 [(set (match_operand:SI 0 "register_operand" "=l,l")
4483 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
5b3e6663 4484 "TARGET_THUMB1 && !arm_arch6"
d5b7b3ae
RE
4485 "*
4486 {
4487 rtx ops[3];
4488 rtx mem = XEXP (operands[1], 0);
4489
4490 if (GET_CODE (mem) == CONST)
4491 mem = XEXP (mem, 0);
4492
4493 if (GET_CODE (mem) == LABEL_REF)
4494 return \"ldr\\t%0, %1\";
4495
4496 if (GET_CODE (mem) == PLUS
4497 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4498 return \"ldr\\t%0, %1\";
4499
4500 if (which_alternative == 0)
4501 return \"ldrsb\\t%0, %1\";
4502
4503 ops[0] = operands[0];
4504
4505 if (GET_CODE (mem) == PLUS)
4506 {
4507 rtx a = XEXP (mem, 0);
4508 rtx b = XEXP (mem, 1);
4509
4510 ops[1] = a;
4511 ops[2] = b;
4512
4513 if (GET_CODE (a) == REG)
4514 {
4515 if (GET_CODE (b) == REG)
4516 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4517 else if (REGNO (a) == REGNO (ops[0]))
5895f793
RE
4518 {
4519 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4520 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4521 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4522 }
d5b7b3ae
RE
4523 else
4524 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4525 }
d5b7b3ae
RE
4526 else
4527 {
e6d29d15 4528 gcc_assert (GET_CODE (b) == REG);
d5b7b3ae 4529 if (REGNO (b) == REGNO (ops[0]))
5895f793
RE
4530 {
4531 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4532 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4533 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4534 }
d5b7b3ae
RE
4535 else
4536 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4537 }
4538 }
4539 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4540 {
5895f793
RE
4541 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4542 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4543 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
d5b7b3ae
RE
4544 }
4545 else
4546 {
4547 ops[1] = mem;
4548 ops[2] = const0_rtx;
4549
4550 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4551 }
4552 return \"\";
4553 }"
4554 [(set_attr "length" "2,6")
9b66ebb1 4555 (set_attr "type" "load_byte,load_byte")
d5b7b3ae
RE
4556 (set_attr "pool_range" "32,32")]
4557)
4558
5b3e6663 4559(define_insn "*thumb1_extendqisi2_v6"
9b66ebb1
PB
4560 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4561 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
5b3e6663 4562 "TARGET_THUMB1 && arm_arch6"
9b66ebb1
PB
4563 "*
4564 {
4565 rtx ops[3];
4566 rtx mem;
4567
4568 if (which_alternative == 0)
4569 return \"sxtb\\t%0, %1\";
4570
4571 mem = XEXP (operands[1], 0);
4572
4573 if (GET_CODE (mem) == CONST)
4574 mem = XEXP (mem, 0);
4575
4576 if (GET_CODE (mem) == LABEL_REF)
4577 return \"ldr\\t%0, %1\";
4578
4579 if (GET_CODE (mem) == PLUS
4580 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4581 return \"ldr\\t%0, %1\";
4582
4583 if (which_alternative == 0)
4584 return \"ldrsb\\t%0, %1\";
4585
4586 ops[0] = operands[0];
4587
4588 if (GET_CODE (mem) == PLUS)
4589 {
4590 rtx a = XEXP (mem, 0);
4591 rtx b = XEXP (mem, 1);
4592
4593 ops[1] = a;
4594 ops[2] = b;
4595
4596 if (GET_CODE (a) == REG)
4597 {
4598 if (GET_CODE (b) == REG)
4599 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4600 else if (REGNO (a) == REGNO (ops[0]))
4601 {
4602 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4603 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4604 }
4605 else
4606 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4607 }
9b66ebb1
PB
4608 else
4609 {
e6d29d15 4610 gcc_assert (GET_CODE (b) == REG);
9b66ebb1
PB
4611 if (REGNO (b) == REGNO (ops[0]))
4612 {
4613 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4614 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4615 }
4616 else
4617 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4618 }
4619 }
4620 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4621 {
4622 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4623 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4624 }
4625 else
4626 {
4627 ops[1] = mem;
4628 ops[2] = const0_rtx;
4629
4630 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4631 }
4632 return \"\";
4633 }"
4634 [(set_attr "length" "2,2,4")
4635 (set_attr "type" "alu_shift,load_byte,load_byte")
4636 (set_attr "pool_range" "*,32,32")]
4637)
4638
1e3af7f6
NC
4639(define_expand "extendsfdf2"
4640 [(set (match_operand:DF 0 "s_register_operand" "")
4641 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
5b3e6663 4642 "TARGET_32BIT && TARGET_HARD_FLOAT"
1e3af7f6
NC
4643 ""
4644)
3a33f76f
RK
4645\f
4646;; Move insns (including loads and stores)
4647
4648;; XXX Just some ideas about movti.
ff9940b0
RE
4649;; I don't think these are a good idea on the arm, there just aren't enough
4650;; registers
3a33f76f 4651;;(define_expand "loadti"
ff9940b0 4652;; [(set (match_operand:TI 0 "s_register_operand" "")
3a33f76f
RK
4653;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4654;; "" "")
4655
4656;;(define_expand "storeti"
4657;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
ff9940b0 4658;; (match_operand:TI 1 "s_register_operand" ""))]
3a33f76f
RK
4659;; "" "")
4660
4661;;(define_expand "movti"
4662;; [(set (match_operand:TI 0 "general_operand" "")
4663;; (match_operand:TI 1 "general_operand" ""))]
4664;; ""
4665;; "
4666;;{
4667;; rtx insn;
4668;;
4669;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4670;; operands[1] = copy_to_reg (operands[1]);
4671;; if (GET_CODE (operands[0]) == MEM)
4672;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4673;; else if (GET_CODE (operands[1]) == MEM)
4674;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4675;; else
4676;; FAIL;
4677;;
4678;; emit_insn (insn);
4679;; DONE;
4680;;}")
4681
05713b80 4682;; Recognize garbage generated above.
3a33f76f
RK
4683
4684;;(define_insn ""
4685;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4686;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4687;; ""
4688;; "*
4689;; {
4690;; register mem = (which_alternative < 3);
cca0a211 4691;; register const char *template;
3a33f76f
RK
4692;;
4693;; operands[mem] = XEXP (operands[mem], 0);
4694;; switch (which_alternative)
4695;; {
4696;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4697;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4698;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4699;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4700;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4701;; case 5: template = \"stmia\\t%0, %M1\"; break;
4702;; }
0f447ef2
RE
4703;; output_asm_insn (template, operands);
4704;; return \"\";
3a33f76f
RK
4705;; }")
4706
d5b7b3ae
RE
4707(define_expand "movdi"
4708 [(set (match_operand:DI 0 "general_operand" "")
4709 (match_operand:DI 1 "general_operand" ""))]
4710 "TARGET_EITHER"
4711 "
b3a13419 4712 if (can_create_pseudo_p ())
d5b7b3ae 4713 {
d5b6e637
PB
4714 if (GET_CODE (operands[0]) != REG)
4715 operands[1] = force_reg (DImode, operands[1]);
d5b7b3ae
RE
4716 }
4717 "
4718)
3a33f76f 4719
d5b7b3ae 4720(define_insn "*arm_movdi"
9b901d50
RE
4721 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4722 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
9b66ebb1 4723 "TARGET_ARM
d5b6e637
PB
4724 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4725 && !TARGET_IWMMXT
4726 && ( register_operand (operands[0], DImode)
4727 || register_operand (operands[1], DImode))"
3a33f76f 4728 "*
9b901d50
RE
4729 switch (which_alternative)
4730 {
4731 case 0:
4732 case 1:
4733 case 2:
4734 return \"#\";
4735 default:
4736 return output_move_double (operands);
4737 }
d5b7b3ae 4738 "
2075b05d
RE
4739 [(set_attr "length" "8,12,16,8,8")
4740 (set_attr "type" "*,*,*,load2,store2")
4741 (set_attr "pool_range" "*,*,*,1020,*")
4742 (set_attr "neg_pool_range" "*,*,*,1008,*")]
d5b7b3ae
RE
4743)
4744
9b901d50
RE
4745(define_split
4746 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4747 (match_operand:ANY64 1 "const_double_operand" ""))]
5b3e6663 4748 "TARGET_32BIT
9b901d50
RE
4749 && reload_completed
4750 && (arm_const_double_inline_cost (operands[1])
4751 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4752 [(const_int 0)]
4753 "
4754 arm_split_constant (SET, SImode, curr_insn,
4755 INTVAL (gen_lowpart (SImode, operands[1])),
4756 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4757 arm_split_constant (SET, SImode, curr_insn,
4758 INTVAL (gen_highpart_mode (SImode,
4759 GET_MODE (operands[0]),
4760 operands[1])),
4761 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4762 DONE;
4763 "
4764)
4765
b4a58f80
RE
4766; If optimizing for size, or if we have load delay slots, then
4767; we want to split the constant into two separate operations.
4768; In both cases this may split a trivial part into a single data op
4769; leaving a single complex constant to load. We can also get longer
4770; offsets in a LDR which means we get better chances of sharing the pool
4771; entries. Finally, we can normally do a better job of scheduling
4772; LDR instructions than we can with LDM.
4773; This pattern will only match if the one above did not.
4774(define_split
4775 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4776 (match_operand:ANY64 1 "const_double_operand" ""))]
4777 "TARGET_ARM && reload_completed
4778 && arm_const_double_by_parts (operands[1])"
4779 [(set (match_dup 0) (match_dup 1))
4780 (set (match_dup 2) (match_dup 3))]
4781 "
4782 operands[2] = gen_highpart (SImode, operands[0]);
4783 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4784 operands[1]);
4785 operands[0] = gen_lowpart (SImode, operands[0]);
4786 operands[1] = gen_lowpart (SImode, operands[1]);
4787 "
4788)
4789
9b901d50
RE
4790(define_split
4791 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4792 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4793 "TARGET_EITHER && reload_completed"
4794 [(set (match_dup 0) (match_dup 1))
4795 (set (match_dup 2) (match_dup 3))]
4796 "
4797 operands[2] = gen_highpart (SImode, operands[0]);
4798 operands[3] = gen_highpart (SImode, operands[1]);
4799 operands[0] = gen_lowpart (SImode, operands[0]);
4800 operands[1] = gen_lowpart (SImode, operands[1]);
4801
4802 /* Handle a partial overlap. */
4803 if (rtx_equal_p (operands[0], operands[3]))
4804 {
4805 rtx tmp0 = operands[0];
4806 rtx tmp1 = operands[1];
4807
4808 operands[0] = operands[2];
4809 operands[1] = operands[3];
4810 operands[2] = tmp0;
4811 operands[3] = tmp1;
4812 }
4813 "
4814)
4815
fdd695fd
PB
4816;; We can't actually do base+index doubleword loads if the index and
4817;; destination overlap. Split here so that we at least have chance to
4818;; schedule.
4819(define_split
4820 [(set (match_operand:DI 0 "s_register_operand" "")
4821 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4822 (match_operand:SI 2 "s_register_operand" ""))))]
4823 "TARGET_LDRD
4824 && reg_overlap_mentioned_p (operands[0], operands[1])
4825 && reg_overlap_mentioned_p (operands[0], operands[2])"
4826 [(set (match_dup 4)
4827 (plus:SI (match_dup 1)
4828 (match_dup 2)))
4829 (set (match_dup 0)
4830 (mem:DI (match_dup 4)))]
4831 "
4832 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4833 "
4834)
4835
d5b7b3ae
RE
4836;;; ??? This should have alternatives for constants.
4837;;; ??? This was originally identical to the movdf_insn pattern.
4838;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4839;;; thumb_reorg with a memory reference.
5b3e6663 4840(define_insn "*thumb1_movdi_insn"
5895f793
RE
4841 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4842 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
5b3e6663 4843 "TARGET_THUMB1
9b66ebb1 4844 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
d5b7b3ae
RE
4845 && ( register_operand (operands[0], DImode)
4846 || register_operand (operands[1], DImode))"
4847 "*
4848 {
4849 switch (which_alternative)
4850 {
4851 default:
4852 case 0:
4853 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4854 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4855 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4856 case 1:
4857 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4858 case 2:
4859 operands[1] = GEN_INT (- INTVAL (operands[1]));
4860 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4861 case 3:
4862 return \"ldmia\\t%1, {%0, %H0}\";
4863 case 4:
4864 return \"stmia\\t%0, {%1, %H1}\";
4865 case 5:
4866 return thumb_load_double_from_address (operands);
4867 case 6:
f1c25d3b 4868 operands[2] = gen_rtx_MEM (SImode,
5895f793 4869 plus_constant (XEXP (operands[0], 0), 4));
d5b7b3ae
RE
4870 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4871 return \"\";
4872 case 7:
4873 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4874 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4875 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4876 }
4877 }"
4878 [(set_attr "length" "4,4,6,2,2,6,4,4")
9b66ebb1 4879 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d5b7b3ae
RE
4880 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4881)
3a33f76f 4882
ff9940b0
RE
4883(define_expand "movsi"
4884 [(set (match_operand:SI 0 "general_operand" "")
4885 (match_operand:SI 1 "general_operand" ""))]
d5b7b3ae 4886 "TARGET_EITHER"
ff9940b0 4887 "
2c3de459 4888 {
8426b956
RS
4889 rtx base, offset, tmp;
4890
5b3e6663 4891 if (TARGET_32BIT)
ff9940b0 4892 {
d6b4baa4 4893 /* Everything except mem = const or mem = mem can be done easily. */
d5b7b3ae
RE
4894 if (GET_CODE (operands[0]) == MEM)
4895 operands[1] = force_reg (SImode, operands[1]);
9b66ebb1
PB
4896 if (arm_general_register_operand (operands[0], SImode)
4897 && GET_CODE (operands[1]) == CONST_INT
d5b7b3ae
RE
4898 && !(const_ok_for_arm (INTVAL (operands[1]))
4899 || const_ok_for_arm (~INTVAL (operands[1]))))
4900 {
a406f566
MM
4901 arm_split_constant (SET, SImode, NULL_RTX,
4902 INTVAL (operands[1]), operands[0], NULL_RTX,
b3a13419 4903 optimize && can_create_pseudo_p ());
d5b7b3ae
RE
4904 DONE;
4905 }
571191af
PB
4906
4907 if (TARGET_USE_MOVT && !target_word_relocations
4908 && GET_CODE (operands[1]) == SYMBOL_REF
4909 && !flag_pic && !arm_tls_referenced_p (operands[1]))
4910 {
4911 arm_emit_movpair (operands[0], operands[1]);
4912 DONE;
4913 }
d5b7b3ae 4914 }
5b3e6663 4915 else /* TARGET_THUMB1... */
d5b7b3ae 4916 {
b3a13419 4917 if (can_create_pseudo_p ())
d5b7b3ae
RE
4918 {
4919 if (GET_CODE (operands[0]) != REG)
4920 operands[1] = force_reg (SImode, operands[1]);
4921 }
ff9940b0 4922 }
d3585b76 4923
8426b956
RS
4924 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
4925 {
4926 split_const (operands[1], &base, &offset);
4927 if (GET_CODE (base) == SYMBOL_REF
4928 && !offset_within_block_p (base, INTVAL (offset)))
4929 {
08a576fb 4930 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
8426b956
RS
4931 emit_move_insn (tmp, base);
4932 emit_insn (gen_addsi3 (operands[0], tmp, offset));
4933 DONE;
4934 }
4935 }
4936
d3585b76
DJ
4937 /* Recognize the case where operand[1] is a reference to thread-local
4938 data and load its address to a register. */
4939 if (arm_tls_referenced_p (operands[1]))
4940 {
4941 rtx tmp = operands[1];
4942 rtx addend = NULL;
4943
4944 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4945 {
4946 addend = XEXP (XEXP (tmp, 0), 1);
4947 tmp = XEXP (XEXP (tmp, 0), 0);
4948 }
4949
4950 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4951 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4952
b3a13419
ILT
4953 tmp = legitimize_tls_address (tmp,
4954 !can_create_pseudo_p () ? operands[0] : 0);
d3585b76
DJ
4955 if (addend)
4956 {
4957 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4958 tmp = force_operand (tmp, operands[0]);
4959 }
4960 operands[1] = tmp;
4961 }
4962 else if (flag_pic
4963 && (CONSTANT_P (operands[1])
4964 || symbol_mentioned_p (operands[1])
4965 || label_mentioned_p (operands[1])))
4966 operands[1] = legitimize_pic_address (operands[1], SImode,
b3a13419
ILT
4967 (!can_create_pseudo_p ()
4968 ? operands[0]
4969 : 0));
2c3de459 4970 }
5895f793
RE
4971 "
4972)
ff9940b0 4973
571191af
PB
4974;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
4975;; LO_SUM adds in the high bits. Fortunately these are opaque operations
4976;; so this does not matter.
4977(define_insn "*arm_movt"
4978 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
4979 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
4980 (match_operand:SI 2 "general_operand" "i")))]
4981 "TARGET_32BIT"
4982 "movt%?\t%0, #:upper16:%c2"
4983 [(set_attr "predicable" "yes")
4984 (set_attr "length" "4")]
4985)
4986
4987(define_insn "*arm_movw"
4988 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
4989 (high:SI (match_operand:SI 1 "general_operand" "i")))]
4990 "TARGET_32BIT"
4991 "movw%?\t%0, #:lower16:%c1"
4992 [(set_attr "predicable" "yes")
4993 (set_attr "length" "4")]
4994)
4995
d5b7b3ae 4996(define_insn "*arm_movsi_insn"
f5c630c3
PB
4997 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
4998 (match_operand:SI 1 "general_operand" "rk, I,K,N,mi,rk"))]
5a9335ef 4999 "TARGET_ARM && ! TARGET_IWMMXT
9b66ebb1 5000 && !(TARGET_HARD_FLOAT && TARGET_VFP)
d5b7b3ae
RE
5001 && ( register_operand (operands[0], SImode)
5002 || register_operand (operands[1], SImode))"
4cdb3ed4 5003 "@
f5c630c3 5004 mov%?\\t%0, %1
4cdb3ed4
RE
5005 mov%?\\t%0, %1
5006 mvn%?\\t%0, #%B1
5b3e6663 5007 movw%?\\t%0, %1
4cdb3ed4
RE
5008 ldr%?\\t%0, %1
5009 str%?\\t%1, %0"
f5c630c3 5010 [(set_attr "type" "*,*,*,*,load1,store1")
cca0a211 5011 (set_attr "predicable" "yes")
f5c630c3
PB
5012 (set_attr "pool_range" "*,*,*,*,4096,*")
5013 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
d5b7b3ae 5014)
091426d3
RE
5015
5016(define_split
9b66ebb1 5017 [(set (match_operand:SI 0 "arm_general_register_operand" "")
091426d3 5018 (match_operand:SI 1 "const_int_operand" ""))]
5b3e6663 5019 "TARGET_32BIT
5895f793
RE
5020 && (!(const_ok_for_arm (INTVAL (operands[1]))
5021 || const_ok_for_arm (~INTVAL (operands[1]))))"
091426d3
RE
5022 [(clobber (const_int 0))]
5023 "
a406f566
MM
5024 arm_split_constant (SET, SImode, NULL_RTX,
5025 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
091426d3 5026 DONE;
5895f793
RE
5027 "
5028)
ff9940b0 5029
5b3e6663 5030(define_insn "*thumb1_movsi_insn"
f5c630c3
PB
5031 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5032 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
5b3e6663 5033 "TARGET_THUMB1
d5b7b3ae
RE
5034 && ( register_operand (operands[0], SImode)
5035 || register_operand (operands[1], SImode))"
5036 "@
5037 mov %0, %1
5038 mov %0, %1
5039 #
5040 #
5041 ldmia\\t%1, {%0}
5042 stmia\\t%0, {%1}
5043 ldr\\t%0, %1
5044 str\\t%1, %0
5045 mov\\t%0, %1"
5046 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
9b66ebb1 5047 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
d5b7b3ae
RE
5048 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
5049)
5050
5051(define_split
5052 [(set (match_operand:SI 0 "register_operand" "")
5053 (match_operand:SI 1 "const_int_operand" ""))]
5b3e6663 5054 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
d5b7b3ae
RE
5055 [(set (match_dup 0) (match_dup 1))
5056 (set (match_dup 0) (neg:SI (match_dup 0)))]
5057 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
5058)
5059
5060(define_split
5061 [(set (match_operand:SI 0 "register_operand" "")
5062 (match_operand:SI 1 "const_int_operand" ""))]
5b3e6663 5063 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
d5b7b3ae
RE
5064 [(set (match_dup 0) (match_dup 1))
5065 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
5066 "
5067 {
5068 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
5069 unsigned HOST_WIDE_INT mask = 0xff;
5070 int i;
5071
5072 for (i = 0; i < 25; i++)
5073 if ((val & (mask << i)) == val)
5074 break;
5075
3a4edb44 5076 /* Shouldn't happen, but we don't want to split if the shift is zero. */
d5b7b3ae
RE
5077 if (i == 0)
5078 FAIL;
5079
5080 operands[1] = GEN_INT (val >> i);
5081 operands[2] = GEN_INT (i);
5082 }"
5083)
5084
f12c5ef3
RE
5085;; When generating pic, we need to load the symbol offset into a register.
5086;; So that the optimizer does not confuse this with a normal symbol load
5087;; we use an unspec. The offset will be loaded from a constant pool entry,
5088;; since that is the only type of relocation we can use.
5089
5090;; The rather odd constraints on the following are to force reload to leave
5091;; the insn alone, and to force the minipool generation pass to then move
5092;; the GOT symbol to memory.
fef37aaf 5093
4bec9f7d 5094(define_insn "pic_load_addr_arm"
fef37aaf 5095 [(set (match_operand:SI 0 "s_register_operand" "=r")
b15bca31 5096 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4bec9f7d 5097 "TARGET_ARM && flag_pic"
f12c5ef3 5098 "ldr%?\\t%0, %1"
9b66ebb1 5099 [(set_attr "type" "load1")
4bec9f7d
NC
5100 (set (attr "pool_range") (const_int 4096))
5101 (set (attr "neg_pool_range") (const_int 4084))]
5102)
5103
5b3e6663 5104(define_insn "pic_load_addr_thumb1"
4bec9f7d 5105 [(set (match_operand:SI 0 "s_register_operand" "=l")
b15bca31 5106 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5b3e6663 5107 "TARGET_THUMB1 && flag_pic"
4bec9f7d 5108 "ldr\\t%0, %1"
9b66ebb1 5109 [(set_attr "type" "load1")
4bec9f7d 5110 (set (attr "pool_range") (const_int 1024))]
d5b7b3ae 5111)
fef37aaf 5112
d5b7b3ae 5113(define_insn "pic_add_dot_plus_four"
6137ba90 5114 [(set (match_operand:SI 0 "register_operand" "=r")
f9bd1a89
RS
5115 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5116 (const_int 4)
10ae7c7b
DJ
5117 (match_operand 2 "" "")]
5118 UNSPEC_PIC_BASE))]
5b3e6663 5119 "TARGET_THUMB1"
d5b7b3ae 5120 "*
f16fe45f
DJ
5121 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5122 INTVAL (operands[2]));
d5b7b3ae
RE
5123 return \"add\\t%0, %|pc\";
5124 "
5125 [(set_attr "length" "2")]
5126)
fef37aaf
RE
5127
5128(define_insn "pic_add_dot_plus_eight"
6137ba90 5129 [(set (match_operand:SI 0 "register_operand" "=r")
f9bd1a89
RS
5130 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5131 (const_int 8)
10ae7c7b
DJ
5132 (match_operand 2 "" "")]
5133 UNSPEC_PIC_BASE))]
d3585b76 5134 "TARGET_ARM"
dfa08768 5135 "*
f16fe45f
DJ
5136 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5137 INTVAL (operands[2]));
6137ba90 5138 return \"add%?\\t%0, %|pc, %1\";
d5b7b3ae 5139 "
cca0a211 5140 [(set_attr "predicable" "yes")]
d5b7b3ae 5141)
fef37aaf 5142
d3585b76
DJ
5143(define_insn "tls_load_dot_plus_eight"
5144 [(set (match_operand:SI 0 "register_operand" "+r")
f9bd1a89
RS
5145 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5146 (const_int 8)
10ae7c7b
DJ
5147 (match_operand 2 "" "")]
5148 UNSPEC_PIC_BASE)))]
d3585b76
DJ
5149 "TARGET_ARM"
5150 "*
f16fe45f
DJ
5151 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5152 INTVAL (operands[2]));
d3585b76
DJ
5153 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5154 "
5155 [(set_attr "predicable" "yes")]
5156)
5157
5158;; PIC references to local variables can generate pic_add_dot_plus_eight
5159;; followed by a load. These sequences can be crunched down to
5160;; tls_load_dot_plus_eight by a peephole.
5161
5162(define_peephole2
f9bd1a89
RS
5163 [(set (match_operand:SI 0 "register_operand" "")
5164 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5165 (const_int 8)
5166 (match_operand 1 "" "")]
5167 UNSPEC_PIC_BASE))
d3585b76
DJ
5168 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5169 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
f9bd1a89
RS
5170 [(set (match_dup 2)
5171 (mem:SI (unspec:SI [(match_dup 3)
5172 (const_int 8)
5173 (match_dup 1)]
5174 UNSPEC_PIC_BASE)))]
d3585b76
DJ
5175 ""
5176)
5177
9403b7f7
RS
5178(define_insn "pic_offset_arm"
5179 [(set (match_operand:SI 0 "register_operand" "=r")
5180 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5181 (unspec:SI [(match_operand:SI 2 "" "X")]
5182 UNSPEC_PIC_OFFSET))))]
5183 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5184 "ldr%?\\t%0, [%1,%2]"
5185 [(set_attr "type" "load1")]
5186)
5187
c1163e75
PB
5188(define_expand "builtin_setjmp_receiver"
5189 [(label_ref (match_operand 0 "" ""))]
5190 "flag_pic"
5191 "
5192{
fe013435
PB
5193 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5194 register. */
020a4035
RE
5195 if (arm_pic_register != INVALID_REGNUM)
5196 arm_load_pic_register (1UL << 3);
c1163e75
PB
5197 DONE;
5198}")
5199
ff9940b0
RE
5200;; If copying one reg to another we can set the condition codes according to
5201;; its value. Such a move is common after a return from subroutine and the
5202;; result is being tested against zero.
5203
4cdb3ed4 5204(define_insn "*movsi_compare0"
48a08b9c 5205 [(set (reg:CC CC_REGNUM)
d5b7b3ae
RE
5206 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5207 (const_int 0)))
5208 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5209 (match_dup 1))]
5b3e6663 5210 "TARGET_32BIT"
0f447ef2 5211 "@
c63165be 5212 cmp%?\\t%0, #0
5b3e6663 5213 sub%.\\t%0, %1, #0"
d5b7b3ae
RE
5214 [(set_attr "conds" "set")]
5215)
3a33f76f 5216
3a33f76f
RK
5217;; Subroutine to store a half word from a register into memory.
5218;; Operand 0 is the source register (HImode)
fd3f89a9 5219;; Operand 1 is the destination address in a register (SImode)
3a33f76f 5220
ff9940b0 5221;; In both this routine and the next, we must be careful not to spill
ddd5a7c1 5222;; a memory address of reg+large_const into a separate PLUS insn, since this
ff9940b0
RE
5223;; can generate unrecognizable rtl.
5224
3a33f76f 5225(define_expand "storehi"
fd3f89a9 5226 [;; store the low byte
7a0a1f09 5227 (set (match_operand 1 "" "") (match_dup 3))
3a33f76f 5228 ;; extract the high byte
fd3f89a9
TG
5229 (set (match_dup 2)
5230 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3a33f76f 5231 ;; store the high byte
c9389e79 5232 (set (match_dup 4) (match_dup 5))]
d5b7b3ae 5233 "TARGET_ARM"
3a33f76f 5234 "
5895f793 5235 {
792760b9
RK
5236 rtx op1 = operands[1];
5237 rtx addr = XEXP (op1, 0);
5895f793
RE
5238 enum rtx_code code = GET_CODE (addr);
5239
5240 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5241 || code == MINUS)
792760b9 5242 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5895f793 5243
792760b9 5244 operands[4] = adjust_address (op1, QImode, 1);
f4ef873c 5245 operands[1] = adjust_address (operands[1], QImode, 0);
5895f793
RE
5246 operands[3] = gen_lowpart (QImode, operands[0]);
5247 operands[0] = gen_lowpart (SImode, operands[0]);
c9389e79
RE
5248 operands[2] = gen_reg_rtx (SImode);
5249 operands[5] = gen_lowpart (QImode, operands[2]);
5895f793
RE
5250 }"
5251)
3a33f76f 5252
fe241a29 5253(define_expand "storehi_bigend"
7a0a1f09 5254 [(set (match_dup 4) (match_dup 3))
fe241a29
RE
5255 (set (match_dup 2)
5256 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
c9389e79 5257 (set (match_operand 1 "" "") (match_dup 5))]
d5b7b3ae 5258 "TARGET_ARM"
3a33f76f 5259 "
5895f793 5260 {
792760b9
RK
5261 rtx op1 = operands[1];
5262 rtx addr = XEXP (op1, 0);
5895f793
RE
5263 enum rtx_code code = GET_CODE (addr);
5264
5265 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5266 || code == MINUS)
792760b9 5267 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5895f793 5268
792760b9 5269 operands[4] = adjust_address (op1, QImode, 1);
f4ef873c 5270 operands[1] = adjust_address (operands[1], QImode, 0);
5895f793
RE
5271 operands[3] = gen_lowpart (QImode, operands[0]);
5272 operands[0] = gen_lowpart (SImode, operands[0]);
5273 operands[2] = gen_reg_rtx (SImode);
c9389e79 5274 operands[5] = gen_lowpart (QImode, operands[2]);
5895f793
RE
5275 }"
5276)
fe241a29
RE
5277
5278;; Subroutine to store a half word integer constant into memory.
5279(define_expand "storeinthi"
7a0a1f09 5280 [(set (match_operand 0 "" "")
c9389e79 5281 (match_operand 1 "" ""))
5d5603e2 5282 (set (match_dup 3) (match_dup 2))]
d5b7b3ae 5283 "TARGET_ARM"
fe241a29 5284 "
5895f793
RE
5285 {
5286 HOST_WIDE_INT value = INTVAL (operands[1]);
5287 rtx addr = XEXP (operands[0], 0);
792760b9 5288 rtx op0 = operands[0];
5895f793 5289 enum rtx_code code = GET_CODE (addr);
fe241a29 5290
5895f793
RE
5291 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5292 || code == MINUS)
792760b9 5293 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
fe241a29 5294
5895f793
RE
5295 operands[1] = gen_reg_rtx (SImode);
5296 if (BYTES_BIG_ENDIAN)
5297 {
5298 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5299 if ((value & 255) == ((value >> 8) & 255))
5300 operands[2] = operands[1];
5301 else
5302 {
5303 operands[2] = gen_reg_rtx (SImode);
5304 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5305 }
5306 }
5307 else
5308 {
5309 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5310 if ((value & 255) == ((value >> 8) & 255))
5311 operands[2] = operands[1];
5312 else
5313 {
5314 operands[2] = gen_reg_rtx (SImode);
5315 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5316 }
5317 }
fe241a29 5318
792760b9 5319 operands[3] = adjust_address (op0, QImode, 1);
f4ef873c 5320 operands[0] = adjust_address (operands[0], QImode, 0);
5d5603e2 5321 operands[2] = gen_lowpart (QImode, operands[2]);
c9389e79 5322 operands[1] = gen_lowpart (QImode, operands[1]);
5895f793
RE
5323 }"
5324)
3a33f76f 5325
4cdb3ed4
RE
5326(define_expand "storehi_single_op"
5327 [(set (match_operand:HI 0 "memory_operand" "")
5328 (match_operand:HI 1 "general_operand" ""))]
5b3e6663 5329 "TARGET_32BIT && arm_arch4"
4cdb3ed4 5330 "
5895f793 5331 if (!s_register_operand (operands[1], HImode))
4cdb3ed4 5332 operands[1] = copy_to_mode_reg (HImode, operands[1]);
5895f793
RE
5333 "
5334)
4cdb3ed4 5335
3a33f76f
RK
5336(define_expand "movhi"
5337 [(set (match_operand:HI 0 "general_operand" "")
fd3f89a9 5338 (match_operand:HI 1 "general_operand" ""))]
d5b7b3ae 5339 "TARGET_EITHER"
3a33f76f 5340 "
d5b7b3ae 5341 if (TARGET_ARM)
3a33f76f 5342 {
b3a13419 5343 if (can_create_pseudo_p ())
d5b7b3ae
RE
5344 {
5345 if (GET_CODE (operands[0]) == MEM)
3a33f76f 5346 {
d5b7b3ae
RE
5347 if (arm_arch4)
5348 {
5349 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5350 DONE;
5351 }
5352 if (GET_CODE (operands[1]) == CONST_INT)
5353 emit_insn (gen_storeinthi (operands[0], operands[1]));
fe241a29 5354 else
d5b7b3ae
RE
5355 {
5356 if (GET_CODE (operands[1]) == MEM)
5357 operands[1] = force_reg (HImode, operands[1]);
5358 if (BYTES_BIG_ENDIAN)
5359 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5360 else
5361 emit_insn (gen_storehi (operands[1], operands[0]));
5362 }
5363 DONE;
3a33f76f 5364 }
d5b7b3ae
RE
5365 /* Sign extend a constant, and keep it in an SImode reg. */
5366 else if (GET_CODE (operands[1]) == CONST_INT)
ff9940b0 5367 {
d5b7b3ae
RE
5368 rtx reg = gen_reg_rtx (SImode);
5369 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5370
5371 /* If the constant is already valid, leave it alone. */
5895f793 5372 if (!const_ok_for_arm (val))
d5b7b3ae
RE
5373 {
5374 /* If setting all the top bits will make the constant
5375 loadable in a single instruction, then set them.
5376 Otherwise, sign extend the number. */
5377
5895f793 5378 if (const_ok_for_arm (~(val | ~0xffff)))
d5b7b3ae
RE
5379 val |= ~0xffff;
5380 else if (val & 0x8000)
5381 val |= ~0xffff;
5382 }
5383
5384 emit_insn (gen_movsi (reg, GEN_INT (val)));
5d5603e2 5385 operands[1] = gen_lowpart (HImode, reg);
ff9940b0 5386 }
b3a13419 5387 else if (arm_arch4 && optimize && can_create_pseudo_p ()
b41caf7c
RE
5388 && GET_CODE (operands[1]) == MEM)
5389 {
5390 rtx reg = gen_reg_rtx (SImode);
5391
5392 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5393 operands[1] = gen_lowpart (HImode, reg);
5394 }
5895f793 5395 else if (!arm_arch4)
4cdb3ed4 5396 {
d5b7b3ae
RE
5397 if (GET_CODE (operands[1]) == MEM)
5398 {
61f0ccff
RE
5399 rtx base;
5400 rtx offset = const0_rtx;
5401 rtx reg = gen_reg_rtx (SImode);
5402
5403 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5404 || (GET_CODE (base) == PLUS
5405 && (GET_CODE (offset = XEXP (base, 1))
5406 == CONST_INT)
5407 && ((INTVAL(offset) & 1) != 1)
5408 && GET_CODE (base = XEXP (base, 0)) == REG))
5409 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
0502226c 5410 {
0a2aaacc 5411 rtx new_rtx;
61f0ccff 5412
0a2aaacc
KG
5413 new_rtx = widen_memory_access (operands[1], SImode,
5414 ((INTVAL (offset) & ~3)
5415 - INTVAL (offset)));
5416 emit_insn (gen_movsi (reg, new_rtx));
61f0ccff
RE
5417 if (((INTVAL (offset) & 2) != 0)
5418 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5419 {
5420 rtx reg2 = gen_reg_rtx (SImode);
5421
5422 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5423 reg = reg2;
5424 }
0502226c 5425 }
61f0ccff
RE
5426 else
5427 emit_insn (gen_movhi_bytes (reg, operands[1]));
5428
5429 operands[1] = gen_lowpart (HImode, reg);
d5b7b3ae
RE
5430 }
5431 }
5432 }
d6b4baa4 5433 /* Handle loading a large integer during reload. */
d5b7b3ae 5434 else if (GET_CODE (operands[1]) == CONST_INT
5895f793
RE
5435 && !const_ok_for_arm (INTVAL (operands[1]))
5436 && !const_ok_for_arm (~INTVAL (operands[1])))
d5b7b3ae
RE
5437 {
5438 /* Writing a constant to memory needs a scratch, which should
5439 be handled with SECONDARY_RELOADs. */
e6d29d15 5440 gcc_assert (GET_CODE (operands[0]) == REG);
d5b7b3ae
RE
5441
5442 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5443 emit_insn (gen_movsi (operands[0], operands[1]));
5444 DONE;
5445 }
5446 }
5b3e6663
PB
5447 else if (TARGET_THUMB2)
5448 {
5449 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
b3a13419 5450 if (can_create_pseudo_p ())
5b3e6663
PB
5451 {
5452 if (GET_CODE (operands[0]) != REG)
5453 operands[1] = force_reg (HImode, operands[1]);
5454 /* Zero extend a constant, and keep it in an SImode reg. */
5455 else if (GET_CODE (operands[1]) == CONST_INT)
5456 {
5457 rtx reg = gen_reg_rtx (SImode);
5458 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5459
5460 emit_insn (gen_movsi (reg, GEN_INT (val)));
5461 operands[1] = gen_lowpart (HImode, reg);
5462 }
5463 }
5464 }
5465 else /* TARGET_THUMB1 */
d5b7b3ae 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 (HImode, reg);
5475 }
d5b7b3ae
RE
5476
5477 /* ??? We shouldn't really get invalid addresses here, but this can
5895f793 5478 happen if we are passed a SP (never OK for HImode/QImode) or
331d9186
PB
5479 virtual register (also rejected as illegitimate for HImode/QImode)
5480 relative address. */
d5b7b3ae
RE
5481 /* ??? This should perhaps be fixed elsewhere, for instance, in
5482 fixup_stack_1, by checking for other kinds of invalid addresses,
5483 e.g. a bare reference to a virtual register. This may confuse the
5484 alpha though, which must handle this case differently. */
5485 if (GET_CODE (operands[0]) == MEM
5895f793
RE
5486 && !memory_address_p (GET_MODE (operands[0]),
5487 XEXP (operands[0], 0)))
792760b9
RK
5488 operands[0]
5489 = replace_equiv_address (operands[0],
5490 copy_to_reg (XEXP (operands[0], 0)));
d5b7b3ae
RE
5491
5492 if (GET_CODE (operands[1]) == MEM
5895f793
RE
5493 && !memory_address_p (GET_MODE (operands[1]),
5494 XEXP (operands[1], 0)))
792760b9
RK
5495 operands[1]
5496 = replace_equiv_address (operands[1],
5497 copy_to_reg (XEXP (operands[1], 0)));
78a5d727
RE
5498
5499 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5500 {
5501 rtx reg = gen_reg_rtx (SImode);
5502
5503 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5504 operands[1] = gen_lowpart (HImode, reg);
5505 }
5506
5507 if (GET_CODE (operands[0]) == MEM)
5508 operands[1] = force_reg (HImode, operands[1]);
d5b7b3ae 5509 }
d5b7b3ae 5510 else if (GET_CODE (operands[1]) == CONST_INT
ce92b223 5511 && !satisfies_constraint_I (operands[1]))
d5b7b3ae 5512 {
78a5d727
RE
5513 /* Handle loading a large integer during reload. */
5514
d5b7b3ae
RE
5515 /* Writing a constant to memory needs a scratch, which should
5516 be handled with SECONDARY_RELOADs. */
e6d29d15 5517 gcc_assert (GET_CODE (operands[0]) == REG);
d5b7b3ae 5518
f1c25d3b 5519 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
d5b7b3ae
RE
5520 emit_insn (gen_movsi (operands[0], operands[1]));
5521 DONE;
5522 }
3a33f76f 5523 }
d5b7b3ae
RE
5524 "
5525)
5526
5b3e6663 5527(define_insn "*thumb1_movhi_insn"
f954388e
RE
5528 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5529 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
5b3e6663 5530 "TARGET_THUMB1
d5b7b3ae
RE
5531 && ( register_operand (operands[0], HImode)
5532 || register_operand (operands[1], HImode))"
5533 "*
5534 switch (which_alternative)
f57b1ad3 5535 {
d5b7b3ae
RE
5536 case 0: return \"add %0, %1, #0\";
5537 case 2: return \"strh %1, %0\";
5538 case 3: return \"mov %0, %1\";
5539 case 4: return \"mov %0, %1\";
5540 case 5: return \"mov %0, %1\";
e6d29d15 5541 default: gcc_unreachable ();
d5b7b3ae
RE
5542 case 1:
5543 /* The stack pointer can end up being taken as an index register.
5544 Catch this case here and deal with it. */
5545 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5546 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5547 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5548 {
5549 rtx ops[2];
5550 ops[0] = operands[0];
5551 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5552
5553 output_asm_insn (\"mov %0, %1\", ops);
5554
5555 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5556
5557 }
5558 return \"ldrh %0, %1\";
5559 }"
5560 [(set_attr "length" "2,4,2,2,2,2")
9b66ebb1 5561 (set_attr "type" "*,load1,store1,*,*,*")]
d5b7b3ae 5562)
f57b1ad3 5563
3a33f76f 5564
988337ca 5565(define_expand "movhi_bytes"
34757369 5566 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
988337ca 5567 (set (match_dup 3)
34757369 5568 (zero_extend:SI (match_dup 6)))
988337ca
RE
5569 (set (match_operand:SI 0 "" "")
5570 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
d5b7b3ae 5571 "TARGET_ARM"
988337ca 5572 "
5895f793
RE
5573 {
5574 rtx mem1, mem2;
5575 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5576
31fa16b6
RE
5577 mem1 = change_address (operands[1], QImode, addr);
5578 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5895f793
RE
5579 operands[0] = gen_lowpart (SImode, operands[0]);
5580 operands[1] = mem1;
5581 operands[2] = gen_reg_rtx (SImode);
5582 operands[3] = gen_reg_rtx (SImode);
5583 operands[6] = mem2;
988337ca 5584
5895f793
RE
5585 if (BYTES_BIG_ENDIAN)
5586 {
5587 operands[4] = operands[2];
5588 operands[5] = operands[3];
5589 }
5590 else
5591 {
5592 operands[4] = operands[3];
5593 operands[5] = operands[2];
5594 }
5595 }"
5596)
988337ca 5597
fe241a29
RE
5598(define_expand "movhi_bigend"
5599 [(set (match_dup 2)
5600 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5601 (const_int 16)))
5602 (set (match_dup 3)
5603 (ashiftrt:SI (match_dup 2) (const_int 16)))
5604 (set (match_operand:HI 0 "s_register_operand" "")
c9389e79 5605 (match_dup 4))]
d5b7b3ae 5606 "TARGET_ARM"
fe241a29
RE
5607 "
5608 operands[2] = gen_reg_rtx (SImode);
5609 operands[3] = gen_reg_rtx (SImode);
c9389e79 5610 operands[4] = gen_lowpart (HImode, operands[3]);
5895f793
RE
5611 "
5612)
3a33f76f 5613
05713b80 5614;; Pattern to recognize insn generated default case above
4cdb3ed4 5615(define_insn "*movhi_insn_arch4"
d5b7b3ae 5616 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
5895f793 5617 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
d5b7b3ae
RE
5618 "TARGET_ARM
5619 && arm_arch4
4cdb3ed4
RE
5620 && (GET_CODE (operands[1]) != CONST_INT
5621 || const_ok_for_arm (INTVAL (operands[1]))
5622 || const_ok_for_arm (~INTVAL (operands[1])))"
5623 "@
5624 mov%?\\t%0, %1\\t%@ movhi
5625 mvn%?\\t%0, #%B1\\t%@ movhi
5b3e6663
PB
5626 str%(h%)\\t%1, %0\\t%@ movhi
5627 ldr%(h%)\\t%0, %1\\t%@ movhi"
9b66ebb1 5628 [(set_attr "type" "*,*,store1,load1")
cca0a211 5629 (set_attr "predicable" "yes")
d5b7b3ae
RE
5630 (set_attr "pool_range" "*,*,*,256")
5631 (set_attr "neg_pool_range" "*,*,*,244")]
5632)
4cdb3ed4 5633
4cdb3ed4 5634(define_insn "*movhi_bytes"
988337ca
RE
5635 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5636 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
61f0ccff 5637 "TARGET_ARM"
988337ca
RE
5638 "@
5639 mov%?\\t%0, %1\\t%@ movhi
cca0a211
RE
5640 mvn%?\\t%0, #%B1\\t%@ movhi"
5641 [(set_attr "predicable" "yes")]
5642)
988337ca 5643
2591db65
RE
5644(define_expand "thumb_movhi_clobber"
5645 [(set (match_operand:HI 0 "memory_operand" "")
5646 (match_operand:HI 1 "register_operand" ""))
5647 (clobber (match_operand:DI 2 "register_operand" ""))]
5b3e6663 5648 "TARGET_THUMB1"
2591db65
RE
5649 "
5650 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5651 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5652 {
5653 emit_insn (gen_movhi (operands[0], operands[1]));
5654 DONE;
5655 }
5656 /* XXX Fixme, need to handle other cases here as well. */
5657 gcc_unreachable ();
5658 "
d5b7b3ae
RE
5659)
5660
f9cc092a
RE
5661;; We use a DImode scratch because we may occasionally need an additional
5662;; temporary if the address isn't offsettable -- push_reload doesn't seem
5663;; to take any notice of the "o" constraints on reload_memory_operand operand.
c1d5bfb9 5664(define_expand "reload_outhi"
d5b7b3ae 5665 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5895f793
RE
5666 (match_operand:HI 1 "s_register_operand" "r")
5667 (match_operand:DI 2 "s_register_operand" "=&l")])]
d5b7b3ae
RE
5668 "TARGET_EITHER"
5669 "if (TARGET_ARM)
5670 arm_reload_out_hi (operands);
5671 else
5672 thumb_reload_out_hi (operands);
c1d5bfb9 5673 DONE;
d5b7b3ae
RE
5674 "
5675)
c1d5bfb9 5676
988337ca
RE
5677(define_expand "reload_inhi"
5678 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
d5b7b3ae 5679 (match_operand:HI 1 "arm_reload_memory_operand" "o")
f9cc092a 5680 (match_operand:DI 2 "s_register_operand" "=&r")])]
61f0ccff 5681 "TARGET_EITHER"
988337ca 5682 "
d5b7b3ae
RE
5683 if (TARGET_ARM)
5684 arm_reload_in_hi (operands);
5685 else
5686 thumb_reload_out_hi (operands);
988337ca
RE
5687 DONE;
5688")
5689
ff9940b0
RE
5690(define_expand "movqi"
5691 [(set (match_operand:QI 0 "general_operand" "")
5692 (match_operand:QI 1 "general_operand" ""))]
d5b7b3ae 5693 "TARGET_EITHER"
ff9940b0 5694 "
78a5d727 5695 /* Everything except mem = const or mem = mem can be done easily */
b41caf7c 5696
b3a13419 5697 if (can_create_pseudo_p ())
d5b7b3ae 5698 {
78a5d727
RE
5699 if (GET_CODE (operands[1]) == CONST_INT)
5700 {
5701 rtx reg = gen_reg_rtx (SImode);
5702
5703 emit_insn (gen_movsi (reg, operands[1]));
5704 operands[1] = gen_lowpart (QImode, reg);
5705 }
d5b7b3ae 5706
78a5d727
RE
5707 if (TARGET_THUMB)
5708 {
d5b7b3ae 5709 /* ??? We shouldn't really get invalid addresses here, but this can
5895f793 5710 happen if we are passed a SP (never OK for HImode/QImode) or
331d9186
PB
5711 virtual register (also rejected as illegitimate for HImode/QImode)
5712 relative address. */
d5b7b3ae
RE
5713 /* ??? This should perhaps be fixed elsewhere, for instance, in
5714 fixup_stack_1, by checking for other kinds of invalid addresses,
5715 e.g. a bare reference to a virtual register. This may confuse the
5716 alpha though, which must handle this case differently. */
5717 if (GET_CODE (operands[0]) == MEM
5895f793 5718 && !memory_address_p (GET_MODE (operands[0]),
d5b7b3ae 5719 XEXP (operands[0], 0)))
792760b9
RK
5720 operands[0]
5721 = replace_equiv_address (operands[0],
5722 copy_to_reg (XEXP (operands[0], 0)));
5895f793
RE
5723 if (GET_CODE (operands[1]) == MEM
5724 && !memory_address_p (GET_MODE (operands[1]),
d5b7b3ae 5725 XEXP (operands[1], 0)))
792760b9
RK
5726 operands[1]
5727 = replace_equiv_address (operands[1],
5728 copy_to_reg (XEXP (operands[1], 0)));
78a5d727
RE
5729 }
5730
5731 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5732 {
5733 rtx reg = gen_reg_rtx (SImode);
5734
5735 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5736 operands[1] = gen_lowpart (QImode, reg);
5737 }
5738
5739 if (GET_CODE (operands[0]) == MEM)
5740 operands[1] = force_reg (QImode, operands[1]);
5741 }
5742 else if (TARGET_THUMB
5743 && GET_CODE (operands[1]) == CONST_INT
ce92b223 5744 && !satisfies_constraint_I (operands[1]))
78a5d727 5745 {
d6b4baa4 5746 /* Handle loading a large integer during reload. */
d5b7b3ae 5747
78a5d727
RE
5748 /* Writing a constant to memory needs a scratch, which should
5749 be handled with SECONDARY_RELOADs. */
5750 gcc_assert (GET_CODE (operands[0]) == REG);
5751
5752 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5753 emit_insn (gen_movsi (operands[0], operands[1]));
5754 DONE;
d5b7b3ae
RE
5755 }
5756 "
5757)
3a33f76f 5758
ff9940b0 5759
d5b7b3ae
RE
5760(define_insn "*arm_movqi_insn"
5761 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
68df59d3 5762 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5b3e6663 5763 "TARGET_32BIT
d5b7b3ae
RE
5764 && ( register_operand (operands[0], QImode)
5765 || register_operand (operands[1], QImode))"
68df59d3
RE
5766 "@
5767 mov%?\\t%0, %1
5768 mvn%?\\t%0, #%B1
5b3e6663
PB
5769 ldr%(b%)\\t%0, %1
5770 str%(b%)\\t%1, %0"
9b66ebb1 5771 [(set_attr "type" "*,*,load1,store1")
cca0a211 5772 (set_attr "predicable" "yes")]
d5b7b3ae
RE
5773)
5774
5b3e6663 5775(define_insn "*thumb1_movqi_insn"
d5b7b3ae 5776 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5895f793 5777 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5b3e6663 5778 "TARGET_THUMB1
d5b7b3ae
RE
5779 && ( register_operand (operands[0], QImode)
5780 || register_operand (operands[1], QImode))"
5781 "@
5782 add\\t%0, %1, #0
5783 ldrb\\t%0, %1
5784 strb\\t%1, %0
5785 mov\\t%0, %1
5786 mov\\t%0, %1
5787 mov\\t%0, %1"
5788 [(set_attr "length" "2")
9b66ebb1 5789 (set_attr "type" "*,load1,store1,*,*,*")
d5b7b3ae
RE
5790 (set_attr "pool_range" "*,32,*,*,*,*")]
5791)
3a33f76f 5792
091426d3
RE
5793(define_expand "movsf"
5794 [(set (match_operand:SF 0 "general_operand" "")
5795 (match_operand:SF 1 "general_operand" ""))]
d5b7b3ae 5796 "TARGET_EITHER"
091426d3 5797 "
5b3e6663 5798 if (TARGET_32BIT)
d5b7b3ae
RE
5799 {
5800 if (GET_CODE (operands[0]) == MEM)
5801 operands[1] = force_reg (SFmode, operands[1]);
5802 }
5b3e6663 5803 else /* TARGET_THUMB1 */
d5b7b3ae 5804 {
b3a13419 5805 if (can_create_pseudo_p ())
d5b7b3ae
RE
5806 {
5807 if (GET_CODE (operands[0]) != REG)
5808 operands[1] = force_reg (SFmode, operands[1]);
5809 }
5810 }
5811 "
5812)
5813
f7657ed3
RE
5814;; Transform a floating-point move of a constant into a core register into
5815;; an SImode operation.
d5b7b3ae 5816(define_split
f7657ed3 5817 [(set (match_operand:SF 0 "arm_general_register_operand" "")
d5b7b3ae 5818 (match_operand:SF 1 "immediate_operand" ""))]
5b3e6663 5819 "TARGET_32BIT
d5b7b3ae
RE
5820 && reload_completed
5821 && GET_CODE (operands[1]) == CONST_DOUBLE"
5822 [(set (match_dup 2) (match_dup 3))]
5823 "
5824 operands[2] = gen_lowpart (SImode, operands[0]);
5825 operands[3] = gen_lowpart (SImode, operands[1]);
5826 if (operands[2] == 0 || operands[3] == 0)
5827 FAIL;
5895f793
RE
5828 "
5829)
091426d3 5830
d5b7b3ae
RE
5831(define_insn "*arm_movsf_soft_insn"
5832 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5833 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5834 "TARGET_ARM
5835 && TARGET_SOFT_FLOAT
5895f793
RE
5836 && (GET_CODE (operands[0]) != MEM
5837 || register_operand (operands[1], SFmode))"
39c0ef95
DE
5838 "@
5839 mov%?\\t%0, %1
5840 ldr%?\\t%0, %1\\t%@ float
5841 str%?\\t%1, %0\\t%@ float"
d5b7b3ae 5842 [(set_attr "length" "4,4,4")
cca0a211 5843 (set_attr "predicable" "yes")
9b66ebb1 5844 (set_attr "type" "*,load1,store1")
d5b7b3ae
RE
5845 (set_attr "pool_range" "*,4096,*")
5846 (set_attr "neg_pool_range" "*,4084,*")]
5847)
5848
5849;;; ??? This should have alternatives for constants.
5b3e6663 5850(define_insn "*thumb1_movsf_insn"
5895f793
RE
5851 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5852 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5b3e6663 5853 "TARGET_THUMB1
d5b7b3ae
RE
5854 && ( register_operand (operands[0], SFmode)
5855 || register_operand (operands[1], SFmode))"
5856 "@
5857 add\\t%0, %1, #0
5858 ldmia\\t%1, {%0}
5859 stmia\\t%0, {%1}
5860 ldr\\t%0, %1
5861 str\\t%1, %0
5862 mov\\t%0, %1
5863 mov\\t%0, %1"
5864 [(set_attr "length" "2")
9b66ebb1 5865 (set_attr "type" "*,load1,store1,load1,store1,*,*")
d5b7b3ae
RE
5866 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5867)
39c0ef95 5868
ff9940b0 5869(define_expand "movdf"
091426d3
RE
5870 [(set (match_operand:DF 0 "general_operand" "")
5871 (match_operand:DF 1 "general_operand" ""))]
d5b7b3ae 5872 "TARGET_EITHER"
ff9940b0 5873 "
5b3e6663 5874 if (TARGET_32BIT)
d5b7b3ae
RE
5875 {
5876 if (GET_CODE (operands[0]) == MEM)
5877 operands[1] = force_reg (DFmode, operands[1]);
5878 }
5879 else /* TARGET_THUMB */
5880 {
b3a13419 5881 if (can_create_pseudo_p ())
d5b7b3ae
RE
5882 {
5883 if (GET_CODE (operands[0]) != REG)
5884 operands[1] = force_reg (DFmode, operands[1]);
5885 }
5886 }
5887 "
5888)
3a33f76f 5889
ff9940b0
RE
5890;; Reloading a df mode value stored in integer regs to memory can require a
5891;; scratch reg.
5892(define_expand "reload_outdf"
d5b7b3ae 5893 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
091426d3
RE
5894 (match_operand:DF 1 "s_register_operand" "r")
5895 (match_operand:SI 2 "s_register_operand" "=&r")]
5b3e6663 5896 "TARGET_32BIT"
091426d3 5897 "
5895f793
RE
5898 {
5899 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4cdb3ed4 5900
5895f793
RE
5901 if (code == REG)
5902 operands[2] = XEXP (operands[0], 0);
5903 else if (code == POST_INC || code == PRE_DEC)
5904 {
5905 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5906 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5907 emit_insn (gen_movdi (operands[0], operands[1]));
5908 DONE;
5909 }
5910 else if (code == PRE_INC)
5911 {
5912 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4cdb3ed4 5913
5895f793
RE
5914 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5915 operands[2] = reg;
5916 }
5917 else if (code == POST_DEC)
5918 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5919 else
5920 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5921 XEXP (XEXP (operands[0], 0), 1)));
4cdb3ed4 5922
31fa16b6
RE
5923 emit_insn (gen_rtx_SET (VOIDmode,
5924 replace_equiv_address (operands[0], operands[2]),
5895f793 5925 operands[1]));
4cdb3ed4 5926
5895f793
RE
5927 if (code == POST_DEC)
5928 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5929
5930 DONE;
5931 }"
5932)
ff9940b0 5933
39c0ef95 5934(define_insn "*movdf_soft_insn"
2075b05d
RE
5935 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5936 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
ca68ea18 5937 "TARGET_ARM && TARGET_SOFT_FLOAT
d5b6e637
PB
5938 && ( register_operand (operands[0], DFmode)
5939 || register_operand (operands[1], DFmode))"
9b901d50
RE
5940 "*
5941 switch (which_alternative)
5942 {
5943 case 0:
5944 case 1:
5945 case 2:
5946 return \"#\";
5947 default:
5948 return output_move_double (operands);
5949 }
5950 "
2075b05d
RE
5951 [(set_attr "length" "8,12,16,8,8")
5952 (set_attr "type" "*,*,*,load2,store2")
0be5cf85
RE
5953 (set_attr "pool_range" "1020")
5954 (set_attr "neg_pool_range" "1008")]
d5b7b3ae
RE
5955)
5956
5957;;; ??? This should have alternatives for constants.
5958;;; ??? This was originally identical to the movdi_insn pattern.
5959;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5960;;; thumb_reorg with a memory reference.
5961(define_insn "*thumb_movdf_insn"
5895f793
RE
5962 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5963 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5b3e6663 5964 "TARGET_THUMB1
d5b7b3ae
RE
5965 && ( register_operand (operands[0], DFmode)
5966 || register_operand (operands[1], DFmode))"
5967 "*
5968 switch (which_alternative)
5969 {
5970 default:
5971 case 0:
5972 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5973 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5974 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5975 case 1:
5976 return \"ldmia\\t%1, {%0, %H0}\";
5977 case 2:
5978 return \"stmia\\t%0, {%1, %H1}\";
5979 case 3:
5980 return thumb_load_double_from_address (operands);
5981 case 4:
f1c25d3b
KH
5982 operands[2] = gen_rtx_MEM (SImode,
5983 plus_constant (XEXP (operands[0], 0), 4));
d5b7b3ae
RE
5984 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5985 return \"\";
5986 case 5:
5987 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5988 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5989 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5990 }
5991 "
5992 [(set_attr "length" "4,2,2,6,4,4")
9b66ebb1 5993 (set_attr "type" "*,load2,store2,load2,store2,*")
d5b7b3ae
RE
5994 (set_attr "pool_range" "*,*,*,1020,*,*")]
5995)
5a9335ef 5996
9f7bf991
RE
5997(define_expand "movxf"
5998 [(set (match_operand:XF 0 "general_operand" "")
5999 (match_operand:XF 1 "general_operand" ""))]
5b3e6663 6000 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
9f7bf991
RE
6001 "
6002 if (GET_CODE (operands[0]) == MEM)
6003 operands[1] = force_reg (XFmode, operands[1]);
6004 "
6005)
6006
3a33f76f 6007\f
3a33f76f 6008
ff9940b0
RE
6009;; load- and store-multiple insns
6010;; The arm can load/store any set of registers, provided that they are in
6011;; ascending order; but that is beyond GCC so stick with what it knows.
3a33f76f 6012
ff9940b0
RE
6013(define_expand "load_multiple"
6014 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6015 (match_operand:SI 1 "" ""))
6016 (use (match_operand:SI 2 "" ""))])]
5b3e6663 6017 "TARGET_32BIT"
50ed9cea
RH
6018{
6019 HOST_WIDE_INT offset = 0;
6020
48a08b9c 6021 /* Support only fixed point registers. */
ff9940b0
RE
6022 if (GET_CODE (operands[2]) != CONST_INT
6023 || INTVAL (operands[2]) > 14
6024 || INTVAL (operands[2]) < 2
6025 || GET_CODE (operands[1]) != MEM
6026 || GET_CODE (operands[0]) != REG
48a08b9c
NC
6027 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6028 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
ff9940b0
RE
6029 FAIL;
6030
6031 operands[3]
7a0a1f09
RE
6032 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
6033 force_reg (SImode, XEXP (operands[1], 0)),
50ed9cea
RH
6034 TRUE, FALSE, operands[1], &offset);
6035})
3a33f76f 6036
ff9940b0
RE
6037;; Load multiple with write-back
6038
d6c5a763 6039(define_insn "*ldmsi_postinc4"
ff9940b0 6040 [(match_parallel 0 "load_multiple_operation"
24cdff34 6041 [(set (match_operand:SI 1 "s_register_operand" "=r")
b0888988 6042 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
d6c5a763
RE
6043 (const_int 16)))
6044 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6045 (mem:SI (match_dup 2)))
b0888988 6046 (set (match_operand:SI 4 "arm_hard_register_operand" "")
d6c5a763
RE
6047 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6048 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6049 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6050 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6051 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5b3e6663
PB
6052 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6053 "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
9b66ebb1 6054 [(set_attr "type" "load4")
d6c5a763
RE
6055 (set_attr "predicable" "yes")]
6056)
3a33f76f 6057
5b3e6663 6058(define_insn "*ldmsi_postinc4_thumb1"
9f7bf991
RE
6059 [(match_parallel 0 "load_multiple_operation"
6060 [(set (match_operand:SI 1 "s_register_operand" "=l")
6061 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6062 (const_int 16)))
6063 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6064 (mem:SI (match_dup 2)))
6065 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6066 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6067 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6068 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6069 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6070 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5b3e6663 6071 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
9f7bf991
RE
6072 "ldmia\\t%1!, {%3, %4, %5, %6}"
6073 [(set_attr "type" "load4")]
6074)
6075
d6c5a763
RE
6076(define_insn "*ldmsi_postinc3"
6077 [(match_parallel 0 "load_multiple_operation"
24cdff34 6078 [(set (match_operand:SI 1 "s_register_operand" "=r")
d6c5a763
RE
6079 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6080 (const_int 12)))
6081 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6082 (mem:SI (match_dup 2)))
6083 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6084 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6085 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6086 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5b3e6663
PB
6087 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6088 "ldm%(ia%)\\t%1!, {%3, %4, %5}"
9b66ebb1 6089 [(set_attr "type" "load3")
d6c5a763
RE
6090 (set_attr "predicable" "yes")]
6091)
3a33f76f 6092
d6c5a763
RE
6093(define_insn "*ldmsi_postinc2"
6094 [(match_parallel 0 "load_multiple_operation"
24cdff34 6095 [(set (match_operand:SI 1 "s_register_operand" "=r")
d6c5a763
RE
6096 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6097 (const_int 8)))
6098 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6099 (mem:SI (match_dup 2)))
6100 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6101 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5b3e6663
PB
6102 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6103 "ldm%(ia%)\\t%1!, {%3, %4}"
9b66ebb1 6104 [(set_attr "type" "load2")
cca0a211
RE
6105 (set_attr "predicable" "yes")]
6106)
3a33f76f 6107
ff9940b0 6108;; Ordinary load multiple
3a33f76f 6109
d6c5a763 6110(define_insn "*ldmsi4"
ff9940b0 6111 [(match_parallel 0 "load_multiple_operation"
d6c5a763
RE
6112 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6113 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6114 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6115 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6116 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6117 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
6118 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6119 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5b3e6663
PB
6120 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6121 "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
9b66ebb1 6122 [(set_attr "type" "load4")
d6c5a763
RE
6123 (set_attr "predicable" "yes")]
6124)
ff9940b0 6125
d6c5a763
RE
6126(define_insn "*ldmsi3"
6127 [(match_parallel 0 "load_multiple_operation"
6128 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6129 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6130 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6131 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6132 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6133 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5b3e6663
PB
6134 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6135 "ldm%(ia%)\\t%1, {%2, %3, %4}"
9b66ebb1 6136 [(set_attr "type" "load3")
d6c5a763
RE
6137 (set_attr "predicable" "yes")]
6138)
ff9940b0 6139
d6c5a763
RE
6140(define_insn "*ldmsi2"
6141 [(match_parallel 0 "load_multiple_operation"
6142 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6143 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6144 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6145 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5b3e6663
PB
6146 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6147 "ldm%(ia%)\\t%1, {%2, %3}"
9b66ebb1 6148 [(set_attr "type" "load2")
cca0a211
RE
6149 (set_attr "predicable" "yes")]
6150)
ff9940b0
RE
6151
6152(define_expand "store_multiple"
6153 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6154 (match_operand:SI 1 "" ""))
6155 (use (match_operand:SI 2 "" ""))])]
5b3e6663 6156 "TARGET_32BIT"
50ed9cea
RH
6157{
6158 HOST_WIDE_INT offset = 0;
6159
d6b4baa4 6160 /* Support only fixed point registers. */
ff9940b0
RE
6161 if (GET_CODE (operands[2]) != CONST_INT
6162 || INTVAL (operands[2]) > 14
6163 || INTVAL (operands[2]) < 2
6164 || GET_CODE (operands[1]) != REG
6165 || GET_CODE (operands[0]) != MEM
48a08b9c
NC
6166 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6167 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
ff9940b0
RE
6168 FAIL;
6169
6170 operands[3]
7a0a1f09
RE
6171 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
6172 force_reg (SImode, XEXP (operands[0], 0)),
50ed9cea
RH
6173 TRUE, FALSE, operands[0], &offset);
6174})
3a33f76f 6175
ff9940b0
RE
6176;; Store multiple with write-back
6177
d6c5a763 6178(define_insn "*stmsi_postinc4"
ff9940b0 6179 [(match_parallel 0 "store_multiple_operation"
24cdff34 6180 [(set (match_operand:SI 1 "s_register_operand" "=r")
b0888988 6181 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
d6c5a763 6182 (const_int 16)))
b0888988 6183 (set (mem:SI (match_dup 2))
d6c5a763
RE
6184 (match_operand:SI 3 "arm_hard_register_operand" ""))
6185 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6186 (match_operand:SI 4 "arm_hard_register_operand" ""))
6187 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6188 (match_operand:SI 5 "arm_hard_register_operand" ""))
6189 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6190 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5b3e6663
PB
6191 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6192 "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
d6c5a763
RE
6193 [(set_attr "predicable" "yes")
6194 (set_attr "type" "store4")]
6195)
3a33f76f 6196
5b3e6663 6197(define_insn "*stmsi_postinc4_thumb1"
9f7bf991
RE
6198 [(match_parallel 0 "store_multiple_operation"
6199 [(set (match_operand:SI 1 "s_register_operand" "=l")
6200 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6201 (const_int 16)))
6202 (set (mem:SI (match_dup 2))
6203 (match_operand:SI 3 "arm_hard_register_operand" ""))
6204 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6205 (match_operand:SI 4 "arm_hard_register_operand" ""))
6206 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6207 (match_operand:SI 5 "arm_hard_register_operand" ""))
6208 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6209 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5b3e6663 6210 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
9f7bf991
RE
6211 "stmia\\t%1!, {%3, %4, %5, %6}"
6212 [(set_attr "type" "store4")]
6213)
6214
d6c5a763
RE
6215(define_insn "*stmsi_postinc3"
6216 [(match_parallel 0 "store_multiple_operation"
24cdff34 6217 [(set (match_operand:SI 1 "s_register_operand" "=r")
d6c5a763
RE
6218 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6219 (const_int 12)))
6220 (set (mem:SI (match_dup 2))
6221 (match_operand:SI 3 "arm_hard_register_operand" ""))
6222 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6223 (match_operand:SI 4 "arm_hard_register_operand" ""))
6224 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6225 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5b3e6663
PB
6226 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6227 "stm%(ia%)\\t%1!, {%3, %4, %5}"
d6c5a763
RE
6228 [(set_attr "predicable" "yes")
6229 (set_attr "type" "store3")]
6230)
ff9940b0 6231
d6c5a763
RE
6232(define_insn "*stmsi_postinc2"
6233 [(match_parallel 0 "store_multiple_operation"
24cdff34 6234 [(set (match_operand:SI 1 "s_register_operand" "=r")
d6c5a763
RE
6235 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6236 (const_int 8)))
6237 (set (mem:SI (match_dup 2))
6238 (match_operand:SI 3 "arm_hard_register_operand" ""))
6239 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6240 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5b3e6663
PB
6241 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6242 "stm%(ia%)\\t%1!, {%3, %4}"
cca0a211 6243 [(set_attr "predicable" "yes")
d6c5a763 6244 (set_attr "type" "store2")]
d5b7b3ae 6245)
ff9940b0
RE
6246
6247;; Ordinary store multiple
6248
d6c5a763 6249(define_insn "*stmsi4"
ff9940b0 6250 [(match_parallel 0 "store_multiple_operation"
b0888988 6251 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
d6c5a763
RE
6252 (match_operand:SI 2 "arm_hard_register_operand" ""))
6253 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6254 (match_operand:SI 3 "arm_hard_register_operand" ""))
6255 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6256 (match_operand:SI 4 "arm_hard_register_operand" ""))
6257 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6258 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5b3e6663
PB
6259 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6260 "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
d6c5a763
RE
6261 [(set_attr "predicable" "yes")
6262 (set_attr "type" "store4")]
6263)
ff9940b0 6264
d6c5a763
RE
6265(define_insn "*stmsi3"
6266 [(match_parallel 0 "store_multiple_operation"
6267 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6268 (match_operand:SI 2 "arm_hard_register_operand" ""))
6269 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6270 (match_operand:SI 3 "arm_hard_register_operand" ""))
6271 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6272 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5b3e6663
PB
6273 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6274 "stm%(ia%)\\t%1, {%2, %3, %4}"
d6c5a763
RE
6275 [(set_attr "predicable" "yes")
6276 (set_attr "type" "store3")]
6277)
ff9940b0 6278
d6c5a763
RE
6279(define_insn "*stmsi2"
6280 [(match_parallel 0 "store_multiple_operation"
6281 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6282 (match_operand:SI 2 "arm_hard_register_operand" ""))
6283 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6284 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5b3e6663
PB
6285 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6286 "stm%(ia%)\\t%1, {%2, %3}"
cca0a211 6287 [(set_attr "predicable" "yes")
d6c5a763 6288 (set_attr "type" "store2")]
d5b7b3ae 6289)
ff9940b0
RE
6290
6291;; Move a block of memory if it is word aligned and MORE than 2 words long.
6292;; We could let this apply for blocks of less than this, but it clobbers so
6293;; many registers that there is then probably a better way.
6294
70128ad9 6295(define_expand "movmemqi"
0bdece8a
RE
6296 [(match_operand:BLK 0 "general_operand" "")
6297 (match_operand:BLK 1 "general_operand" "")
6298 (match_operand:SI 2 "const_int_operand" "")
6299 (match_operand:SI 3 "const_int_operand" "")]
d5b7b3ae 6300 "TARGET_EITHER"
ff9940b0 6301 "
5b3e6663 6302 if (TARGET_32BIT)
d5b7b3ae 6303 {
70128ad9 6304 if (arm_gen_movmemqi (operands))
d5b7b3ae
RE
6305 DONE;
6306 FAIL;
6307 }
5b3e6663 6308 else /* TARGET_THUMB1 */
d5b7b3ae
RE
6309 {
6310 if ( INTVAL (operands[3]) != 4
6311 || INTVAL (operands[2]) > 48)
6312 FAIL;
6313
70128ad9 6314 thumb_expand_movmemqi (operands);
d5b7b3ae
RE
6315 DONE;
6316 }
6317 "
6318)
6319
d6c5a763 6320;; Thumb block-move insns
d5b7b3ae
RE
6321
6322(define_insn "movmem12b"
ca356f3a
RE
6323 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6324 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6325 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6326 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6327 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6328 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6329 (set (match_operand:SI 0 "register_operand" "=l")
6330 (plus:SI (match_dup 2) (const_int 12)))
6331 (set (match_operand:SI 1 "register_operand" "=l")
6332 (plus:SI (match_dup 3) (const_int 12)))
6333 (clobber (match_scratch:SI 4 "=&l"))
6334 (clobber (match_scratch:SI 5 "=&l"))
6335 (clobber (match_scratch:SI 6 "=&l"))]
5b3e6663 6336 "TARGET_THUMB1"
d5b7b3ae
RE
6337 "* return thumb_output_move_mem_multiple (3, operands);"
6338 [(set_attr "length" "4")
5895f793
RE
6339 ; This isn't entirely accurate... It loads as well, but in terms of
6340 ; scheduling the following insn it is better to consider it as a store
d5b7b3ae
RE
6341 (set_attr "type" "store3")]
6342)
6343
6344(define_insn "movmem8b"
ca356f3a
RE
6345 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6346 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6347 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6348 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6349 (set (match_operand:SI 0 "register_operand" "=l")
6350 (plus:SI (match_dup 2) (const_int 8)))
6351 (set (match_operand:SI 1 "register_operand" "=l")
6352 (plus:SI (match_dup 3) (const_int 8)))
6353 (clobber (match_scratch:SI 4 "=&l"))
6354 (clobber (match_scratch:SI 5 "=&l"))]
5b3e6663 6355 "TARGET_THUMB1"
d5b7b3ae
RE
6356 "* return thumb_output_move_mem_multiple (2, operands);"
6357 [(set_attr "length" "4")
5895f793
RE
6358 ; This isn't entirely accurate... It loads as well, but in terms of
6359 ; scheduling the following insn it is better to consider it as a store
d5b7b3ae
RE
6360 (set_attr "type" "store2")]
6361)
6362
ff9940b0 6363\f
3a33f76f 6364
6c98269c 6365;; Compare & branch insns
9a9f7594 6366;; The range calculations are based as follows:
6c98269c
RE
6367;; For forward branches, the address calculation returns the address of
6368;; the next instruction. This is 2 beyond the branch instruction.
6369;; For backward branches, the address calculation returns the address of
6370;; the first instruction in this pattern (cmp). This is 2 before the branch
6371;; instruction for the shortest sequence, and 4 before the branch instruction
6372;; if we have to jump around an unconditional branch.
6373;; To the basic branch range the PC offset must be added (this is +4).
6374;; So for forward branches we have
6375;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6376;; And for backward branches we have
6377;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6378;;
6379;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6380;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
d5b7b3ae 6381
c769a35d
RE
6382(define_expand "cbranchsi4"
6383 [(set (pc) (if_then_else
6384 (match_operator 0 "arm_comparison_operator"
6385 [(match_operand:SI 1 "s_register_operand" "")
6386 (match_operand:SI 2 "nonmemory_operand" "")])
6387 (label_ref (match_operand 3 "" ""))
6388 (pc)))]
f90b7a5a 6389 "TARGET_THUMB1 || TARGET_32BIT"
c769a35d 6390 "
f90b7a5a
PB
6391 if (!TARGET_THUMB1)
6392 {
6393 if (!arm_add_operand (operands[2], SImode))
6394 operands[2] = force_reg (SImode, operands[2]);
6395 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6396 operands[3]));
6397 DONE;
6398 }
5b3e6663 6399 if (thumb1_cmpneg_operand (operands[2], SImode))
c769a35d
RE
6400 {
6401 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6402 operands[3], operands[0]));
6403 DONE;
6404 }
5b3e6663 6405 if (!thumb1_cmp_operand (operands[2], SImode))
c769a35d
RE
6406 operands[2] = force_reg (SImode, operands[2]);
6407 ")
6408
f90b7a5a
PB
6409(define_expand "cbranchsf4"
6410 [(set (pc) (if_then_else
6411 (match_operator 0 "arm_comparison_operator"
6412 [(match_operand:SF 1 "s_register_operand" "")
6413 (match_operand:SF 2 "arm_float_compare_operand" "")])
6414 (label_ref (match_operand 3 "" ""))
6415 (pc)))]
6416 "TARGET_32BIT && TARGET_HARD_FLOAT"
6417 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6418 operands[3])); DONE;"
6419)
6420
6421(define_expand "cbranchdf4"
6422 [(set (pc) (if_then_else
6423 (match_operator 0 "arm_comparison_operator"
6424 [(match_operand:DF 1 "s_register_operand" "")
6425 (match_operand:DF 2 "arm_float_compare_operand" "")])
6426 (label_ref (match_operand 3 "" ""))
6427 (pc)))]
6428 "TARGET_32BIT && TARGET_HARD_FLOAT"
6429 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6430 operands[3])); DONE;"
6431)
6432
6433;; this uses the Cirrus DI compare instruction
6434(define_expand "cbranchdi4"
6435 [(set (pc) (if_then_else
6436 (match_operator 0 "arm_comparison_operator"
6437 [(match_operand:DI 1 "cirrus_fp_register" "")
6438 (match_operand:DI 2 "cirrus_fp_register" "")])
6439 (label_ref (match_operand 3 "" ""))
6440 (pc)))]
6441 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6442 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6443 operands[3])); DONE;"
6444)
6445
c769a35d
RE
6446(define_insn "*cbranchsi4_insn"
6447 [(set (pc) (if_then_else
6448 (match_operator 0 "arm_comparison_operator"
6449 [(match_operand:SI 1 "s_register_operand" "l,*h")
5b3e6663 6450 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
c769a35d
RE
6451 (label_ref (match_operand 3 "" ""))
6452 (pc)))]
5b3e6663 6453 "TARGET_THUMB1"
d5b7b3ae
RE
6454 "*
6455 output_asm_insn (\"cmp\\t%1, %2\", operands);
c769a35d 6456
d5b7b3ae
RE
6457 switch (get_attr_length (insn))
6458 {
6459 case 4: return \"b%d0\\t%l3\";
6460 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6461 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6462 }
6463 "
6464 [(set (attr "far_jump")
6465 (if_then_else
6466 (eq_attr "length" "8")
6467 (const_string "yes")
6468 (const_string "no")))
6469 (set (attr "length")
6470 (if_then_else
6471 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6472 (le (minus (match_dup 3) (pc)) (const_int 256)))
6473 (const_int 4)
6474 (if_then_else
6475 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6c98269c 6476 (le (minus (match_dup 3) (pc)) (const_int 2048)))
d5b7b3ae
RE
6477 (const_int 6)
6478 (const_int 8))))]
6479)
6480
c769a35d
RE
6481(define_insn "cbranchsi4_scratch"
6482 [(set (pc) (if_then_else
6483 (match_operator 4 "arm_comparison_operator"
6484 [(match_operand:SI 1 "s_register_operand" "l,0")
5b3e6663 6485 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
c769a35d
RE
6486 (label_ref (match_operand 3 "" ""))
6487 (pc)))
6488 (clobber (match_scratch:SI 0 "=l,l"))]
5b3e6663 6489 "TARGET_THUMB1"
c769a35d
RE
6490 "*
6491 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6492
6493 switch (get_attr_length (insn))
6494 {
6495 case 4: return \"b%d4\\t%l3\";
6496 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6497 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6498 }
6499 "
6500 [(set (attr "far_jump")
6501 (if_then_else
6502 (eq_attr "length" "8")
6503 (const_string "yes")
6504 (const_string "no")))
6505 (set (attr "length")
6506 (if_then_else
6507 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6508 (le (minus (match_dup 3) (pc)) (const_int 256)))
6509 (const_int 4)
6510 (if_then_else
6511 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6512 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6513 (const_int 6)
6514 (const_int 8))))]
6515)
6516(define_insn "*movsi_cbranchsi4"
6517 [(set (pc)
6518 (if_then_else
6519 (match_operator 3 "arm_comparison_operator"
6520 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6521 (const_int 0)])
6522 (label_ref (match_operand 2 "" ""))
6523 (pc)))
6524 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6525 (match_dup 1))]
5b3e6663 6526 "TARGET_THUMB1"
c769a35d
RE
6527 "*{
6528 if (which_alternative == 0)
6529 output_asm_insn (\"cmp\t%0, #0\", operands);
6530 else if (which_alternative == 1)
6531 output_asm_insn (\"sub\t%0, %1, #0\", operands);
6532 else
6533 {
6534 output_asm_insn (\"cmp\t%1, #0\", operands);
6535 if (which_alternative == 2)
6536 output_asm_insn (\"mov\t%0, %1\", operands);
6537 else
6538 output_asm_insn (\"str\t%1, %0\", operands);
6539 }
6540 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6541 {
6542 case 4: return \"b%d3\\t%l2\";
6543 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6544 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6545 }
6546 }"
6547 [(set (attr "far_jump")
6548 (if_then_else
6549 (ior (and (gt (symbol_ref ("which_alternative"))
6550 (const_int 1))
6551 (eq_attr "length" "8"))
6552 (eq_attr "length" "10"))
6553 (const_string "yes")
6554 (const_string "no")))
6555 (set (attr "length")
6556 (if_then_else
6557 (le (symbol_ref ("which_alternative"))
6558 (const_int 1))
6559 (if_then_else
6560 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6561 (le (minus (match_dup 2) (pc)) (const_int 256)))
6562 (const_int 4)
6563 (if_then_else
6564 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6565 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6566 (const_int 6)
6567 (const_int 8)))
6568 (if_then_else
6569 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6570 (le (minus (match_dup 2) (pc)) (const_int 256)))
6571 (const_int 6)
6572 (if_then_else
6573 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6574 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6575 (const_int 8)
6576 (const_int 10)))))]
6577)
6578
d5b7b3ae
RE
6579(define_insn "*negated_cbranchsi4"
6580 [(set (pc)
6581 (if_then_else
1ac3e311 6582 (match_operator 0 "equality_operator"
c769a35d
RE
6583 [(match_operand:SI 1 "s_register_operand" "l")
6584 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6585 (label_ref (match_operand 3 "" ""))
5895f793 6586 (pc)))]
5b3e6663 6587 "TARGET_THUMB1"
d5b7b3ae
RE
6588 "*
6589 output_asm_insn (\"cmn\\t%1, %2\", operands);
6590 switch (get_attr_length (insn))
6591 {
6592 case 4: return \"b%d0\\t%l3\";
6593 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6594 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6595 }
6596 "
6597 [(set (attr "far_jump")
6598 (if_then_else
6599 (eq_attr "length" "8")
6600 (const_string "yes")
6601 (const_string "no")))
6602 (set (attr "length")
6603 (if_then_else
6604 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6c98269c 6605 (le (minus (match_dup 3) (pc)) (const_int 256)))
d5b7b3ae
RE
6606 (const_int 4)
6607 (if_then_else
6c98269c
RE
6608 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6609 (le (minus (match_dup 3) (pc)) (const_int 2048)))
d5b7b3ae
RE
6610 (const_int 6)
6611 (const_int 8))))]
6612)
6613
defc0463
RE
6614(define_insn "*tbit_cbranch"
6615 [(set (pc)
6616 (if_then_else
6617 (match_operator 0 "equality_operator"
6618 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6619 (const_int 1)
6620 (match_operand:SI 2 "const_int_operand" "i"))
6621 (const_int 0)])
6622 (label_ref (match_operand 3 "" ""))
6623 (pc)))
6624 (clobber (match_scratch:SI 4 "=l"))]
5b3e6663 6625 "TARGET_THUMB1"
defc0463
RE
6626 "*
6627 {
6628 rtx op[3];
6629 op[0] = operands[4];
6630 op[1] = operands[1];
6631 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6632
f9fa4363
RE
6633 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6634 switch (get_attr_length (insn))
6635 {
6636 case 4: return \"b%d0\\t%l3\";
6637 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6638 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6639 }
6640 }"
6641 [(set (attr "far_jump")
6642 (if_then_else
6643 (eq_attr "length" "8")
6644 (const_string "yes")
6645 (const_string "no")))
6646 (set (attr "length")
6647 (if_then_else
6648 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6649 (le (minus (match_dup 3) (pc)) (const_int 256)))
6650 (const_int 4)
6651 (if_then_else
6652 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6653 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6654 (const_int 6)
6655 (const_int 8))))]
6656)
6657
6658(define_insn "*tlobits_cbranch"
6659 [(set (pc)
6660 (if_then_else
6661 (match_operator 0 "equality_operator"
6662 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6663 (match_operand:SI 2 "const_int_operand" "i")
6664 (const_int 0))
6665 (const_int 0)])
6666 (label_ref (match_operand 3 "" ""))
6667 (pc)))
6668 (clobber (match_scratch:SI 4 "=l"))]
5b3e6663 6669 "TARGET_THUMB1"
f9fa4363
RE
6670 "*
6671 {
6672 rtx op[3];
6673 op[0] = operands[4];
6674 op[1] = operands[1];
6675 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6676
defc0463
RE
6677 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6678 switch (get_attr_length (insn))
6679 {
6680 case 4: return \"b%d0\\t%l3\";
6681 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6682 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6683 }
6684 }"
6685 [(set (attr "far_jump")
6686 (if_then_else
6687 (eq_attr "length" "8")
6688 (const_string "yes")
6689 (const_string "no")))
6690 (set (attr "length")
6691 (if_then_else
6692 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6693 (le (minus (match_dup 3) (pc)) (const_int 256)))
6694 (const_int 4)
6695 (if_then_else
6696 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6697 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6698 (const_int 6)
6699 (const_int 8))))]
6700)
6701
c769a35d 6702(define_insn "*tstsi3_cbranch"
defc0463
RE
6703 [(set (pc)
6704 (if_then_else
c769a35d
RE
6705 (match_operator 3 "equality_operator"
6706 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6707 (match_operand:SI 1 "s_register_operand" "l"))
defc0463 6708 (const_int 0)])
c769a35d
RE
6709 (label_ref (match_operand 2 "" ""))
6710 (pc)))]
5b3e6663 6711 "TARGET_THUMB1"
defc0463
RE
6712 "*
6713 {
c769a35d 6714 output_asm_insn (\"tst\\t%0, %1\", operands);
defc0463
RE
6715 switch (get_attr_length (insn))
6716 {
c769a35d
RE
6717 case 4: return \"b%d3\\t%l2\";
6718 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6719 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
defc0463
RE
6720 }
6721 }"
6722 [(set (attr "far_jump")
6723 (if_then_else
6724 (eq_attr "length" "8")
6725 (const_string "yes")
6726 (const_string "no")))
6727 (set (attr "length")
6728 (if_then_else
c769a35d
RE
6729 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6730 (le (minus (match_dup 2) (pc)) (const_int 256)))
defc0463
RE
6731 (const_int 4)
6732 (if_then_else
c769a35d
RE
6733 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6734 (le (minus (match_dup 2) (pc)) (const_int 2048)))
defc0463
RE
6735 (const_int 6)
6736 (const_int 8))))]
6737)
6738
6739(define_insn "*andsi3_cbranch"
6740 [(set (pc)
6741 (if_then_else
6742 (match_operator 5 "equality_operator"
6743 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6744 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6745 (const_int 0)])
6746 (label_ref (match_operand 4 "" ""))
6747 (pc)))
c769a35d 6748 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
defc0463
RE
6749 (and:SI (match_dup 2) (match_dup 3)))
6750 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5b3e6663 6751 "TARGET_THUMB1"
defc0463
RE
6752 "*
6753 {
6754 if (which_alternative == 0)
6755 output_asm_insn (\"and\\t%0, %3\", operands);
6756 else if (which_alternative == 1)
6757 {
6758 output_asm_insn (\"and\\t%1, %3\", operands);
6759 output_asm_insn (\"mov\\t%0, %1\", operands);
6760 }
6761 else
6762 {
6763 output_asm_insn (\"and\\t%1, %3\", operands);
6764 output_asm_insn (\"str\\t%1, %0\", operands);
6765 }
6766
6767 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6768 {
6769 case 4: return \"b%d5\\t%l4\";
6770 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6771 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6772 }
6773 }"
6774 [(set (attr "far_jump")
6775 (if_then_else
6776 (ior (and (eq (symbol_ref ("which_alternative"))
6777 (const_int 0))
6778 (eq_attr "length" "8"))
6779 (eq_attr "length" "10"))
6780 (const_string "yes")
6781 (const_string "no")))
6782 (set (attr "length")
6783 (if_then_else
6784 (eq (symbol_ref ("which_alternative"))
6785 (const_int 0))
6786 (if_then_else
6787 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6788 (le (minus (match_dup 4) (pc)) (const_int 256)))
6789 (const_int 4)
6790 (if_then_else
6791 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6792 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6793 (const_int 6)
6794 (const_int 8)))
6795 (if_then_else
6796 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6797 (le (minus (match_dup 4) (pc)) (const_int 256)))
6798 (const_int 6)
6799 (if_then_else
6800 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6801 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6802 (const_int 8)
6803 (const_int 10)))))]
6804)
6805
6806(define_insn "*orrsi3_cbranch_scratch"
6807 [(set (pc)
6808 (if_then_else
6809 (match_operator 4 "equality_operator"
6810 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6811 (match_operand:SI 2 "s_register_operand" "l"))
6812 (const_int 0)])
6813 (label_ref (match_operand 3 "" ""))
6814 (pc)))
6815 (clobber (match_scratch:SI 0 "=l"))]
5b3e6663 6816 "TARGET_THUMB1"
defc0463
RE
6817 "*
6818 {
6819 output_asm_insn (\"orr\\t%0, %2\", operands);
6820 switch (get_attr_length (insn))
6821 {
6822 case 4: return \"b%d4\\t%l3\";
6823 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6824 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6825 }
6826 }"
6827 [(set (attr "far_jump")
6828 (if_then_else
6829 (eq_attr "length" "8")
6830 (const_string "yes")
6831 (const_string "no")))
6832 (set (attr "length")
6833 (if_then_else
6834 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6835 (le (minus (match_dup 3) (pc)) (const_int 256)))
6836 (const_int 4)
6837 (if_then_else
6838 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6839 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6840 (const_int 6)
6841 (const_int 8))))]
6842)
6843
6844(define_insn "*orrsi3_cbranch"
6845 [(set (pc)
6846 (if_then_else
6847 (match_operator 5 "equality_operator"
6848 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6849 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6850 (const_int 0)])
6851 (label_ref (match_operand 4 "" ""))
6852 (pc)))
c769a35d 6853 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
defc0463
RE
6854 (ior:SI (match_dup 2) (match_dup 3)))
6855 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5b3e6663 6856 "TARGET_THUMB1"
defc0463
RE
6857 "*
6858 {
6859 if (which_alternative == 0)
6860 output_asm_insn (\"orr\\t%0, %3\", operands);
6861 else if (which_alternative == 1)
6862 {
6863 output_asm_insn (\"orr\\t%1, %3\", operands);
6864 output_asm_insn (\"mov\\t%0, %1\", operands);
6865 }
6866 else
6867 {
6868 output_asm_insn (\"orr\\t%1, %3\", operands);
6869 output_asm_insn (\"str\\t%1, %0\", operands);
6870 }
6871
6872 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6873 {
6874 case 4: return \"b%d5\\t%l4\";
6875 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6876 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6877 }
6878 }"
6879 [(set (attr "far_jump")
6880 (if_then_else
6881 (ior (and (eq (symbol_ref ("which_alternative"))
6882 (const_int 0))
6883 (eq_attr "length" "8"))
6884 (eq_attr "length" "10"))
6885 (const_string "yes")
6886 (const_string "no")))
6887 (set (attr "length")
6888 (if_then_else
6889 (eq (symbol_ref ("which_alternative"))
6890 (const_int 0))
6891 (if_then_else
6892 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6893 (le (minus (match_dup 4) (pc)) (const_int 256)))
6894 (const_int 4)
6895 (if_then_else
6896 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6897 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6898 (const_int 6)
6899 (const_int 8)))
6900 (if_then_else
6901 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6902 (le (minus (match_dup 4) (pc)) (const_int 256)))
6903 (const_int 6)
6904 (if_then_else
6905 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6906 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6907 (const_int 8)
6908 (const_int 10)))))]
6909)
6910
6911(define_insn "*xorsi3_cbranch_scratch"
6912 [(set (pc)
6913 (if_then_else
6914 (match_operator 4 "equality_operator"
6915 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6916 (match_operand:SI 2 "s_register_operand" "l"))
6917 (const_int 0)])
6918 (label_ref (match_operand 3 "" ""))
6919 (pc)))
6920 (clobber (match_scratch:SI 0 "=l"))]
5b3e6663 6921 "TARGET_THUMB1"
defc0463
RE
6922 "*
6923 {
6924 output_asm_insn (\"eor\\t%0, %2\", operands);
6925 switch (get_attr_length (insn))
6926 {
6927 case 4: return \"b%d4\\t%l3\";
6928 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6929 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6930 }
6931 }"
6932 [(set (attr "far_jump")
6933 (if_then_else
6934 (eq_attr "length" "8")
6935 (const_string "yes")
6936 (const_string "no")))
6937 (set (attr "length")
6938 (if_then_else
6939 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6940 (le (minus (match_dup 3) (pc)) (const_int 256)))
6941 (const_int 4)
6942 (if_then_else
6943 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6944 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6945 (const_int 6)
6946 (const_int 8))))]
6947)
6948
6949(define_insn "*xorsi3_cbranch"
6950 [(set (pc)
6951 (if_then_else
6952 (match_operator 5 "equality_operator"
6953 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6954 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6955 (const_int 0)])
6956 (label_ref (match_operand 4 "" ""))
6957 (pc)))
c769a35d 6958 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
defc0463
RE
6959 (xor:SI (match_dup 2) (match_dup 3)))
6960 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5b3e6663 6961 "TARGET_THUMB1"
defc0463
RE
6962 "*
6963 {
6964 if (which_alternative == 0)
6965 output_asm_insn (\"eor\\t%0, %3\", operands);
6966 else if (which_alternative == 1)
6967 {
6968 output_asm_insn (\"eor\\t%1, %3\", operands);
6969 output_asm_insn (\"mov\\t%0, %1\", operands);
6970 }
6971 else
6972 {
6973 output_asm_insn (\"eor\\t%1, %3\", operands);
6974 output_asm_insn (\"str\\t%1, %0\", operands);
6975 }
6976
6977 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6978 {
6979 case 4: return \"b%d5\\t%l4\";
6980 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6981 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6982 }
6983 }"
6984 [(set (attr "far_jump")
6985 (if_then_else
6986 (ior (and (eq (symbol_ref ("which_alternative"))
6987 (const_int 0))
6988 (eq_attr "length" "8"))
6989 (eq_attr "length" "10"))
6990 (const_string "yes")
6991 (const_string "no")))
6992 (set (attr "length")
6993 (if_then_else
6994 (eq (symbol_ref ("which_alternative"))
6995 (const_int 0))
6996 (if_then_else
6997 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6998 (le (minus (match_dup 4) (pc)) (const_int 256)))
6999 (const_int 4)
7000 (if_then_else
7001 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7002 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7003 (const_int 6)
7004 (const_int 8)))
7005 (if_then_else
7006 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7007 (le (minus (match_dup 4) (pc)) (const_int 256)))
7008 (const_int 6)
7009 (if_then_else
7010 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7011 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7012 (const_int 8)
7013 (const_int 10)))))]
7014)
7015
c769a35d
RE
7016(define_insn "*bicsi3_cbranch_scratch"
7017 [(set (pc)
7018 (if_then_else
7019 (match_operator 4 "equality_operator"
7020 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
7021 (match_operand:SI 1 "s_register_operand" "0"))
7022 (const_int 0)])
7023 (label_ref (match_operand 3 "" ""))
7024 (pc)))
7025 (clobber (match_scratch:SI 0 "=l"))]
5b3e6663 7026 "TARGET_THUMB1"
c769a35d
RE
7027 "*
7028 {
7029 output_asm_insn (\"bic\\t%0, %2\", operands);
7030 switch (get_attr_length (insn))
7031 {
7032 case 4: return \"b%d4\\t%l3\";
7033 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7034 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7035 }
7036 }"
7037 [(set (attr "far_jump")
7038 (if_then_else
7039 (eq_attr "length" "8")
7040 (const_string "yes")
7041 (const_string "no")))
7042 (set (attr "length")
7043 (if_then_else
7044 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7045 (le (minus (match_dup 3) (pc)) (const_int 256)))
7046 (const_int 4)
7047 (if_then_else
7048 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7049 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7050 (const_int 6)
7051 (const_int 8))))]
7052)
7053
7054(define_insn "*bicsi3_cbranch"
7055 [(set (pc)
7056 (if_then_else
7057 (match_operator 5 "equality_operator"
e1d2bd1e
RE
7058 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
7059 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
c769a35d
RE
7060 (const_int 0)])
7061 (label_ref (match_operand 4 "" ""))
7062 (pc)))
e1d2bd1e 7063 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
c769a35d 7064 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
e1d2bd1e 7065 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
5b3e6663 7066 "TARGET_THUMB1"
c769a35d
RE
7067 "*
7068 {
7069 if (which_alternative == 0)
7070 output_asm_insn (\"bic\\t%0, %3\", operands);
e1d2bd1e 7071 else if (which_alternative <= 2)
c769a35d
RE
7072 {
7073 output_asm_insn (\"bic\\t%1, %3\", operands);
e1d2bd1e
RE
7074 /* It's ok if OP0 is a lo-reg, even though the mov will set the
7075 conditions again, since we're only testing for equality. */
c769a35d
RE
7076 output_asm_insn (\"mov\\t%0, %1\", operands);
7077 }
7078 else
7079 {
7080 output_asm_insn (\"bic\\t%1, %3\", operands);
7081 output_asm_insn (\"str\\t%1, %0\", operands);
7082 }
7083
7084 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7085 {
7086 case 4: return \"b%d5\\t%l4\";
7087 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7088 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7089 }
7090 }"
7091 [(set (attr "far_jump")
7092 (if_then_else
7093 (ior (and (eq (symbol_ref ("which_alternative"))
7094 (const_int 0))
7095 (eq_attr "length" "8"))
7096 (eq_attr "length" "10"))
7097 (const_string "yes")
7098 (const_string "no")))
7099 (set (attr "length")
7100 (if_then_else
7101 (eq (symbol_ref ("which_alternative"))
7102 (const_int 0))
7103 (if_then_else
7104 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7105 (le (minus (match_dup 4) (pc)) (const_int 256)))
7106 (const_int 4)
7107 (if_then_else
7108 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7109 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7110 (const_int 6)
7111 (const_int 8)))
7112 (if_then_else
7113 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7114 (le (minus (match_dup 4) (pc)) (const_int 256)))
7115 (const_int 6)
7116 (if_then_else
7117 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7118 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7119 (const_int 8)
7120 (const_int 10)))))]
7121)
7122
f9b9980e
RE
7123(define_insn "*cbranchne_decr1"
7124 [(set (pc)
7125 (if_then_else (match_operator 3 "equality_operator"
7126 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7127 (const_int 0)])
7128 (label_ref (match_operand 4 "" ""))
7129 (pc)))
c769a35d 7130 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
f9b9980e
RE
7131 (plus:SI (match_dup 2) (const_int -1)))
7132 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5b3e6663 7133 "TARGET_THUMB1"
f9b9980e
RE
7134 "*
7135 {
7136 rtx cond[2];
7137 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7138 ? GEU : LTU),
defc0463 7139 VOIDmode, operands[2], const1_rtx);
f9b9980e
RE
7140 cond[1] = operands[4];
7141
7142 if (which_alternative == 0)
7143 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7144 else if (which_alternative == 1)
7145 {
7146 /* We must provide an alternative for a hi reg because reload
7147 cannot handle output reloads on a jump instruction, but we
7148 can't subtract into that. Fortunately a mov from lo to hi
7149 does not clobber the condition codes. */
7150 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7151 output_asm_insn (\"mov\\t%0, %1\", operands);
7152 }
7153 else
7154 {
7155 /* Similarly, but the target is memory. */
7156 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7157 output_asm_insn (\"str\\t%1, %0\", operands);
7158 }
7159
7160 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7161 {
7162 case 4:
91de08c3 7163 output_asm_insn (\"b%d0\\t%l1\", cond);
f9b9980e
RE
7164 return \"\";
7165 case 6:
91de08c3 7166 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
f9b9980e
RE
7167 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7168 default:
91de08c3 7169 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
f9b9980e
RE
7170 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7171 }
7172 }
7173 "
7174 [(set (attr "far_jump")
7175 (if_then_else
7176 (ior (and (eq (symbol_ref ("which_alternative"))
7177 (const_int 0))
7178 (eq_attr "length" "8"))
7179 (eq_attr "length" "10"))
7180 (const_string "yes")
7181 (const_string "no")))
7182 (set_attr_alternative "length"
7183 [
7184 ;; Alternative 0
7185 (if_then_else
7186 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7187 (le (minus (match_dup 4) (pc)) (const_int 256)))
7188 (const_int 4)
7189 (if_then_else
7190 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7191 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7192 (const_int 6)
7193 (const_int 8)))
7194 ;; Alternative 1
7195 (if_then_else
7196 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7197 (le (minus (match_dup 4) (pc)) (const_int 256)))
7198 (const_int 6)
7199 (if_then_else
7200 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7201 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7202 (const_int 8)
7203 (const_int 10)))
7204 ;; Alternative 2
7205 (if_then_else
7206 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7207 (le (minus (match_dup 4) (pc)) (const_int 256)))
7208 (const_int 6)
7209 (if_then_else
7210 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7211 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7212 (const_int 8)
7213 (const_int 10)))
7214 ;; Alternative 3
7215 (if_then_else
7216 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7217 (le (minus (match_dup 4) (pc)) (const_int 256)))
7218 (const_int 6)
7219 (if_then_else
7220 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7221 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7222 (const_int 8)
7223 (const_int 10)))])]
7224)
d5b7b3ae 7225
defc0463
RE
7226(define_insn "*addsi3_cbranch"
7227 [(set (pc)
7228 (if_then_else
7229 (match_operator 4 "comparison_operator"
7230 [(plus:SI
7231 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
7232 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
7233 (const_int 0)])
7234 (label_ref (match_operand 5 "" ""))
7235 (pc)))
c769a35d
RE
7236 (set
7237 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7238 (plus:SI (match_dup 2) (match_dup 3)))
defc0463 7239 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
5b3e6663 7240 "TARGET_THUMB1
defc0463
RE
7241 && (GET_CODE (operands[4]) == EQ
7242 || GET_CODE (operands[4]) == NE
7243 || GET_CODE (operands[4]) == GE
7244 || GET_CODE (operands[4]) == LT)"
7245 "*
7246 {
7247 rtx cond[3];
7248
7249
7250 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
7251 cond[1] = operands[2];
7252 cond[2] = operands[3];
7253
7254 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7255 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7256 else
7257 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7258
7259 if (which_alternative >= 3
7260 && which_alternative < 4)
7261 output_asm_insn (\"mov\\t%0, %1\", operands);
7262 else if (which_alternative >= 4)
7263 output_asm_insn (\"str\\t%1, %0\", operands);
7264
7265 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7266 {
7267 case 4:
7268 return \"b%d4\\t%l5\";
7269 case 6:
7270 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7271 default:
7272 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7273 }
7274 }
7275 "
7276 [(set (attr "far_jump")
7277 (if_then_else
7278 (ior (and (lt (symbol_ref ("which_alternative"))
7279 (const_int 3))
7280 (eq_attr "length" "8"))
7281 (eq_attr "length" "10"))
7282 (const_string "yes")
7283 (const_string "no")))
7284 (set (attr "length")
7285 (if_then_else
7286 (lt (symbol_ref ("which_alternative"))
7287 (const_int 3))
7288 (if_then_else
7289 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7290 (le (minus (match_dup 5) (pc)) (const_int 256)))
7291 (const_int 4)
7292 (if_then_else
7293 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7294 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7295 (const_int 6)
7296 (const_int 8)))
7297 (if_then_else
7298 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7299 (le (minus (match_dup 5) (pc)) (const_int 256)))
7300 (const_int 6)
7301 (if_then_else
7302 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7303 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7304 (const_int 8)
7305 (const_int 10)))))]
7306)
7307
7308(define_insn "*addsi3_cbranch_scratch"
7309 [(set (pc)
7310 (if_then_else
7311 (match_operator 3 "comparison_operator"
7312 [(plus:SI
7313 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
b49e92fe 7314 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
defc0463
RE
7315 (const_int 0)])
7316 (label_ref (match_operand 4 "" ""))
7317 (pc)))
7318 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
5b3e6663 7319 "TARGET_THUMB1
defc0463
RE
7320 && (GET_CODE (operands[3]) == EQ
7321 || GET_CODE (operands[3]) == NE
7322 || GET_CODE (operands[3]) == GE
7323 || GET_CODE (operands[3]) == LT)"
7324 "*
7325 {
7326 switch (which_alternative)
7327 {
7328 case 0:
7329 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7330 break;
7331 case 1:
7332 output_asm_insn (\"cmn\t%1, %2\", operands);
7333 break;
108a579c 7334 case 2:
b49e92fe
PB
7335 if (INTVAL (operands[2]) < 0)
7336 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7337 else
7338 output_asm_insn (\"add\t%0, %1, %2\", operands);
defc0463 7339 break;
108a579c 7340 case 3:
b49e92fe
PB
7341 if (INTVAL (operands[2]) < 0)
7342 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7343 else
7344 output_asm_insn (\"add\t%0, %0, %2\", operands);
defc0463
RE
7345 break;
7346 }
7347
7348 switch (get_attr_length (insn))
7349 {
7350 case 4:
7351 return \"b%d3\\t%l4\";
7352 case 6:
7353 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7354 default:
7355 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7356 }
7357 }
7358 "
7359 [(set (attr "far_jump")
7360 (if_then_else
7361 (eq_attr "length" "8")
7362 (const_string "yes")
7363 (const_string "no")))
7364 (set (attr "length")
7365 (if_then_else
7366 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7367 (le (minus (match_dup 4) (pc)) (const_int 256)))
7368 (const_int 4)
7369 (if_then_else
7370 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7371 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7372 (const_int 6)
7373 (const_int 8))))]
7374)
7375
7376(define_insn "*subsi3_cbranch"
7377 [(set (pc)
7378 (if_then_else
7379 (match_operator 4 "comparison_operator"
7380 [(minus:SI
7381 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7382 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7383 (const_int 0)])
7384 (label_ref (match_operand 5 "" ""))
7385 (pc)))
c769a35d 7386 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
defc0463
RE
7387 (minus:SI (match_dup 2) (match_dup 3)))
7388 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5b3e6663 7389 "TARGET_THUMB1
defc0463
RE
7390 && (GET_CODE (operands[4]) == EQ
7391 || GET_CODE (operands[4]) == NE
7392 || GET_CODE (operands[4]) == GE
7393 || GET_CODE (operands[4]) == LT)"
7394 "*
7395 {
7396 if (which_alternative == 0)
7397 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7398 else if (which_alternative == 1)
7399 {
7400 /* We must provide an alternative for a hi reg because reload
7401 cannot handle output reloads on a jump instruction, but we
7402 can't subtract into that. Fortunately a mov from lo to hi
7403 does not clobber the condition codes. */
7404 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7405 output_asm_insn (\"mov\\t%0, %1\", operands);
7406 }
7407 else
7408 {
7409 /* Similarly, but the target is memory. */
7410 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7411 output_asm_insn (\"str\\t%1, %0\", operands);
7412 }
7413
7414 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7415 {
7416 case 4:
7417 return \"b%d4\\t%l5\";
7418 case 6:
7419 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7420 default:
7421 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7422 }
7423 }
7424 "
7425 [(set (attr "far_jump")
7426 (if_then_else
7427 (ior (and (eq (symbol_ref ("which_alternative"))
7428 (const_int 0))
7429 (eq_attr "length" "8"))
7430 (eq_attr "length" "10"))
7431 (const_string "yes")
7432 (const_string "no")))
7433 (set (attr "length")
7434 (if_then_else
7435 (eq (symbol_ref ("which_alternative"))
7436 (const_int 0))
7437 (if_then_else
7438 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7439 (le (minus (match_dup 5) (pc)) (const_int 256)))
7440 (const_int 4)
7441 (if_then_else
7442 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7443 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7444 (const_int 6)
7445 (const_int 8)))
7446 (if_then_else
7447 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7448 (le (minus (match_dup 5) (pc)) (const_int 256)))
7449 (const_int 6)
7450 (if_then_else
7451 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7452 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7453 (const_int 8)
7454 (const_int 10)))))]
7455)
7456
7457(define_insn "*subsi3_cbranch_scratch"
7458 [(set (pc)
7459 (if_then_else
7460 (match_operator 0 "arm_comparison_operator"
7461 [(minus:SI (match_operand:SI 1 "register_operand" "l")
7462 (match_operand:SI 2 "nonmemory_operand" "l"))
7463 (const_int 0)])
7464 (label_ref (match_operand 3 "" ""))
7465 (pc)))]
5b3e6663 7466 "TARGET_THUMB1
defc0463
RE
7467 && (GET_CODE (operands[0]) == EQ
7468 || GET_CODE (operands[0]) == NE
7469 || GET_CODE (operands[0]) == GE
7470 || GET_CODE (operands[0]) == LT)"
7471 "*
7472 output_asm_insn (\"cmp\\t%1, %2\", operands);
7473 switch (get_attr_length (insn))
7474 {
7475 case 4: return \"b%d0\\t%l3\";
7476 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7477 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7478 }
7479 "
7480 [(set (attr "far_jump")
7481 (if_then_else
7482 (eq_attr "length" "8")
7483 (const_string "yes")
7484 (const_string "no")))
7485 (set (attr "length")
7486 (if_then_else
7487 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7488 (le (minus (match_dup 3) (pc)) (const_int 256)))
7489 (const_int 4)
7490 (if_then_else
7491 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7492 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7493 (const_int 6)
7494 (const_int 8))))]
7495)
7496
ff9940b0
RE
7497;; Comparison and test insns
7498
d5b7b3ae 7499(define_insn "*arm_cmpsi_insn"
48a08b9c 7500 [(set (reg:CC CC_REGNUM)
589fe0fc 7501 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
d5b7b3ae 7502 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5b3e6663 7503 "TARGET_32BIT"
68df59d3 7504 "@
589fe0fc
RE
7505 cmp%?\\t%0, %1
7506 cmn%?\\t%0, #%n1"
d5b7b3ae
RE
7507 [(set_attr "conds" "set")]
7508)
3a33f76f 7509
5b3e6663 7510(define_insn "*arm_cmpsi_shiftsi"
48a08b9c 7511 [(set (reg:CC CC_REGNUM)
d5b7b3ae
RE
7512 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
7513 (match_operator:SI 3 "shift_operator"
589fe0fc 7514 [(match_operand:SI 1 "s_register_operand" "r")
d5b7b3ae
RE
7515 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
7516 "TARGET_ARM"
589fe0fc 7517 "cmp%?\\t%0, %1%S3"
ca68ea18 7518 [(set_attr "conds" "set")
d19fb8e3 7519 (set_attr "shift" "1")
9b66ebb1
PB
7520 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7521 (const_string "alu_shift")
7522 (const_string "alu_shift_reg")))]
cca0a211 7523)
3a33f76f 7524
5b3e6663 7525(define_insn "*arm_cmpsi_shiftsi_swp"
48a08b9c 7526 [(set (reg:CC_SWP CC_REGNUM)
589fe0fc
RE
7527 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7528 [(match_operand:SI 1 "s_register_operand" "r")
7529 (match_operand:SI 2 "reg_or_int_operand" "rM")])
7530 (match_operand:SI 0 "s_register_operand" "r")))]
d5b7b3ae 7531 "TARGET_ARM"
589fe0fc 7532 "cmp%?\\t%0, %1%S3"
ca68ea18 7533 [(set_attr "conds" "set")
d19fb8e3 7534 (set_attr "shift" "1")
9b66ebb1
PB
7535 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7536 (const_string "alu_shift")
7537 (const_string "alu_shift_reg")))]
cca0a211 7538)
3a33f76f 7539
5b3e6663 7540(define_insn "*arm_cmpsi_negshiftsi_si"
1ac3e311
RE
7541 [(set (reg:CC_Z CC_REGNUM)
7542 (compare:CC_Z
7543 (neg:SI (match_operator:SI 1 "shift_operator"
7544 [(match_operand:SI 2 "s_register_operand" "r")
7545 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7546 (match_operand:SI 0 "s_register_operand" "r")))]
d5b7b3ae 7547 "TARGET_ARM"
1ac3e311 7548 "cmn%?\\t%0, %2%S1"
ca68ea18 7549 [(set_attr "conds" "set")
1ac3e311
RE
7550 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7551 (const_string "alu_shift")
7552 (const_string "alu_shift_reg")))]
cca0a211 7553)
3a33f76f 7554
9b6b54e2
NC
7555;; Cirrus SF compare instruction
7556(define_insn "*cirrus_cmpsf"
7557 [(set (reg:CCFP CC_REGNUM)
7558 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7559 (match_operand:SF 1 "cirrus_fp_register" "v")))]
9b66ebb1 7560 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
9b6b54e2 7561 "cfcmps%?\\tr15, %V0, %V1"
f0375c66 7562 [(set_attr "type" "mav_farith")
9b6b54e2
NC
7563 (set_attr "cirrus" "compare")]
7564)
7565
7566;; Cirrus DF compare instruction
7567(define_insn "*cirrus_cmpdf"
7568 [(set (reg:CCFP CC_REGNUM)
7569 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7570 (match_operand:DF 1 "cirrus_fp_register" "v")))]
9b66ebb1 7571 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
9b6b54e2 7572 "cfcmpd%?\\tr15, %V0, %V1"
f0375c66 7573 [(set_attr "type" "mav_farith")
9b6b54e2
NC
7574 (set_attr "cirrus" "compare")]
7575)
7576
9b6b54e2
NC
7577(define_insn "*cirrus_cmpdi"
7578 [(set (reg:CC CC_REGNUM)
7579 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7580 (match_operand:DI 1 "cirrus_fp_register" "v")))]
9b66ebb1 7581 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
9b6b54e2 7582 "cfcmp64%?\\tr15, %V0, %V1"
f0375c66 7583 [(set_attr "type" "mav_farith")
9b6b54e2
NC
7584 (set_attr "cirrus" "compare")]
7585)
7586
ff9940b0
RE
7587; This insn allows redundant compares to be removed by cse, nothing should
7588; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7589; is deleted later on. The match_dup will match the mode here, so that
7590; mode changes of the condition codes aren't lost by this even though we don't
7591; specify what they are.
7592
f54fd62e 7593(define_insn "*deleted_compare"
ff9940b0 7594 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5b3e6663 7595 "TARGET_32BIT"
c63165be 7596 "\\t%@ deleted compare"
d5b7b3ae
RE
7597 [(set_attr "conds" "set")
7598 (set_attr "length" "0")]
7599)
ff9940b0
RE
7600
7601\f
7602;; Conditional branch insns
7603
f90b7a5a 7604(define_expand "cbranch_cc"
ff9940b0 7605 [(set (pc)
f90b7a5a
PB
7606 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7607 (match_operand 2 "" "")])
7608 (label_ref (match_operand 3 "" ""))
ff9940b0 7609 (pc)))]
5b3e6663 7610 "TARGET_32BIT"
f90b7a5a
PB
7611 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7612 operands[1], operands[2]);
7613 operands[2] = const0_rtx;"
05ed98a1
RE
7614)
7615
7616;;
7617;; Patterns to match conditional branch insns.
7618;;
7619
7620; Special pattern to match UNEQ.
7621(define_insn "*arm_buneq"
7622 [(set (pc)
7623 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7624 (label_ref (match_operand 0 "" ""))
7625 (pc)))]
5b3e6663 7626 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1 7627 "*
e6d29d15 7628 gcc_assert (!arm_ccfsm_state);
05ed98a1 7629
3ade30ea 7630 return \"bvs\\t%l0\;beq\\t%l0\";
05ed98a1
RE
7631 "
7632 [(set_attr "conds" "jump_clob")
7633 (set_attr "length" "8")]
7634)
7635
7636; Special pattern to match LTGT.
7637(define_insn "*arm_bltgt"
7638 [(set (pc)
7639 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7640 (label_ref (match_operand 0 "" ""))
7641 (pc)))]
5b3e6663 7642 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1 7643 "*
e6d29d15 7644 gcc_assert (!arm_ccfsm_state);
05ed98a1 7645
3ade30ea 7646 return \"bmi\\t%l0\;bgt\\t%l0\";
05ed98a1
RE
7647 "
7648 [(set_attr "conds" "jump_clob")
7649 (set_attr "length" "8")]
7650)
ff9940b0 7651
d5b7b3ae 7652(define_insn "*arm_cond_branch"
ff9940b0 7653 [(set (pc)
05ed98a1 7654 (if_then_else (match_operator 1 "arm_comparison_operator"
f54fd62e 7655 [(match_operand 2 "cc_register" "") (const_int 0)])
ff9940b0
RE
7656 (label_ref (match_operand 0 "" ""))
7657 (pc)))]
5b3e6663 7658 "TARGET_32BIT"
6d5363fa 7659 "*
ff9940b0 7660 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
d5b7b3ae
RE
7661 {
7662 arm_ccfsm_state += 2;
7663 return \"\";
7664 }
0f447ef2 7665 return \"b%d1\\t%l0\";
d5b7b3ae 7666 "
9b66ebb1
PB
7667 [(set_attr "conds" "use")
7668 (set_attr "type" "branch")]
d5b7b3ae 7669)
6d5363fa 7670
05ed98a1
RE
7671; Special pattern to match reversed UNEQ.
7672(define_insn "*arm_buneq_reversed"
7673 [(set (pc)
7674 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7675 (pc)
7676 (label_ref (match_operand 0 "" ""))))]
75fe7b2f 7677 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1 7678 "*
e6d29d15 7679 gcc_assert (!arm_ccfsm_state);
05ed98a1 7680
3ade30ea 7681 return \"bmi\\t%l0\;bgt\\t%l0\";
05ed98a1
RE
7682 "
7683 [(set_attr "conds" "jump_clob")
7684 (set_attr "length" "8")]
7685)
7686
7687; Special pattern to match reversed LTGT.
7688(define_insn "*arm_bltgt_reversed"
7689 [(set (pc)
7690 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7691 (pc)
7692 (label_ref (match_operand 0 "" ""))))]
75fe7b2f 7693 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1 7694 "*
e6d29d15 7695 gcc_assert (!arm_ccfsm_state);
05ed98a1 7696
3ade30ea 7697 return \"bvs\\t%l0\;beq\\t%l0\";
05ed98a1
RE
7698 "
7699 [(set_attr "conds" "jump_clob")
7700 (set_attr "length" "8")]
7701)
7702
d5b7b3ae 7703(define_insn "*arm_cond_branch_reversed"
ff9940b0 7704 [(set (pc)
05ed98a1 7705 (if_then_else (match_operator 1 "arm_comparison_operator"
f54fd62e 7706 [(match_operand 2 "cc_register" "") (const_int 0)])
ff9940b0
RE
7707 (pc)
7708 (label_ref (match_operand 0 "" ""))))]
5b3e6663 7709 "TARGET_32BIT"
6d5363fa 7710 "*
ff9940b0 7711 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
d5b7b3ae
RE
7712 {
7713 arm_ccfsm_state += 2;
7714 return \"\";
7715 }
0f447ef2 7716 return \"b%D1\\t%l0\";
d5b7b3ae 7717 "
9b66ebb1
PB
7718 [(set_attr "conds" "use")
7719 (set_attr "type" "branch")]
d5b7b3ae
RE
7720)
7721
3a33f76f 7722\f
ff9940b0
RE
7723
7724; scc insns
7725
f90b7a5a 7726(define_expand "cstore_cc"
82955615 7727 [(set (match_operand:SI 0 "s_register_operand" "")
f90b7a5a
PB
7728 (match_operator:SI 1 "" [(match_operand 2 "" "")
7729 (match_operand 3 "" "")]))]
5b3e6663 7730 "TARGET_32BIT"
f90b7a5a
PB
7731 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7732 operands[2], operands[3]);
7733 operands[3] = const0_rtx;"
05ed98a1
RE
7734)
7735
4cdb3ed4 7736(define_insn "*mov_scc"
ff9940b0 7737 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 7738 (match_operator:SI 1 "arm_comparison_operator"
f54fd62e 7739 [(match_operand 2 "cc_register" "") (const_int 0)]))]
d5b7b3ae 7740 "TARGET_ARM"
cce4322b 7741 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
d5b7b3ae
RE
7742 [(set_attr "conds" "use")
7743 (set_attr "length" "8")]
7744)
ff9940b0 7745
4cdb3ed4 7746(define_insn "*mov_negscc"
ff9940b0 7747 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 7748 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
f54fd62e 7749 [(match_operand 2 "cc_register" "") (const_int 0)])))]
d5b7b3ae 7750 "TARGET_ARM"
cce4322b 7751 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
d5b7b3ae
RE
7752 [(set_attr "conds" "use")
7753 (set_attr "length" "8")]
7754)
ff9940b0 7755
4cdb3ed4 7756(define_insn "*mov_notscc"
ff9940b0 7757 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 7758 (not:SI (match_operator:SI 1 "arm_comparison_operator"
f54fd62e 7759 [(match_operand 2 "cc_register" "") (const_int 0)])))]
d5b7b3ae 7760 "TARGET_ARM"
cce4322b 7761 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
d5b7b3ae
RE
7762 [(set_attr "conds" "use")
7763 (set_attr "length" "8")]
7764)
ff9940b0 7765
a41a56b6
RE
7766(define_expand "cstoresi4"
7767 [(set (match_operand:SI 0 "s_register_operand" "")
7768 (match_operator:SI 1 "arm_comparison_operator"
7769 [(match_operand:SI 2 "s_register_operand" "")
7770 (match_operand:SI 3 "reg_or_int_operand" "")]))]
f90b7a5a 7771 "TARGET_32BIT || TARGET_THUMB1"
a41a56b6
RE
7772 "{
7773 rtx op3, scratch, scratch2;
7774
f90b7a5a
PB
7775 if (!TARGET_THUMB1)
7776 {
7777 if (!arm_add_operand (operands[3], SImode))
7778 operands[3] = force_reg (SImode, operands[3]);
7779 emit_insn (gen_cstore_cc (operands[0], operands[1],
7780 operands[2], operands[3]));
7781 DONE;
7782 }
7783
a41a56b6
RE
7784 if (operands[3] == const0_rtx)
7785 {
7786 switch (GET_CODE (operands[1]))
7787 {
7788 case EQ:
5b3e6663 7789 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
a41a56b6
RE
7790 break;
7791
7792 case NE:
5b3e6663 7793 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
a41a56b6
RE
7794 break;
7795
7796 case LE:
7797 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7798 NULL_RTX, 0, OPTAB_WIDEN);
7799 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7800 NULL_RTX, 0, OPTAB_WIDEN);
7801 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7802 operands[0], 1, OPTAB_WIDEN);
7803 break;
7804
7805 case GE:
7806 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7807 NULL_RTX, 1);
7808 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7809 NULL_RTX, 1, OPTAB_WIDEN);
7810 break;
7811
7812 case GT:
7813 scratch = expand_binop (SImode, ashr_optab, operands[2],
7814 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7815 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7816 NULL_RTX, 0, OPTAB_WIDEN);
7817 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7818 0, OPTAB_WIDEN);
7819 break;
7820
7821 /* LT is handled by generic code. No need for unsigned with 0. */
7822 default:
7823 FAIL;
7824 }
7825 DONE;
7826 }
7827
7828 switch (GET_CODE (operands[1]))
7829 {
7830 case EQ:
7831 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7832 NULL_RTX, 0, OPTAB_WIDEN);
5b3e6663 7833 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
a41a56b6
RE
7834 break;
7835
7836 case NE:
7837 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7838 NULL_RTX, 0, OPTAB_WIDEN);
5b3e6663 7839 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
a41a56b6
RE
7840 break;
7841
7842 case LE:
7843 op3 = force_reg (SImode, operands[3]);
7844
7845 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7846 NULL_RTX, 1, OPTAB_WIDEN);
7847 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7848 NULL_RTX, 0, OPTAB_WIDEN);
5b3e6663 7849 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
a41a56b6
RE
7850 op3, operands[2]));
7851 break;
7852
7853 case GE:
7854 op3 = operands[3];
5b3e6663 7855 if (!thumb1_cmp_operand (op3, SImode))
a41a56b6
RE
7856 op3 = force_reg (SImode, op3);
7857 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7858 NULL_RTX, 0, OPTAB_WIDEN);
7859 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7860 NULL_RTX, 1, OPTAB_WIDEN);
5b3e6663 7861 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
a41a56b6
RE
7862 operands[2], op3));
7863 break;
7864
7865 case LEU:
7866 op3 = force_reg (SImode, operands[3]);
7867 scratch = force_reg (SImode, const0_rtx);
5b3e6663 7868 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
a41a56b6
RE
7869 op3, operands[2]));
7870 break;
7871
7872 case GEU:
7873 op3 = operands[3];
5b3e6663 7874 if (!thumb1_cmp_operand (op3, SImode))
a41a56b6
RE
7875 op3 = force_reg (SImode, op3);
7876 scratch = force_reg (SImode, const0_rtx);
5b3e6663 7877 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
a41a56b6
RE
7878 operands[2], op3));
7879 break;
7880
7881 case LTU:
7882 op3 = operands[3];
5b3e6663 7883 if (!thumb1_cmp_operand (op3, SImode))
a41a56b6
RE
7884 op3 = force_reg (SImode, op3);
7885 scratch = gen_reg_rtx (SImode);
5b3e6663 7886 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
a41a56b6
RE
7887 emit_insn (gen_negsi2 (operands[0], scratch));
7888 break;
7889
7890 case GTU:
7891 op3 = force_reg (SImode, operands[3]);
7892 scratch = gen_reg_rtx (SImode);
5b3e6663 7893 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
a41a56b6
RE
7894 emit_insn (gen_negsi2 (operands[0], scratch));
7895 break;
7896
7897 /* No good sequences for GT, LT. */
7898 default:
7899 FAIL;
7900 }
7901 DONE;
7902}")
7903
f90b7a5a
PB
7904(define_expand "cstoresf4"
7905 [(set (match_operand:SI 0 "s_register_operand" "")
7906 (match_operator:SI 1 "arm_comparison_operator"
7907 [(match_operand:SF 2 "s_register_operand" "")
7908 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7909 "TARGET_32BIT && TARGET_HARD_FLOAT"
7910 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7911 operands[2], operands[3])); DONE;"
7912)
7913
7914(define_expand "cstoredf4"
7915 [(set (match_operand:SI 0 "s_register_operand" "")
7916 (match_operator:SI 1 "arm_comparison_operator"
7917 [(match_operand:DF 2 "s_register_operand" "")
7918 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
7919 "TARGET_32BIT && TARGET_HARD_FLOAT"
7920 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7921 operands[2], operands[3])); DONE;"
7922)
7923
7924;; this uses the Cirrus DI compare instruction
7925(define_expand "cstoredi4"
7926 [(set (match_operand:SI 0 "s_register_operand" "")
7927 (match_operator:SI 1 "arm_comparison_operator"
7928 [(match_operand:DI 2 "cirrus_fp_register" "")
7929 (match_operand:DI 3 "cirrus_fp_register" "")]))]
7930 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7931 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7932 operands[2], operands[3])); DONE;"
7933)
7934
7935
5b3e6663 7936(define_expand "cstoresi_eq0_thumb1"
a41a56b6
RE
7937 [(parallel
7938 [(set (match_operand:SI 0 "s_register_operand" "")
7939 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7940 (const_int 0)))
7941 (clobber (match_dup:SI 2))])]
5b3e6663 7942 "TARGET_THUMB1"
a41a56b6
RE
7943 "operands[2] = gen_reg_rtx (SImode);"
7944)
7945
5b3e6663 7946(define_expand "cstoresi_ne0_thumb1"
a41a56b6
RE
7947 [(parallel
7948 [(set (match_operand:SI 0 "s_register_operand" "")
7949 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7950 (const_int 0)))
7951 (clobber (match_dup:SI 2))])]
5b3e6663 7952 "TARGET_THUMB1"
a41a56b6
RE
7953 "operands[2] = gen_reg_rtx (SImode);"
7954)
7955
5b3e6663 7956(define_insn "*cstoresi_eq0_thumb1_insn"
a41a56b6
RE
7957 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7958 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7959 (const_int 0)))
7960 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
5b3e6663 7961 "TARGET_THUMB1"
a41a56b6
RE
7962 "@
7963 neg\\t%0, %1\;adc\\t%0, %0, %1
7964 neg\\t%2, %1\;adc\\t%0, %1, %2"
7965 [(set_attr "length" "4")]
7966)
7967
5b3e6663 7968(define_insn "*cstoresi_ne0_thumb1_insn"
a41a56b6
RE
7969 [(set (match_operand:SI 0 "s_register_operand" "=l")
7970 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7971 (const_int 0)))
7972 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
5b3e6663 7973 "TARGET_THUMB1"
a41a56b6
RE
7974 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7975 [(set_attr "length" "4")]
7976)
7977
5b3e6663 7978(define_insn "cstoresi_nltu_thumb1"
a41a56b6
RE
7979 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7980 (neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
5b3e6663
PB
7981 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7982 "TARGET_THUMB1"
a41a56b6
RE
7983 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7984 [(set_attr "length" "4")]
7985)
7986
7987;; Used as part of the expansion of thumb les sequence.
5b3e6663 7988(define_insn "thumb1_addsi3_addgeu"
a41a56b6
RE
7989 [(set (match_operand:SI 0 "s_register_operand" "=l")
7990 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7991 (match_operand:SI 2 "s_register_operand" "l"))
7992 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
5b3e6663
PB
7993 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7994 "TARGET_THUMB1"
a41a56b6
RE
7995 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7996 [(set_attr "length" "4")]
7997)
7998
ff9940b0 7999\f
e7c3cc84
DE
8000;; Conditional move insns
8001
8002(define_expand "movsicc"
f54fd62e 8003 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 8004 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
589fe0fc 8005 (match_operand:SI 2 "arm_not_operand" "")
f54fd62e 8006 (match_operand:SI 3 "arm_not_operand" "")))]
5b3e6663 8007 "TARGET_32BIT"
e7c3cc84 8008 "
5895f793
RE
8009 {
8010 enum rtx_code code = GET_CODE (operands[1]);
3ade30ea
RE
8011 rtx ccreg;
8012
8013 if (code == UNEQ || code == LTGT)
8014 FAIL;
e7c3cc84 8015
f90b7a5a
PB
8016 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8017 XEXP (operands[1], 1));
1c563bed 8018 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
5895f793
RE
8019 }"
8020)
e7c3cc84
DE
8021
8022(define_expand "movsfcc"
f54fd62e 8023 [(set (match_operand:SF 0 "s_register_operand" "")
05ed98a1 8024 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
f54fd62e
RE
8025 (match_operand:SF 2 "s_register_operand" "")
8026 (match_operand:SF 3 "nonmemory_operand" "")))]
aad2bccb 8027 "TARGET_32BIT && TARGET_HARD_FLOAT"
e7c3cc84 8028 "
5895f793
RE
8029 {
8030 enum rtx_code code = GET_CODE (operands[1]);
8031 rtx ccreg;
7a0a1f09 8032
3ade30ea
RE
8033 if (code == UNEQ || code == LTGT)
8034 FAIL;
8035
5895f793 8036 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
9b66ebb1
PB
8037 Otherwise, ensure it is a valid FP add operand */
8038 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8039 || (!arm_float_add_operand (operands[3], SFmode)))
5895f793 8040 operands[3] = force_reg (SFmode, operands[3]);
e7c3cc84 8041
f90b7a5a
PB
8042 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8043 XEXP (operands[1], 1));
1c563bed 8044 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
5895f793
RE
8045 }"
8046)
e7c3cc84
DE
8047
8048(define_expand "movdfcc"
f54fd62e 8049 [(set (match_operand:DF 0 "s_register_operand" "")
05ed98a1 8050 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
f54fd62e 8051 (match_operand:DF 2 "s_register_operand" "")
9b66ebb1 8052 (match_operand:DF 3 "arm_float_add_operand" "")))]
5b3e6663 8053 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
e7c3cc84 8054 "
5895f793
RE
8055 {
8056 enum rtx_code code = GET_CODE (operands[1]);
3ade30ea 8057 rtx ccreg;
e7c3cc84 8058
3ade30ea
RE
8059 if (code == UNEQ || code == LTGT)
8060 FAIL;
8061
f90b7a5a
PB
8062 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8063 XEXP (operands[1], 1));
1c563bed 8064 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
5895f793
RE
8065 }"
8066)
e7c3cc84
DE
8067
8068(define_insn "*movsicc_insn"
7a0a1f09 8069 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
f54fd62e 8070 (if_then_else:SI
05ed98a1 8071 (match_operator 3 "arm_comparison_operator"
f54fd62e 8072 [(match_operand 4 "cc_register" "") (const_int 0)])
7a0a1f09
RE
8073 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8074 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
d5b7b3ae 8075 "TARGET_ARM"
e7c3cc84 8076 "@
f54fd62e
RE
8077 mov%D3\\t%0, %2
8078 mvn%D3\\t%0, #%B2
7a0a1f09
RE
8079 mov%d3\\t%0, %1
8080 mvn%d3\\t%0, #%B1
f54fd62e
RE
8081 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8082 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8083 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8084 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7a0a1f09 8085 [(set_attr "length" "4,4,4,4,8,8,8,8")
5895f793
RE
8086 (set_attr "conds" "use")]
8087)
e7c3cc84 8088
e7c3cc84 8089(define_insn "*movsfcc_soft_insn"
7a0a1f09 8090 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
05ed98a1 8091 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
f54fd62e 8092 [(match_operand 4 "cc_register" "") (const_int 0)])
7a0a1f09
RE
8093 (match_operand:SF 1 "s_register_operand" "0,r")
8094 (match_operand:SF 2 "s_register_operand" "r,0")))]
d5b7b3ae 8095 "TARGET_ARM && TARGET_SOFT_FLOAT"
7a0a1f09
RE
8096 "@
8097 mov%D3\\t%0, %2
8098 mov%d3\\t%0, %1"
05ed98a1
RE
8099 [(set_attr "conds" "use")]
8100)
e7c3cc84 8101
e7c3cc84 8102\f
ff9940b0
RE
8103;; Jump and linkage insns
8104
d5b7b3ae 8105(define_expand "jump"
ff9940b0
RE
8106 [(set (pc)
8107 (label_ref (match_operand 0 "" "")))]
d5b7b3ae 8108 "TARGET_EITHER"
ff9940b0 8109 ""
d5b7b3ae
RE
8110)
8111
8112(define_insn "*arm_jump"
8113 [(set (pc)
8114 (label_ref (match_operand 0 "" "")))]
5b3e6663 8115 "TARGET_32BIT"
ff9940b0 8116 "*
cca0a211
RE
8117 {
8118 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8119 {
8120 arm_ccfsm_state += 2;
8121 return \"\";
8122 }
8123 return \"b%?\\t%l0\";
8124 }
8125 "
8126 [(set_attr "predicable" "yes")]
8127)
ff9940b0 8128
d5b7b3ae
RE
8129(define_insn "*thumb_jump"
8130 [(set (pc)
8131 (label_ref (match_operand 0 "" "")))]
5b3e6663 8132 "TARGET_THUMB1"
d5b7b3ae
RE
8133 "*
8134 if (get_attr_length (insn) == 2)
8135 return \"b\\t%l0\";
8136 return \"bl\\t%l0\\t%@ far jump\";
8137 "
8138 [(set (attr "far_jump")
8139 (if_then_else
8140 (eq_attr "length" "4")
8141 (const_string "yes")
8142 (const_string "no")))
8143 (set (attr "length")
8144 (if_then_else
a2246edc
NC
8145 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8146 (le (minus (match_dup 0) (pc)) (const_int 2048)))
d5b7b3ae
RE
8147 (const_int 2)
8148 (const_int 4)))]
8149)
8150
c1d5bfb9
RK
8151(define_expand "call"
8152 [(parallel [(call (match_operand 0 "memory_operand" "")
8153 (match_operand 1 "general_operand" ""))
d5b7b3ae 8154 (use (match_operand 2 "" ""))
48a08b9c 8155 (clobber (reg:SI LR_REGNUM))])]
d5b7b3ae 8156 "TARGET_EITHER"
b020fd92
NC
8157 "
8158 {
9403b7f7 8159 rtx callee, pat;
81ee8129 8160
81ee8129
SB
8161 /* In an untyped call, we can get NULL for operand 2. */
8162 if (operands[2] == NULL_RTX)
8163 operands[2] = const0_rtx;
8164
25a65198 8165 /* Decide if we should generate indirect calls by loading the
a50aa827 8166 32-bit address of the callee into a register before performing the
25a65198
RS
8167 branch and link. */
8168 callee = XEXP (operands[0], 0);
8169 if (GET_CODE (callee) == SYMBOL_REF
8170 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8171 : !REG_P (callee))
81ee8129 8172 XEXP (operands[0], 0) = force_reg (Pmode, callee);
9403b7f7
RS
8173
8174 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8175 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8176 DONE;
b020fd92
NC
8177 }"
8178)
c1d5bfb9 8179
9403b7f7
RS
8180(define_expand "call_internal"
8181 [(parallel [(call (match_operand 0 "memory_operand" "")
8182 (match_operand 1 "general_operand" ""))
8183 (use (match_operand 2 "" ""))
8184 (clobber (reg:SI LR_REGNUM))])])
8185
68d560d4 8186(define_insn "*call_reg_armv5"
c1d5bfb9 8187 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
d5b7b3ae
RE
8188 (match_operand 1 "" ""))
8189 (use (match_operand 2 "" ""))
48a08b9c 8190 (clobber (reg:SI LR_REGNUM))]
68d560d4
RE
8191 "TARGET_ARM && arm_arch5"
8192 "blx%?\\t%0"
8193 [(set_attr "type" "call")]
8194)
8195
8196(define_insn "*call_reg_arm"
8197 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8198 (match_operand 1 "" ""))
8199 (use (match_operand 2 "" ""))
8200 (clobber (reg:SI LR_REGNUM))]
8201 "TARGET_ARM && !arm_arch5"
ff9940b0 8202 "*
68df59d3 8203 return output_call (operands);
d5b7b3ae
RE
8204 "
8205 ;; length is worst case, normally it is only two
8206 [(set_attr "length" "12")
8207 (set_attr "type" "call")]
8208)
ff9940b0 8209
4cdb3ed4 8210(define_insn "*call_mem"
e6add59b 8211 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
d5b7b3ae
RE
8212 (match_operand 1 "" ""))
8213 (use (match_operand 2 "" ""))
48a08b9c 8214 (clobber (reg:SI LR_REGNUM))]
d5b7b3ae 8215 "TARGET_ARM"
ff9940b0 8216 "*
68df59d3 8217 return output_call_mem (operands);
d5b7b3ae
RE
8218 "
8219 [(set_attr "length" "12")
8220 (set_attr "type" "call")]
8221)
8222
5b3e6663 8223(define_insn "*call_reg_thumb1_v5"
d5b7b3ae
RE
8224 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8225 (match_operand 1 "" ""))
8226 (use (match_operand 2 "" ""))
48a08b9c 8227 (clobber (reg:SI LR_REGNUM))]
5b3e6663 8228 "TARGET_THUMB1 && arm_arch5"
68d560d4
RE
8229 "blx\\t%0"
8230 [(set_attr "length" "2")
8231 (set_attr "type" "call")]
d5b7b3ae
RE
8232)
8233
5b3e6663 8234(define_insn "*call_reg_thumb1"
68d560d4
RE
8235 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8236 (match_operand 1 "" ""))
8237 (use (match_operand 2 "" ""))
48a08b9c 8238 (clobber (reg:SI LR_REGNUM))]
5b3e6663 8239 "TARGET_THUMB1 && !arm_arch5"
d5b7b3ae
RE
8240 "*
8241 {
a2503645 8242 if (!TARGET_CALLER_INTERWORKING)
b12a00f1 8243 return thumb_call_via_reg (operands[0]);
a2503645 8244 else if (operands[1] == const0_rtx)
68d560d4 8245 return \"bl\\t%__interwork_call_via_%0\";
a2503645
RS
8246 else if (frame_pointer_needed)
8247 return \"bl\\t%__interwork_r7_call_via_%0\";
d5b7b3ae 8248 else
a2503645 8249 return \"bl\\t%__interwork_r11_call_via_%0\";
d5b7b3ae
RE
8250 }"
8251 [(set_attr "type" "call")]
8252)
ff9940b0 8253
c1d5bfb9 8254(define_expand "call_value"
60dd1b7b
AH
8255 [(parallel [(set (match_operand 0 "" "")
8256 (call (match_operand 1 "memory_operand" "")
8257 (match_operand 2 "general_operand" "")))
d5b7b3ae 8258 (use (match_operand 3 "" ""))
48a08b9c 8259 (clobber (reg:SI LR_REGNUM))])]
d5b7b3ae 8260 "TARGET_EITHER"
b020fd92
NC
8261 "
8262 {
9403b7f7 8263 rtx pat, callee;
81ee8129
SB
8264
8265 /* In an untyped call, we can get NULL for operand 2. */
8266 if (operands[3] == 0)
8267 operands[3] = const0_rtx;
8268
25a65198
RS
8269 /* Decide if we should generate indirect calls by loading the
8270 32-bit address of the callee into a register before performing the
8271 branch and link. */
8272 callee = XEXP (operands[1], 0);
8273 if (GET_CODE (callee) == SYMBOL_REF
8274 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8275 : !REG_P (callee))
c27ba912 8276 XEXP (operands[1], 0) = force_reg (Pmode, callee);
9403b7f7
RS
8277
8278 pat = gen_call_value_internal (operands[0], operands[1],
8279 operands[2], operands[3]);
8280 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8281 DONE;
b020fd92
NC
8282 }"
8283)
c1d5bfb9 8284
9403b7f7
RS
8285(define_expand "call_value_internal"
8286 [(parallel [(set (match_operand 0 "" "")
8287 (call (match_operand 1 "memory_operand" "")
8288 (match_operand 2 "general_operand" "")))
8289 (use (match_operand 3 "" ""))
8290 (clobber (reg:SI LR_REGNUM))])])
8291
68d560d4 8292(define_insn "*call_value_reg_armv5"
24391720 8293 [(set (match_operand 0 "" "")
5a9335ef 8294 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
d5b7b3ae 8295 (match_operand 2 "" "")))
81ee8129 8296 (use (match_operand 3 "" ""))
48a08b9c 8297 (clobber (reg:SI LR_REGNUM))]
68d560d4
RE
8298 "TARGET_ARM && arm_arch5"
8299 "blx%?\\t%1"
8300 [(set_attr "type" "call")]
8301)
8302
8303(define_insn "*call_value_reg_arm"
8304 [(set (match_operand 0 "" "")
8305 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8306 (match_operand 2 "" "")))
8307 (use (match_operand 3 "" ""))
8308 (clobber (reg:SI LR_REGNUM))]
8309 "TARGET_ARM && !arm_arch5"
ff9940b0 8310 "*
5895f793 8311 return output_call (&operands[1]);
d5b7b3ae
RE
8312 "
8313 [(set_attr "length" "12")
8314 (set_attr "type" "call")]
8315)
ff9940b0 8316
4cdb3ed4 8317(define_insn "*call_value_mem"
24391720 8318 [(set (match_operand 0 "" "")
e6add59b 8319 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
d5b7b3ae 8320 (match_operand 2 "" "")))
81ee8129 8321 (use (match_operand 3 "" ""))
48a08b9c 8322 (clobber (reg:SI LR_REGNUM))]
5895f793 8323 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
ff9940b0 8324 "*
5895f793 8325 return output_call_mem (&operands[1]);
d5b7b3ae
RE
8326 "
8327 [(set_attr "length" "12")
8328 (set_attr "type" "call")]
8329)
ff9940b0 8330
5b3e6663 8331(define_insn "*call_value_reg_thumb1_v5"
68d560d4
RE
8332 [(set (match_operand 0 "" "")
8333 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8334 (match_operand 2 "" "")))
8335 (use (match_operand 3 "" ""))
8336 (clobber (reg:SI LR_REGNUM))]
5b3e6663 8337 "TARGET_THUMB1 && arm_arch5"
68d560d4
RE
8338 "blx\\t%1"
8339 [(set_attr "length" "2")
8340 (set_attr "type" "call")]
8341)
8342
5b3e6663 8343(define_insn "*call_value_reg_thumb1"
68d560d4
RE
8344 [(set (match_operand 0 "" "")
8345 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8346 (match_operand 2 "" "")))
8347 (use (match_operand 3 "" ""))
8348 (clobber (reg:SI LR_REGNUM))]
5b3e6663 8349 "TARGET_THUMB1 && !arm_arch5"
68d560d4
RE
8350 "*
8351 {
a2503645 8352 if (!TARGET_CALLER_INTERWORKING)
b12a00f1 8353 return thumb_call_via_reg (operands[1]);
a2503645 8354 else if (operands[2] == const0_rtx)
68d560d4 8355 return \"bl\\t%__interwork_call_via_%1\";
a2503645
RS
8356 else if (frame_pointer_needed)
8357 return \"bl\\t%__interwork_r7_call_via_%1\";
68d560d4 8358 else
a2503645 8359 return \"bl\\t%__interwork_r11_call_via_%1\";
68d560d4
RE
8360 }"
8361 [(set_attr "type" "call")]
8362)
8363
ff9940b0
RE
8364;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8365;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8366
4cdb3ed4 8367(define_insn "*call_symbol"
24391720 8368 [(call (mem:SI (match_operand:SI 0 "" ""))
d5b7b3ae 8369 (match_operand 1 "" ""))
81ee8129 8370 (use (match_operand 2 "" ""))
48a08b9c 8371 (clobber (reg:SI LR_REGNUM))]
d5b7b3ae
RE
8372 "TARGET_ARM
8373 && (GET_CODE (operands[0]) == SYMBOL_REF)
25a65198 8374 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
86efdc8e
PB
8375 "*
8376 {
ed0e6530 8377 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
86efdc8e 8378 }"
d5b7b3ae
RE
8379 [(set_attr "type" "call")]
8380)
ff9940b0 8381
4cdb3ed4 8382(define_insn "*call_value_symbol"
9f7bf991 8383 [(set (match_operand 0 "" "")
24391720 8384 (call (mem:SI (match_operand:SI 1 "" ""))
41e3f998 8385 (match_operand:SI 2 "" "")))
81ee8129 8386 (use (match_operand 3 "" ""))
48a08b9c 8387 (clobber (reg:SI LR_REGNUM))]
d5b7b3ae
RE
8388 "TARGET_ARM
8389 && (GET_CODE (operands[1]) == SYMBOL_REF)
25a65198 8390 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
86efdc8e
PB
8391 "*
8392 {
ed0e6530 8393 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
86efdc8e 8394 }"
d5b7b3ae
RE
8395 [(set_attr "type" "call")]
8396)
8397
8398(define_insn "*call_insn"
24391720 8399 [(call (mem:SI (match_operand:SI 0 "" ""))
d5b7b3ae
RE
8400 (match_operand:SI 1 "" ""))
8401 (use (match_operand 2 "" ""))
48a08b9c 8402 (clobber (reg:SI LR_REGNUM))]
0616531f 8403 "TARGET_THUMB
7b8781c8 8404 && GET_CODE (operands[0]) == SYMBOL_REF
25a65198 8405 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
d5b7b3ae
RE
8406 "bl\\t%a0"
8407 [(set_attr "length" "4")
8408 (set_attr "type" "call")]
8409)
8410
8411(define_insn "*call_value_insn"
9f7bf991 8412 [(set (match_operand 0 "" "")
24391720 8413 (call (mem:SI (match_operand 1 "" ""))
d5b7b3ae
RE
8414 (match_operand 2 "" "")))
8415 (use (match_operand 3 "" ""))
48a08b9c 8416 (clobber (reg:SI LR_REGNUM))]
0616531f 8417 "TARGET_THUMB
7b8781c8 8418 && GET_CODE (operands[1]) == SYMBOL_REF
25a65198 8419 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
d5b7b3ae
RE
8420 "bl\\t%a1"
8421 [(set_attr "length" "4")
8422 (set_attr "type" "call")]
8423)
ff9940b0 8424
0616531f
RE
8425;; We may also be able to do sibcalls for Thumb, but it's much harder...
8426(define_expand "sibcall"
8427 [(parallel [(call (match_operand 0 "memory_operand" "")
8428 (match_operand 1 "general_operand" ""))
72b075d1
RE
8429 (return)
8430 (use (match_operand 2 "" ""))])]
0616531f
RE
8431 "TARGET_ARM"
8432 "
8433 {
8434 if (operands[2] == NULL_RTX)
8435 operands[2] = const0_rtx;
0616531f
RE
8436 }"
8437)
8438
8439(define_expand "sibcall_value"
9f7bf991 8440 [(parallel [(set (match_operand 0 "" "")
0616531f
RE
8441 (call (match_operand 1 "memory_operand" "")
8442 (match_operand 2 "general_operand" "")))
72b075d1
RE
8443 (return)
8444 (use (match_operand 3 "" ""))])]
0616531f
RE
8445 "TARGET_ARM"
8446 "
8447 {
8448 if (operands[3] == NULL_RTX)
8449 operands[3] = const0_rtx;
0616531f
RE
8450 }"
8451)
8452
8453(define_insn "*sibcall_insn"
8454 [(call (mem:SI (match_operand:SI 0 "" "X"))
8455 (match_operand 1 "" ""))
72b075d1
RE
8456 (return)
8457 (use (match_operand 2 "" ""))]
0616531f
RE
8458 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8459 "*
8460 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8461 "
8462 [(set_attr "type" "call")]
8463)
8464
8465(define_insn "*sibcall_value_insn"
9f7bf991 8466 [(set (match_operand 0 "" "")
5a9335ef 8467 (call (mem:SI (match_operand:SI 1 "" "X"))
0616531f 8468 (match_operand 2 "" "")))
72b075d1
RE
8469 (return)
8470 (use (match_operand 3 "" ""))]
0616531f
RE
8471 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8472 "*
8473 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8474 "
8475 [(set_attr "type" "call")]
8476)
8477
ff9940b0
RE
8478;; Often the return insn will be the same as loading from memory, so set attr
8479(define_insn "return"
8480 [(return)]
d5b7b3ae 8481 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
ff9940b0 8482 "*
ff9940b0 8483 {
d5b7b3ae
RE
8484 if (arm_ccfsm_state == 2)
8485 {
8486 arm_ccfsm_state += 2;
8487 return \"\";
8488 }
64e92a26 8489 return output_return_instruction (const_true_rtx, TRUE, FALSE);
d5b7b3ae 8490 }"
9b66ebb1 8491 [(set_attr "type" "load1")
5a9335ef 8492 (set_attr "length" "12")
cca0a211 8493 (set_attr "predicable" "yes")]
d5b7b3ae 8494)
ff9940b0 8495
4cdb3ed4 8496(define_insn "*cond_return"
ff9940b0 8497 [(set (pc)
05ed98a1 8498 (if_then_else (match_operator 0 "arm_comparison_operator"
f54fd62e 8499 [(match_operand 1 "cc_register" "") (const_int 0)])
ff9940b0
RE
8500 (return)
8501 (pc)))]
d5b7b3ae 8502 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
ff9940b0 8503 "*
05ed98a1
RE
8504 {
8505 if (arm_ccfsm_state == 2)
8506 {
8507 arm_ccfsm_state += 2;
8508 return \"\";
8509 }
8510 return output_return_instruction (operands[0], TRUE, FALSE);
8511 }"
8512 [(set_attr "conds" "use")
5a9335ef 8513 (set_attr "length" "12")
9b66ebb1 8514 (set_attr "type" "load1")]
05ed98a1 8515)
ff9940b0 8516
4cdb3ed4 8517(define_insn "*cond_return_inverted"
ff9940b0 8518 [(set (pc)
05ed98a1 8519 (if_then_else (match_operator 0 "arm_comparison_operator"
f54fd62e 8520 [(match_operand 1 "cc_register" "") (const_int 0)])
ff9940b0
RE
8521 (pc)
8522 (return)))]
d5b7b3ae 8523 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
ff9940b0 8524 "*
05ed98a1
RE
8525 {
8526 if (arm_ccfsm_state == 2)
8527 {
8528 arm_ccfsm_state += 2;
8529 return \"\";
8530 }
8531 return output_return_instruction (operands[0], TRUE, TRUE);
8532 }"
8533 [(set_attr "conds" "use")
3e1b8dc0 8534 (set_attr "length" "12")
9b66ebb1 8535 (set_attr "type" "load1")]
05ed98a1 8536)
ff9940b0 8537
fcd53748
JT
8538;; Generate a sequence of instructions to determine if the processor is
8539;; in 26-bit or 32-bit mode, and return the appropriate return address
8540;; mask.
8541
8542(define_expand "return_addr_mask"
8543 [(set (match_dup 1)
8544 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8545 (const_int 0)))
8546 (set (match_operand:SI 0 "s_register_operand" "")
8547 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8548 (const_int -1)
8549 (const_int 67108860)))] ; 0x03fffffc
8550 "TARGET_ARM"
8551 "
20ae4500 8552 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
fcd53748
JT
8553 ")
8554
8555(define_insn "*check_arch2"
8556 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8557 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8558 (const_int 0)))]
8559 "TARGET_ARM"
8560 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8561 [(set_attr "length" "8")
8562 (set_attr "conds" "set")]
8563)
8564
ff9940b0
RE
8565;; Call subroutine returning any type.
8566
8567(define_expand "untyped_call"
8568 [(parallel [(call (match_operand 0 "" "")
8569 (const_int 0))
8570 (match_operand 1 "" "")
8571 (match_operand 2 "" "")])]
9f7bf991 8572 "TARGET_EITHER"
ff9940b0 8573 "
5895f793
RE
8574 {
8575 int i;
9f7bf991
RE
8576 rtx par = gen_rtx_PARALLEL (VOIDmode,
8577 rtvec_alloc (XVECLEN (operands[2], 0)));
8578 rtx addr = gen_reg_rtx (Pmode);
8579 rtx mem;
8580 int size = 0;
ff9940b0 8581
9f7bf991
RE
8582 emit_move_insn (addr, XEXP (operands[1], 0));
8583 mem = change_address (operands[1], BLKmode, addr);
ff9940b0 8584
5895f793
RE
8585 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8586 {
9f7bf991 8587 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
ff9940b0 8588
9f7bf991
RE
8589 /* Default code only uses r0 as a return value, but we could
8590 be using anything up to 4 registers. */
8591 if (REGNO (src) == R0_REGNUM)
8592 src = gen_rtx_REG (TImode, R0_REGNUM);
8593
8594 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8595 GEN_INT (size));
8596 size += GET_MODE_SIZE (GET_MODE (src));
8597 }
8598
8599 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8600 const0_rtx));
8601
8602 size = 0;
8603
8604 for (i = 0; i < XVECLEN (par, 0); i++)
8605 {
8606 HOST_WIDE_INT offset = 0;
8607 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8608
8609 if (size != 0)
8610 emit_move_insn (addr, plus_constant (addr, size));
8611
8612 mem = change_address (mem, GET_MODE (reg), NULL);
8613 if (REGNO (reg) == R0_REGNUM)
8614 {
8615 /* On thumb we have to use a write-back instruction. */
8616 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8617 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8618 size = TARGET_ARM ? 16 : 0;
8619 }
8620 else
8621 {
8622 emit_move_insn (mem, reg);
8623 size = GET_MODE_SIZE (GET_MODE (reg));
8624 }
5895f793 8625 }
ff9940b0 8626
5895f793
RE
8627 /* The optimizer does not know that the call sets the function value
8628 registers we stored in the result block. We avoid problems by
8629 claiming that all hard registers are used and clobbered at this
8630 point. */
8631 emit_insn (gen_blockage ());
8632
8633 DONE;
8634 }"
8635)
ff9940b0 8636
9f7bf991
RE
8637(define_expand "untyped_return"
8638 [(match_operand:BLK 0 "memory_operand" "")
8639 (match_operand 1 "" "")]
8640 "TARGET_EITHER"
8641 "
8642 {
8643 int i;
8644 rtx addr = gen_reg_rtx (Pmode);
8645 rtx mem;
8646 int size = 0;
8647
8648 emit_move_insn (addr, XEXP (operands[0], 0));
8649 mem = change_address (operands[0], BLKmode, addr);
8650
8651 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8652 {
8653 HOST_WIDE_INT offset = 0;
8654 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8655
8656 if (size != 0)
8657 emit_move_insn (addr, plus_constant (addr, size));
8658
8659 mem = change_address (mem, GET_MODE (reg), NULL);
8660 if (REGNO (reg) == R0_REGNUM)
8661 {
8662 /* On thumb we have to use a write-back instruction. */
8663 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8664 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8665 size = TARGET_ARM ? 16 : 0;
8666 }
8667 else
8668 {
8669 emit_move_insn (reg, mem);
8670 size = GET_MODE_SIZE (GET_MODE (reg));
8671 }
8672 }
8673
8674 /* Emit USE insns before the return. */
8675 for (i = 0; i < XVECLEN (operands[1], 0); i++)
c41c1387 8676 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
9f7bf991
RE
8677
8678 /* Construct the return. */
8679 expand_naked_return ();
8680
8681 DONE;
8682 }"
8683)
8684
ff9940b0
RE
8685;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8686;; all of memory. This blocks insns from being moved across this point.
8687
8688(define_insn "blockage"
b15bca31 8689 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
d5b7b3ae 8690 "TARGET_EITHER"
ff9940b0 8691 ""
d5b7b3ae
RE
8692 [(set_attr "length" "0")
8693 (set_attr "type" "block")]
8694)
ff9940b0 8695
4cdb3ed4
RE
8696(define_expand "casesi"
8697 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
589fe0fc
RE
8698 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8699 (match_operand:SI 2 "const_int_operand" "") ; total range
4cdb3ed4
RE
8700 (match_operand:SI 3 "" "") ; table label
8701 (match_operand:SI 4 "" "")] ; Out of range label
5b3e6663 8702 "TARGET_32BIT"
4cdb3ed4 8703 "
5895f793
RE
8704 {
8705 rtx reg;
8706 if (operands[1] != const0_rtx)
8707 {
8708 reg = gen_reg_rtx (SImode);
4cdb3ed4 8709
5895f793
RE
8710 emit_insn (gen_addsi3 (reg, operands[0],
8711 GEN_INT (-INTVAL (operands[1]))));
8712 operands[0] = reg;
8713 }
ff9940b0 8714
5895f793
RE
8715 if (!const_ok_for_arm (INTVAL (operands[2])))
8716 operands[2] = force_reg (SImode, operands[2]);
8717
5b3e6663
PB
8718 if (TARGET_ARM)
8719 {
8720 emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
8721 operands[3], operands[4]));
8722 }
8723 else if (flag_pic)
8724 {
8725 emit_jump_insn (gen_thumb2_casesi_internal_pic (operands[0],
8726 operands[2], operands[3], operands[4]));
8727 }
8728 else
8729 {
8730 emit_jump_insn (gen_thumb2_casesi_internal (operands[0], operands[2],
8731 operands[3], operands[4]));
8732 }
5895f793
RE
8733 DONE;
8734 }"
8735)
4cdb3ed4 8736
7a0a1f09
RE
8737;; The USE in this pattern is needed to tell flow analysis that this is
8738;; a CASESI insn. It has no other purpose.
5b3e6663 8739(define_insn "arm_casesi_internal"
7a0a1f09
RE
8740 [(parallel [(set (pc)
8741 (if_then_else
8742 (leu (match_operand:SI 0 "s_register_operand" "r")
8743 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8744 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8745 (label_ref (match_operand 2 "" ""))))
8746 (label_ref (match_operand 3 "" ""))))
48a08b9c 8747 (clobber (reg:CC CC_REGNUM))
7a0a1f09 8748 (use (label_ref (match_dup 2)))])]
d5b7b3ae 8749 "TARGET_ARM"
4cdb3ed4 8750 "*
cca0a211
RE
8751 if (flag_pic)
8752 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8753 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8754 "
8755 [(set_attr "conds" "clob")
8756 (set_attr "length" "12")]
8757)
ff9940b0 8758
d5b7b3ae 8759(define_expand "indirect_jump"
ff9940b0 8760 [(set (pc)
d5b7b3ae
RE
8761 (match_operand:SI 0 "s_register_operand" ""))]
8762 "TARGET_EITHER"
5b3e6663
PB
8763 "
8764 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8765 address and use bx. */
8766 if (TARGET_THUMB2)
8767 {
8768 rtx tmp;
8769 tmp = gen_reg_rtx (SImode);
8770 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8771 operands[0] = tmp;
8772 }
8773 "
d5b7b3ae
RE
8774)
8775
68d560d4 8776;; NB Never uses BX.
d5b7b3ae
RE
8777(define_insn "*arm_indirect_jump"
8778 [(set (pc)
8779 (match_operand:SI 0 "s_register_operand" "r"))]
8780 "TARGET_ARM"
8781 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
cca0a211 8782 [(set_attr "predicable" "yes")]
d5b7b3ae 8783)
ff9940b0 8784
4cdb3ed4 8785(define_insn "*load_indirect_jump"
ff9940b0
RE
8786 [(set (pc)
8787 (match_operand:SI 0 "memory_operand" "m"))]
d5b7b3ae
RE
8788 "TARGET_ARM"
8789 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9b66ebb1 8790 [(set_attr "type" "load1")
859230d4
NC
8791 (set_attr "pool_range" "4096")
8792 (set_attr "neg_pool_range" "4084")
cca0a211 8793 (set_attr "predicable" "yes")]
d5b7b3ae
RE
8794)
8795
68d560d4 8796;; NB Never uses BX.
5b3e6663 8797(define_insn "*thumb1_indirect_jump"
d5b7b3ae
RE
8798 [(set (pc)
8799 (match_operand:SI 0 "register_operand" "l*r"))]
5b3e6663 8800 "TARGET_THUMB1"
d5b7b3ae
RE
8801 "mov\\tpc, %0"
8802 [(set_attr "conds" "clob")
8803 (set_attr "length" "2")]
8804)
8805
ff9940b0
RE
8806\f
8807;; Misc insns
8808
8809(define_insn "nop"
8810 [(const_int 0)]
d5b7b3ae
RE
8811 "TARGET_EITHER"
8812 "*
5b3e6663
PB
8813 if (TARGET_UNIFIED_ASM)
8814 return \"nop\";
d5b7b3ae
RE
8815 if (TARGET_ARM)
8816 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8817 return \"mov\\tr8, r8\";
8818 "
8819 [(set (attr "length")
8820 (if_then_else (eq_attr "is_thumb" "yes")
8821 (const_int 2)
8822 (const_int 4)))]
8823)
8824
ff9940b0
RE
8825\f
8826;; Patterns to allow combination of arithmetic, cond code and shifts
8827
4cdb3ed4 8828(define_insn "*arith_shiftsi"
ff9940b0
RE
8829 [(set (match_operand:SI 0 "s_register_operand" "=r")
8830 (match_operator:SI 1 "shiftable_operator"
8831 [(match_operator:SI 3 "shift_operator"
8832 [(match_operand:SI 4 "s_register_operand" "r")
091426d3 8833 (match_operand:SI 5 "reg_or_int_operand" "rI")])
ff9940b0 8834 (match_operand:SI 2 "s_register_operand" "r")]))]
d5b7b3ae 8835 "TARGET_ARM"
b020fd92 8836 "%i1%?\\t%0, %2, %4%S3"
ca68ea18 8837 [(set_attr "predicable" "yes")
d19fb8e3 8838 (set_attr "shift" "4")
9b66ebb1
PB
8839 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8840 (const_string "alu_shift")
8841 (const_string "alu_shift_reg")))]
b020fd92 8842)
ff9940b0 8843
da5cafa7
RE
8844(define_split
8845 [(set (match_operand:SI 0 "s_register_operand" "")
8846 (match_operator:SI 1 "shiftable_operator"
8847 [(match_operator:SI 2 "shiftable_operator"
8848 [(match_operator:SI 3 "shift_operator"
8849 [(match_operand:SI 4 "s_register_operand" "")
8850 (match_operand:SI 5 "reg_or_int_operand" "")])
8851 (match_operand:SI 6 "s_register_operand" "")])
8852 (match_operand:SI 7 "arm_rhs_operand" "")]))
8853 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8854 "TARGET_ARM"
8855 [(set (match_dup 8)
8856 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8857 (match_dup 6)]))
8858 (set (match_dup 0)
8859 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8860 "")
8861
4cdb3ed4 8862(define_insn "*arith_shiftsi_compare0"
48a08b9c 8863 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
8864 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8865 [(match_operator:SI 3 "shift_operator"
8866 [(match_operand:SI 4 "s_register_operand" "r")
091426d3 8867 (match_operand:SI 5 "reg_or_int_operand" "rI")])
ff9940b0
RE
8868 (match_operand:SI 2 "s_register_operand" "r")])
8869 (const_int 0)))
8870 (set (match_operand:SI 0 "s_register_operand" "=r")
8871 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8872 (match_dup 2)]))]
d5b7b3ae 8873 "TARGET_ARM"
5b3e6663 8874 "%i1%.\\t%0, %2, %4%S3"
ca68ea18 8875 [(set_attr "conds" "set")
d19fb8e3 8876 (set_attr "shift" "4")
9b66ebb1
PB
8877 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8878 (const_string "alu_shift")
8879 (const_string "alu_shift_reg")))]
cca0a211 8880)
ff9940b0 8881
4cdb3ed4 8882(define_insn "*arith_shiftsi_compare0_scratch"
48a08b9c 8883 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
8884 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8885 [(match_operator:SI 3 "shift_operator"
8886 [(match_operand:SI 4 "s_register_operand" "r")
091426d3 8887 (match_operand:SI 5 "reg_or_int_operand" "rI")])
ff9940b0
RE
8888 (match_operand:SI 2 "s_register_operand" "r")])
8889 (const_int 0)))
8890 (clobber (match_scratch:SI 0 "=r"))]
d5b7b3ae 8891 "TARGET_ARM"
5b3e6663 8892 "%i1%.\\t%0, %2, %4%S3"
ca68ea18 8893 [(set_attr "conds" "set")
d19fb8e3 8894 (set_attr "shift" "4")
9b66ebb1
PB
8895 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8896 (const_string "alu_shift")
8897 (const_string "alu_shift_reg")))]
cca0a211 8898)
ff9940b0 8899
4cdb3ed4 8900(define_insn "*sub_shiftsi"
ff9940b0
RE
8901 [(set (match_operand:SI 0 "s_register_operand" "=r")
8902 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8903 (match_operator:SI 2 "shift_operator"
8904 [(match_operand:SI 3 "s_register_operand" "r")
091426d3 8905 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
d5b7b3ae 8906 "TARGET_ARM"
b020fd92 8907 "sub%?\\t%0, %1, %3%S2"
ca68ea18 8908 [(set_attr "predicable" "yes")
d19fb8e3 8909 (set_attr "shift" "3")
9b66ebb1
PB
8910 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8911 (const_string "alu_shift")
8912 (const_string "alu_shift_reg")))]
b020fd92 8913)
ff9940b0 8914
4cdb3ed4 8915(define_insn "*sub_shiftsi_compare0"
48a08b9c 8916 [(set (reg:CC_NOOV CC_REGNUM)
c63165be
RE
8917 (compare:CC_NOOV
8918 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8919 (match_operator:SI 2 "shift_operator"
8920 [(match_operand:SI 3 "s_register_operand" "r")
091426d3 8921 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
c63165be 8922 (const_int 0)))
ff9940b0
RE
8923 (set (match_operand:SI 0 "s_register_operand" "=r")
8924 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8925 (match_dup 4)])))]
d5b7b3ae 8926 "TARGET_ARM"
5b3e6663 8927 "sub%.\\t%0, %1, %3%S2"
ca68ea18 8928 [(set_attr "conds" "set")
9b66ebb1
PB
8929 (set_attr "shift" "3")
8930 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8931 (const_string "alu_shift")
8932 (const_string "alu_shift_reg")))]
cca0a211 8933)
ff9940b0 8934
4cdb3ed4 8935(define_insn "*sub_shiftsi_compare0_scratch"
48a08b9c 8936 [(set (reg:CC_NOOV CC_REGNUM)
c63165be
RE
8937 (compare:CC_NOOV
8938 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8939 (match_operator:SI 2 "shift_operator"
8940 [(match_operand:SI 3 "s_register_operand" "r")
091426d3 8941 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
c63165be 8942 (const_int 0)))
ff9940b0 8943 (clobber (match_scratch:SI 0 "=r"))]
d5b7b3ae 8944 "TARGET_ARM"
5b3e6663 8945 "sub%.\\t%0, %1, %3%S2"
ca68ea18 8946 [(set_attr "conds" "set")
9b66ebb1
PB
8947 (set_attr "shift" "3")
8948 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8949 (const_string "alu_shift")
8950 (const_string "alu_shift_reg")))]
cca0a211 8951)
ff9940b0 8952
ff9940b0
RE
8953\f
8954
4cdb3ed4 8955(define_insn "*and_scc"
ff9940b0 8956 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 8957 (and:SI (match_operator:SI 1 "arm_comparison_operator"
589fe0fc 8958 [(match_operand 3 "cc_register" "") (const_int 0)])
ff9940b0 8959 (match_operand:SI 2 "s_register_operand" "r")))]
d5b7b3ae 8960 "TARGET_ARM"
0f447ef2 8961 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
05ed98a1
RE
8962 [(set_attr "conds" "use")
8963 (set_attr "length" "8")]
8964)
ff9940b0 8965
4cdb3ed4 8966(define_insn "*ior_scc"
ff9940b0 8967 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 8968 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
f54fd62e 8969 [(match_operand 3 "cc_register" "") (const_int 0)])
ff9940b0 8970 (match_operand:SI 1 "s_register_operand" "0,?r")))]
d5b7b3ae 8971 "TARGET_ARM"
0f447ef2 8972 "@
916cc8c5
RE
8973 orr%d2\\t%0, %1, #1
8974 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
05ed98a1
RE
8975 [(set_attr "conds" "use")
8976 (set_attr "length" "4,8")]
8977)
ff9940b0 8978
4cdb3ed4 8979(define_insn "*compare_scc"
68df59d3 8980 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 8981 (match_operator:SI 1 "arm_comparison_operator"
68df59d3
RE
8982 [(match_operand:SI 2 "s_register_operand" "r,r")
8983 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
48a08b9c 8984 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 8985 "TARGET_ARM"
ff9940b0 8986 "*
9af66e58
RE
8987 if (operands[3] == const0_rtx)
8988 {
8989 if (GET_CODE (operands[1]) == LT)
8990 return \"mov\\t%0, %2, lsr #31\";
8991
8992 if (GET_CODE (operands[1]) == GE)
8993 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
0f447ef2 8994
9af66e58
RE
8995 if (GET_CODE (operands[1]) == EQ)
8996 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8997 }
0f447ef2 8998
05ed98a1
RE
8999 if (GET_CODE (operands[1]) == NE)
9000 {
9001 if (which_alternative == 1)
9002 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9003 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9004 }
9005 if (which_alternative == 1)
9006 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9007 else
9008 output_asm_insn (\"cmp\\t%2, %3\", operands);
9009 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9010 "
9011 [(set_attr "conds" "clob")
9012 (set_attr "length" "12")]
9013)
ff9940b0 9014
4cdb3ed4 9015(define_insn "*cond_move"
ff9940b0 9016 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
589fe0fc 9017 (if_then_else:SI (match_operator 3 "equality_operator"
05ed98a1 9018 [(match_operator 4 "arm_comparison_operator"
f54fd62e 9019 [(match_operand 5 "cc_register" "") (const_int 0)])
589fe0fc
RE
9020 (const_int 0)])
9021 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9022 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
d5b7b3ae 9023 "TARGET_ARM"
ff9940b0 9024 "*
05ed98a1
RE
9025 if (GET_CODE (operands[3]) == NE)
9026 {
9027 if (which_alternative != 1)
9028 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9029 if (which_alternative != 0)
9030 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9031 return \"\";
9032 }
9033 if (which_alternative != 0)
9034 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9035 if (which_alternative != 1)
9036 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9037 return \"\";
9038 "
9039 [(set_attr "conds" "use")
9040 (set_attr "length" "4,4,8")]
9041)
ff9940b0 9042
4cdb3ed4 9043(define_insn "*cond_arith"
ff9940b0
RE
9044 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9045 (match_operator:SI 5 "shiftable_operator"
05ed98a1 9046 [(match_operator:SI 4 "arm_comparison_operator"
ff9940b0
RE
9047 [(match_operand:SI 2 "s_register_operand" "r,r")
9048 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9049 (match_operand:SI 1 "s_register_operand" "0,?r")]))
48a08b9c 9050 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9051 "TARGET_ARM"
ff9940b0 9052 "*
05ed98a1
RE
9053 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9054 return \"%i5\\t%0, %1, %2, lsr #31\";
c63165be 9055
05ed98a1
RE
9056 output_asm_insn (\"cmp\\t%2, %3\", operands);
9057 if (GET_CODE (operands[5]) == AND)
9058 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9059 else if (GET_CODE (operands[5]) == MINUS)
9060 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9061 else if (which_alternative != 0)
9062 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9063 return \"%i5%d4\\t%0, %1, #1\";
9064 "
9065 [(set_attr "conds" "clob")
9066 (set_attr "length" "12")]
9067)
ff9940b0 9068
4cdb3ed4 9069(define_insn "*cond_sub"
ff9940b0
RE
9070 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9071 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
05ed98a1 9072 (match_operator:SI 4 "arm_comparison_operator"
ff9940b0
RE
9073 [(match_operand:SI 2 "s_register_operand" "r,r")
9074 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
48a08b9c 9075 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9076 "TARGET_ARM"
ff9940b0 9077 "*
05ed98a1
RE
9078 output_asm_insn (\"cmp\\t%2, %3\", operands);
9079 if (which_alternative != 0)
9080 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9081 return \"sub%d4\\t%0, %1, #1\";
9082 "
9083 [(set_attr "conds" "clob")
9084 (set_attr "length" "8,12")]
9085)
ff9940b0 9086
5b3e6663 9087;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
589fe0fc 9088(define_insn "*cmp_ite0"
d5b7b3ae 9089 [(set (match_operand 6 "dominant_cc_register" "")
589fe0fc
RE
9090 (compare
9091 (if_then_else:SI
05ed98a1 9092 (match_operator 4 "arm_comparison_operator"
589fe0fc
RE
9093 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9094 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
05ed98a1 9095 (match_operator:SI 5 "arm_comparison_operator"
589fe0fc
RE
9096 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9097 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9098 (const_int 0))
9099 (const_int 0)))]
d5b7b3ae 9100 "TARGET_ARM"
ff9940b0 9101 "*
589fe0fc 9102 {
05ed98a1
RE
9103 static const char * const opcodes[4][2] =
9104 {
9105 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9106 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9107 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9108 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9109 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9110 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9111 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9112 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9113 };
9114 int swap =
9115 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9116
9117 return opcodes[which_alternative][swap];
9118 }"
9119 [(set_attr "conds" "set")
9120 (set_attr "length" "8")]
9121)
ff9940b0 9122
589fe0fc 9123(define_insn "*cmp_ite1"
d5b7b3ae 9124 [(set (match_operand 6 "dominant_cc_register" "")
589fe0fc
RE
9125 (compare
9126 (if_then_else:SI
05ed98a1 9127 (match_operator 4 "arm_comparison_operator"
589fe0fc 9128 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
a0b632ec 9129 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
05ed98a1 9130 (match_operator:SI 5 "arm_comparison_operator"
589fe0fc 9131 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
a0b632ec 9132 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
589fe0fc
RE
9133 (const_int 1))
9134 (const_int 0)))]
d5b7b3ae 9135 "TARGET_ARM"
ff9940b0 9136 "*
ff9940b0 9137 {
5895f793
RE
9138 static const char * const opcodes[4][2] =
9139 {
9140 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9141 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9142 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9143 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9144 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9145 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9146 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9147 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9148 };
9149 int swap =
9150 comparison_dominates_p (GET_CODE (operands[5]),
9151 reverse_condition (GET_CODE (operands[4])));
9152
9153 return opcodes[which_alternative][swap];
9154 }"
05ed98a1
RE
9155 [(set_attr "conds" "set")
9156 (set_attr "length" "8")]
9157)
ff9940b0 9158
1646cf41
RE
9159(define_insn "*cmp_and"
9160 [(set (match_operand 6 "dominant_cc_register" "")
9161 (compare
9162 (and:SI
9163 (match_operator 4 "arm_comparison_operator"
9164 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9165 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9166 (match_operator:SI 5 "arm_comparison_operator"
9167 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9168 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9169 (const_int 0)))]
9170 "TARGET_ARM"
9171 "*
9172 {
27c38fbe 9173 static const char *const opcodes[4][2] =
1646cf41
RE
9174 {
9175 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9176 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9177 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9178 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9179 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9180 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9181 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9182 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9183 };
9184 int swap =
9185 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9186
9187 return opcodes[which_alternative][swap];
9188 }"
9189 [(set_attr "conds" "set")
9190 (set_attr "predicable" "no")
9191 (set_attr "length" "8")]
9192)
9193
9194(define_insn "*cmp_ior"
9195 [(set (match_operand 6 "dominant_cc_register" "")
9196 (compare
9197 (ior:SI
9198 (match_operator 4 "arm_comparison_operator"
9199 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9200 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9201 (match_operator:SI 5 "arm_comparison_operator"
9202 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9203 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9204 (const_int 0)))]
9205 "TARGET_ARM"
9206 "*
9207{
27c38fbe 9208 static const char *const opcodes[4][2] =
1646cf41
RE
9209 {
9210 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9211 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9212 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9213 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9214 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9215 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9216 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9217 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9218 };
9219 int swap =
9220 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9221
9222 return opcodes[which_alternative][swap];
9223}
9224"
9225 [(set_attr "conds" "set")
9226 (set_attr "length" "8")]
9227)
9228
03f1640c
RE
9229(define_insn_and_split "*ior_scc_scc"
9230 [(set (match_operand:SI 0 "s_register_operand" "=r")
9231 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9232 [(match_operand:SI 1 "s_register_operand" "r")
9233 (match_operand:SI 2 "arm_add_operand" "rIL")])
9234 (match_operator:SI 6 "arm_comparison_operator"
9235 [(match_operand:SI 4 "s_register_operand" "r")
9236 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9237 (clobber (reg:CC CC_REGNUM))]
9238 "TARGET_ARM
9239 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9240 != CCmode)"
9241 "#"
9242 "TARGET_ARM && reload_completed"
9243 [(set (match_dup 7)
9244 (compare
9245 (ior:SI
9246 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9247 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9248 (const_int 0)))
9249 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9250 "operands[7]
9251 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9252 DOM_CC_X_OR_Y),
9af66e58
RE
9253 CC_REGNUM);"
9254 [(set_attr "conds" "clob")
9255 (set_attr "length" "16")])
9256
9257; If the above pattern is followed by a CMP insn, then the compare is
9258; redundant, since we can rework the conditional instruction that follows.
9259(define_insn_and_split "*ior_scc_scc_cmp"
9260 [(set (match_operand 0 "dominant_cc_register" "")
9261 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9262 [(match_operand:SI 1 "s_register_operand" "r")
9263 (match_operand:SI 2 "arm_add_operand" "rIL")])
9264 (match_operator:SI 6 "arm_comparison_operator"
9265 [(match_operand:SI 4 "s_register_operand" "r")
9266 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9267 (const_int 0)))
9268 (set (match_operand:SI 7 "s_register_operand" "=r")
9269 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9270 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9271 "TARGET_ARM"
9272 "#"
9273 "TARGET_ARM && reload_completed"
9274 [(set (match_dup 0)
9275 (compare
9276 (ior:SI
9277 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9278 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9279 (const_int 0)))
9280 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9281 ""
9282 [(set_attr "conds" "set")
9283 (set_attr "length" "16")])
03f1640c
RE
9284
9285(define_insn_and_split "*and_scc_scc"
9286 [(set (match_operand:SI 0 "s_register_operand" "=r")
9287 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9288 [(match_operand:SI 1 "s_register_operand" "r")
9289 (match_operand:SI 2 "arm_add_operand" "rIL")])
9290 (match_operator:SI 6 "arm_comparison_operator"
9291 [(match_operand:SI 4 "s_register_operand" "r")
9292 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9293 (clobber (reg:CC CC_REGNUM))]
9294 "TARGET_ARM
9295 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9296 != CCmode)"
9297 "#"
9af66e58
RE
9298 "TARGET_ARM && reload_completed
9299 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9300 != CCmode)"
03f1640c
RE
9301 [(set (match_dup 7)
9302 (compare
9303 (and:SI
9304 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9305 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9306 (const_int 0)))
9307 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9308 "operands[7]
9309 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9310 DOM_CC_X_AND_Y),
9af66e58
RE
9311 CC_REGNUM);"
9312 [(set_attr "conds" "clob")
9313 (set_attr "length" "16")])
9314
9315; If the above pattern is followed by a CMP insn, then the compare is
9316; redundant, since we can rework the conditional instruction that follows.
9317(define_insn_and_split "*and_scc_scc_cmp"
9318 [(set (match_operand 0 "dominant_cc_register" "")
9319 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9320 [(match_operand:SI 1 "s_register_operand" "r")
9321 (match_operand:SI 2 "arm_add_operand" "rIL")])
9322 (match_operator:SI 6 "arm_comparison_operator"
9323 [(match_operand:SI 4 "s_register_operand" "r")
9324 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9325 (const_int 0)))
9326 (set (match_operand:SI 7 "s_register_operand" "=r")
9327 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9328 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9329 "TARGET_ARM"
9330 "#"
9331 "TARGET_ARM && reload_completed"
9332 [(set (match_dup 0)
9333 (compare
9334 (and:SI
9335 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9336 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9337 (const_int 0)))
9338 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9339 ""
9340 [(set_attr "conds" "set")
9341 (set_attr "length" "16")])
9342
9343;; If there is no dominance in the comparison, then we can still save an
9344;; instruction in the AND case, since we can know that the second compare
9345;; need only zero the value if false (if true, then the value is already
9346;; correct).
9347(define_insn_and_split "*and_scc_scc_nodom"
9348 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9349 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9350 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9351 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9352 (match_operator:SI 6 "arm_comparison_operator"
9353 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9354 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9355 (clobber (reg:CC CC_REGNUM))]
9356 "TARGET_ARM
9357 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9358 == CCmode)"
9359 "#"
9360 "TARGET_ARM && reload_completed"
9361 [(parallel [(set (match_dup 0)
9362 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9363 (clobber (reg:CC CC_REGNUM))])
9364 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9365 (set (match_dup 0)
9366 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9367 (match_dup 0)
9368 (const_int 0)))]
9369 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9370 operands[4], operands[5]),
9371 CC_REGNUM);
9372 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9373 operands[5]);"
9374 [(set_attr "conds" "clob")
9375 (set_attr "length" "20")])
03f1640c 9376
e25c906a
RE
9377(define_split
9378 [(set (reg:CC_NOOV CC_REGNUM)
9379 (compare:CC_NOOV (ior:SI
9380 (and:SI (match_operand:SI 0 "s_register_operand" "")
9381 (const_int 1))
9382 (match_operator:SI 1 "comparison_operator"
9383 [(match_operand:SI 2 "s_register_operand" "")
9384 (match_operand:SI 3 "arm_add_operand" "")]))
9385 (const_int 0)))
9386 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9387 "TARGET_ARM"
9388 [(set (match_dup 4)
9389 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9390 (match_dup 0)))
9391 (set (reg:CC_NOOV CC_REGNUM)
9392 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9393 (const_int 0)))]
9394 "")
9395
9396(define_split
9397 [(set (reg:CC_NOOV CC_REGNUM)
9398 (compare:CC_NOOV (ior:SI
9399 (match_operator:SI 1 "comparison_operator"
9400 [(match_operand:SI 2 "s_register_operand" "")
9401 (match_operand:SI 3 "arm_add_operand" "")])
9402 (and:SI (match_operand:SI 0 "s_register_operand" "")
9403 (const_int 1)))
9404 (const_int 0)))
9405 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9406 "TARGET_ARM"
9407 [(set (match_dup 4)
9408 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9409 (match_dup 0)))
9410 (set (reg:CC_NOOV CC_REGNUM)
9411 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9412 (const_int 0)))]
9413 "")
5b3e6663 9414;; ??? The conditional patterns above need checking for Thumb-2 usefulness
e25c906a 9415
4cdb3ed4 9416(define_insn "*negscc"
ff9940b0 9417 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 9418 (neg:SI (match_operator 3 "arm_comparison_operator"
ff9940b0
RE
9419 [(match_operand:SI 1 "s_register_operand" "r")
9420 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
48a08b9c 9421 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9422 "TARGET_ARM"
ff9940b0 9423 "*
630ef467 9424 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
0f447ef2
RE
9425 return \"mov\\t%0, %1, asr #31\";
9426
ff9940b0 9427 if (GET_CODE (operands[3]) == NE)
0f447ef2
RE
9428 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9429
0f447ef2
RE
9430 output_asm_insn (\"cmp\\t%1, %2\", operands);
9431 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9432 return \"mvn%d3\\t%0, #0\";
5895f793 9433 "
05ed98a1
RE
9434 [(set_attr "conds" "clob")
9435 (set_attr "length" "12")]
9436)
ff9940b0
RE
9437
9438(define_insn "movcond"
9439 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
68df59d3 9440 (if_then_else:SI
05ed98a1 9441 (match_operator 5 "arm_comparison_operator"
68df59d3
RE
9442 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9443 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9444 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9445 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
48a08b9c 9446 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9447 "TARGET_ARM"
ff9940b0
RE
9448 "*
9449 if (GET_CODE (operands[5]) == LT
9450 && (operands[4] == const0_rtx))
9451 {
68df59d3 9452 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
ff9940b0 9453 {
ff9940b0 9454 if (operands[2] == const0_rtx)
0f447ef2
RE
9455 return \"and\\t%0, %1, %3, asr #31\";
9456 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
ff9940b0
RE
9457 }
9458 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9459 {
ff9940b0 9460 if (operands[1] == const0_rtx)
0f447ef2
RE
9461 return \"bic\\t%0, %2, %3, asr #31\";
9462 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
ff9940b0
RE
9463 }
9464 /* The only case that falls through to here is when both ops 1 & 2
d6b4baa4 9465 are constants. */
ff9940b0 9466 }
0f447ef2 9467
ff9940b0
RE
9468 if (GET_CODE (operands[5]) == GE
9469 && (operands[4] == const0_rtx))
9470 {
9471 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9472 {
ff9940b0 9473 if (operands[2] == const0_rtx)
0f447ef2
RE
9474 return \"bic\\t%0, %1, %3, asr #31\";
9475 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
ff9940b0
RE
9476 }
9477 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9478 {
ff9940b0 9479 if (operands[1] == const0_rtx)
0f447ef2
RE
9480 return \"and\\t%0, %2, %3, asr #31\";
9481 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
ff9940b0
RE
9482 }
9483 /* The only case that falls through to here is when both ops 1 & 2
d6b4baa4 9484 are constants. */
ff9940b0
RE
9485 }
9486 if (GET_CODE (operands[4]) == CONST_INT
9487 && !const_ok_for_arm (INTVAL (operands[4])))
0f447ef2 9488 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
ff9940b0 9489 else
0f447ef2 9490 output_asm_insn (\"cmp\\t%3, %4\", operands);
ff9940b0 9491 if (which_alternative != 0)
0f447ef2 9492 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
ff9940b0 9493 if (which_alternative != 1)
0f447ef2 9494 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
ff9940b0 9495 return \"\";
5895f793 9496 "
05ed98a1
RE
9497 [(set_attr "conds" "clob")
9498 (set_attr "length" "8,8,12")]
9499)
ff9940b0 9500
5b3e6663
PB
9501;; ??? The patterns below need checking for Thumb-2 usefulness.
9502
f54fd62e
RE
9503(define_insn "*ifcompare_plus_move"
9504 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 9505 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9506 [(match_operand:SI 4 "s_register_operand" "r,r")
9507 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9508 (plus:SI
9509 (match_operand:SI 2 "s_register_operand" "r,r")
9510 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
b36ba79f 9511 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
48a08b9c 9512 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9513 "TARGET_ARM"
f54fd62e 9514 "#"
05ed98a1
RE
9515 [(set_attr "conds" "clob")
9516 (set_attr "length" "8,12")]
9517)
f54fd62e
RE
9518
9519(define_insn "*if_plus_move"
b36ba79f 9520 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
f54fd62e 9521 (if_then_else:SI
05ed98a1 9522 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
9523 [(match_operand 5 "cc_register" "") (const_int 0)])
9524 (plus:SI
b36ba79f
RE
9525 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9526 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9527 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
d5b7b3ae 9528 "TARGET_ARM"
f54fd62e
RE
9529 "@
9530 add%d4\\t%0, %2, %3
9531 sub%d4\\t%0, %2, #%n3
9532 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
b36ba79f 9533 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
05ed98a1
RE
9534 [(set_attr "conds" "use")
9535 (set_attr "length" "4,4,8,8")
9536 (set_attr "type" "*,*,*,*")]
9537)
f54fd62e
RE
9538
9539(define_insn "*ifcompare_move_plus"
68df59d3 9540 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 9541 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9542 [(match_operand:SI 4 "s_register_operand" "r,r")
9543 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
b36ba79f 9544 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
f54fd62e
RE
9545 (plus:SI
9546 (match_operand:SI 2 "s_register_operand" "r,r")
9547 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
48a08b9c 9548 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9549 "TARGET_ARM"
f54fd62e 9550 "#"
05ed98a1
RE
9551 [(set_attr "conds" "clob")
9552 (set_attr "length" "8,12")]
9553)
f54fd62e
RE
9554
9555(define_insn "*if_move_plus"
b36ba79f 9556 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
f54fd62e 9557 (if_then_else:SI
05ed98a1 9558 (match_operator 4 "arm_comparison_operator"
f54fd62e 9559 [(match_operand 5 "cc_register" "") (const_int 0)])
b36ba79f 9560 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
f54fd62e 9561 (plus:SI
b36ba79f
RE
9562 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9563 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
d5b7b3ae 9564 "TARGET_ARM"
f54fd62e
RE
9565 "@
9566 add%D4\\t%0, %2, %3
9567 sub%D4\\t%0, %2, #%n3
9568 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
b36ba79f 9569 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
05ed98a1
RE
9570 [(set_attr "conds" "use")
9571 (set_attr "length" "4,4,8,8")
9572 (set_attr "type" "*,*,*,*")]
9573)
f54fd62e
RE
9574
9575(define_insn "*ifcompare_arith_arith"
9576 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 9577 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
f54fd62e
RE
9578 [(match_operand:SI 5 "s_register_operand" "r")
9579 (match_operand:SI 6 "arm_add_operand" "rIL")])
ff9940b0 9580 (match_operator:SI 8 "shiftable_operator"
f54fd62e
RE
9581 [(match_operand:SI 1 "s_register_operand" "r")
9582 (match_operand:SI 2 "arm_rhs_operand" "rI")])
ff9940b0 9583 (match_operator:SI 7 "shiftable_operator"
f54fd62e
RE
9584 [(match_operand:SI 3 "s_register_operand" "r")
9585 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
48a08b9c 9586 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9587 "TARGET_ARM"
f54fd62e 9588 "#"
05ed98a1
RE
9589 [(set_attr "conds" "clob")
9590 (set_attr "length" "12")]
9591)
ff9940b0 9592
f54fd62e
RE
9593(define_insn "*if_arith_arith"
9594 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 9595 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9596 [(match_operand 8 "cc_register" "") (const_int 0)])
9597 (match_operator:SI 6 "shiftable_operator"
9598 [(match_operand:SI 1 "s_register_operand" "r")
9599 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9600 (match_operator:SI 7 "shiftable_operator"
9601 [(match_operand:SI 3 "s_register_operand" "r")
9602 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
d5b7b3ae 9603 "TARGET_ARM"
f54fd62e 9604 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
05ed98a1
RE
9605 [(set_attr "conds" "use")
9606 (set_attr "length" "8")]
9607)
f54fd62e 9608
4cdb3ed4 9609(define_insn "*ifcompare_arith_move"
ff9940b0 9610 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 9611 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
ff9940b0 9612 [(match_operand:SI 2 "s_register_operand" "r,r")
68df59d3 9613 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
ff9940b0
RE
9614 (match_operator:SI 7 "shiftable_operator"
9615 [(match_operand:SI 4 "s_register_operand" "r,r")
9616 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
b36ba79f 9617 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
48a08b9c 9618 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9619 "TARGET_ARM"
ff9940b0 9620 "*
ff9940b0 9621 /* If we have an operation where (op x 0) is the identity operation and
ddd5a7c1 9622 the conditional operator is LT or GE and we are comparing against zero and
d6b4baa4 9623 everything is in registers then we can do this in two instructions. */
ff9940b0
RE
9624 if (operands[3] == const0_rtx
9625 && GET_CODE (operands[7]) != AND
9626 && GET_CODE (operands[5]) == REG
9627 && GET_CODE (operands[1]) == REG
9628 && REGNO (operands[1]) == REGNO (operands[4])
9629 && REGNO (operands[4]) != REGNO (operands[0]))
9630 {
9631 if (GET_CODE (operands[6]) == LT)
c63165be 9632 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
ff9940b0 9633 else if (GET_CODE (operands[6]) == GE)
c63165be 9634 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
ff9940b0
RE
9635 }
9636 if (GET_CODE (operands[3]) == CONST_INT
9637 && !const_ok_for_arm (INTVAL (operands[3])))
0f447ef2 9638 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
ff9940b0 9639 else
0f447ef2 9640 output_asm_insn (\"cmp\\t%2, %3\", operands);
c63165be 9641 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
ff9940b0 9642 if (which_alternative != 0)
b36ba79f 9643 return \"mov%D6\\t%0, %1\";
ff9940b0 9644 return \"\";
5895f793 9645 "
05ed98a1
RE
9646 [(set_attr "conds" "clob")
9647 (set_attr "length" "8,12")]
9648)
ff9940b0 9649
f54fd62e 9650(define_insn "*if_arith_move"
b36ba79f 9651 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 9652 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
9653 [(match_operand 6 "cc_register" "") (const_int 0)])
9654 (match_operator:SI 5 "shiftable_operator"
b36ba79f
RE
9655 [(match_operand:SI 2 "s_register_operand" "r,r")
9656 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9657 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
d5b7b3ae 9658 "TARGET_ARM"
f54fd62e
RE
9659 "@
9660 %I5%d4\\t%0, %2, %3
b36ba79f 9661 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
05ed98a1
RE
9662 [(set_attr "conds" "use")
9663 (set_attr "length" "4,8")
9664 (set_attr "type" "*,*")]
9665)
f54fd62e 9666
4cdb3ed4 9667(define_insn "*ifcompare_move_arith"
ff9940b0 9668 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 9669 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
ff9940b0 9670 [(match_operand:SI 4 "s_register_operand" "r,r")
68df59d3 9671 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
b36ba79f 9672 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
ff9940b0
RE
9673 (match_operator:SI 7 "shiftable_operator"
9674 [(match_operand:SI 2 "s_register_operand" "r,r")
9675 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
48a08b9c 9676 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9677 "TARGET_ARM"
ff9940b0 9678 "*
ff9940b0 9679 /* If we have an operation where (op x 0) is the identity operation and
ddd5a7c1 9680 the conditional operator is LT or GE and we are comparing against zero and
ff9940b0
RE
9681 everything is in registers then we can do this in two instructions */
9682 if (operands[5] == const0_rtx
9683 && GET_CODE (operands[7]) != AND
9684 && GET_CODE (operands[3]) == REG
9685 && GET_CODE (operands[1]) == REG
9686 && REGNO (operands[1]) == REGNO (operands[2])
9687 && REGNO (operands[2]) != REGNO (operands[0]))
9688 {
9689 if (GET_CODE (operands[6]) == GE)
c63165be 9690 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
ff9940b0 9691 else if (GET_CODE (operands[6]) == LT)
c63165be 9692 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
ff9940b0 9693 }
c63165be 9694
ff9940b0
RE
9695 if (GET_CODE (operands[5]) == CONST_INT
9696 && !const_ok_for_arm (INTVAL (operands[5])))
0f447ef2 9697 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
ff9940b0 9698 else
0f447ef2 9699 output_asm_insn (\"cmp\\t%4, %5\", operands);
c63165be 9700
ff9940b0 9701 if (which_alternative != 0)
b36ba79f 9702 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
c63165be 9703 return \"%I7%D6\\t%0, %2, %3\";
5895f793 9704 "
05ed98a1
RE
9705 [(set_attr "conds" "clob")
9706 (set_attr "length" "8,12")]
9707)
ff9940b0 9708
f54fd62e 9709(define_insn "*if_move_arith"
b36ba79f 9710 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 9711 (if_then_else:SI
05ed98a1 9712 (match_operator 4 "arm_comparison_operator"
f54fd62e 9713 [(match_operand 6 "cc_register" "") (const_int 0)])
b36ba79f 9714 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
f54fd62e 9715 (match_operator:SI 5 "shiftable_operator"
b36ba79f
RE
9716 [(match_operand:SI 2 "s_register_operand" "r,r")
9717 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
d5b7b3ae 9718 "TARGET_ARM"
f54fd62e
RE
9719 "@
9720 %I5%D4\\t%0, %2, %3
b36ba79f 9721 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
05ed98a1
RE
9722 [(set_attr "conds" "use")
9723 (set_attr "length" "4,8")
9724 (set_attr "type" "*,*")]
9725)
f54fd62e
RE
9726
9727(define_insn "*ifcompare_move_not"
ff9940b0 9728 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 9729 (if_then_else:SI
05ed98a1 9730 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9731 [(match_operand:SI 3 "s_register_operand" "r,r")
9732 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9733 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9734 (not:SI
9735 (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 9736 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9737 "TARGET_ARM"
f54fd62e 9738 "#"
05ed98a1
RE
9739 [(set_attr "conds" "clob")
9740 (set_attr "length" "8,12")]
9741)
ff9940b0 9742
f54fd62e
RE
9743(define_insn "*if_move_not"
9744 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9745 (if_then_else:SI
05ed98a1 9746 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
9747 [(match_operand 3 "cc_register" "") (const_int 0)])
9748 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9749 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
d5b7b3ae 9750 "TARGET_ARM"
f54fd62e
RE
9751 "@
9752 mvn%D4\\t%0, %2
9753 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9754 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
05ed98a1
RE
9755 [(set_attr "conds" "use")
9756 (set_attr "length" "4,8,8")]
9757)
f54fd62e
RE
9758
9759(define_insn "*ifcompare_not_move"
ff9940b0 9760 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 9761 (if_then_else:SI
05ed98a1 9762 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9763 [(match_operand:SI 3 "s_register_operand" "r,r")
9764 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9765 (not:SI
9766 (match_operand:SI 2 "s_register_operand" "r,r"))
9767 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
48a08b9c 9768 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9769 "TARGET_ARM"
f54fd62e 9770 "#"
05ed98a1
RE
9771 [(set_attr "conds" "clob")
9772 (set_attr "length" "8,12")]
9773)
ff9940b0 9774
f54fd62e
RE
9775(define_insn "*if_not_move"
9776 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9777 (if_then_else:SI
05ed98a1 9778 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
9779 [(match_operand 3 "cc_register" "") (const_int 0)])
9780 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9781 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
d5b7b3ae 9782 "TARGET_ARM"
f54fd62e
RE
9783 "@
9784 mvn%d4\\t%0, %2
9785 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9786 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
05ed98a1
RE
9787 [(set_attr "conds" "use")
9788 (set_attr "length" "4,8,8")]
9789)
f54fd62e
RE
9790
9791(define_insn "*ifcompare_shift_move"
ff9940b0 9792 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 9793 (if_then_else:SI
05ed98a1 9794 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9795 [(match_operand:SI 4 "s_register_operand" "r,r")
9796 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9797 (match_operator:SI 7 "shift_operator"
9798 [(match_operand:SI 2 "s_register_operand" "r,r")
9799 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9800 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
48a08b9c 9801 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9802 "TARGET_ARM"
ff9940b0 9803 "#"
05ed98a1
RE
9804 [(set_attr "conds" "clob")
9805 (set_attr "length" "8,12")]
9806)
ff9940b0 9807
f54fd62e
RE
9808(define_insn "*if_shift_move"
9809 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9810 (if_then_else:SI
05ed98a1 9811 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9812 [(match_operand 6 "cc_register" "") (const_int 0)])
9813 (match_operator:SI 4 "shift_operator"
9814 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9815 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9816 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
d5b7b3ae 9817 "TARGET_ARM"
68df59d3 9818 "@
f54fd62e
RE
9819 mov%d5\\t%0, %2%S4
9820 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9821 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
05ed98a1 9822 [(set_attr "conds" "use")
d19fb8e3 9823 (set_attr "shift" "2")
9b66ebb1
PB
9824 (set_attr "length" "4,8,8")
9825 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9826 (const_string "alu_shift")
9827 (const_string "alu_shift_reg")))]
05ed98a1 9828)
68df59d3 9829
f54fd62e
RE
9830(define_insn "*ifcompare_move_shift"
9831 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
68df59d3 9832 (if_then_else:SI
05ed98a1 9833 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9834 [(match_operand:SI 4 "s_register_operand" "r,r")
9835 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9836 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
68df59d3 9837 (match_operator:SI 7 "shift_operator"
f54fd62e
RE
9838 [(match_operand:SI 2 "s_register_operand" "r,r")
9839 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
48a08b9c 9840 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9841 "TARGET_ARM"
f54fd62e 9842 "#"
05ed98a1
RE
9843 [(set_attr "conds" "clob")
9844 (set_attr "length" "8,12")]
9845)
68df59d3 9846
f54fd62e
RE
9847(define_insn "*if_move_shift"
9848 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
68df59d3 9849 (if_then_else:SI
05ed98a1 9850 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9851 [(match_operand 6 "cc_register" "") (const_int 0)])
9852 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9853 (match_operator:SI 4 "shift_operator"
9854 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9855 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
d5b7b3ae 9856 "TARGET_ARM"
68df59d3 9857 "@
f54fd62e
RE
9858 mov%D5\\t%0, %2%S4
9859 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9860 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
05ed98a1 9861 [(set_attr "conds" "use")
d19fb8e3 9862 (set_attr "shift" "2")
9b66ebb1
PB
9863 (set_attr "length" "4,8,8")
9864 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9865 (const_string "alu_shift")
9866 (const_string "alu_shift_reg")))]
05ed98a1 9867)
ff9940b0 9868
4cdb3ed4 9869(define_insn "*ifcompare_shift_shift"
f54fd62e 9870 [(set (match_operand:SI 0 "s_register_operand" "=r")
68df59d3 9871 (if_then_else:SI
05ed98a1 9872 (match_operator 7 "arm_comparison_operator"
f54fd62e
RE
9873 [(match_operand:SI 5 "s_register_operand" "r")
9874 (match_operand:SI 6 "arm_add_operand" "rIL")])
68df59d3 9875 (match_operator:SI 8 "shift_operator"
f54fd62e
RE
9876 [(match_operand:SI 1 "s_register_operand" "r")
9877 (match_operand:SI 2 "arm_rhs_operand" "rM")])
68df59d3 9878 (match_operator:SI 9 "shift_operator"
f54fd62e
RE
9879 [(match_operand:SI 3 "s_register_operand" "r")
9880 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
48a08b9c 9881 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9882 "TARGET_ARM"
f54fd62e 9883 "#"
05ed98a1
RE
9884 [(set_attr "conds" "clob")
9885 (set_attr "length" "12")]
9886)
ff9940b0 9887
f54fd62e
RE
9888(define_insn "*if_shift_shift"
9889 [(set (match_operand:SI 0 "s_register_operand" "=r")
9890 (if_then_else:SI
05ed98a1 9891 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9892 [(match_operand 8 "cc_register" "") (const_int 0)])
9893 (match_operator:SI 6 "shift_operator"
9894 [(match_operand:SI 1 "s_register_operand" "r")
9895 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9896 (match_operator:SI 7 "shift_operator"
9897 [(match_operand:SI 3 "s_register_operand" "r")
9898 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
d5b7b3ae 9899 "TARGET_ARM"
f54fd62e 9900 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
05ed98a1 9901 [(set_attr "conds" "use")
d19fb8e3 9902 (set_attr "shift" "1")
9b66ebb1
PB
9903 (set_attr "length" "8")
9904 (set (attr "type") (if_then_else
9905 (and (match_operand 2 "const_int_operand" "")
9906 (match_operand 4 "const_int_operand" ""))
9907 (const_string "alu_shift")
9908 (const_string "alu_shift_reg")))]
05ed98a1 9909)
f54fd62e 9910
4cdb3ed4 9911(define_insn "*ifcompare_not_arith"
f54fd62e 9912 [(set (match_operand:SI 0 "s_register_operand" "=r")
68df59d3 9913 (if_then_else:SI
05ed98a1 9914 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9915 [(match_operand:SI 4 "s_register_operand" "r")
9916 (match_operand:SI 5 "arm_add_operand" "rIL")])
9917 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
68df59d3 9918 (match_operator:SI 7 "shiftable_operator"
f54fd62e
RE
9919 [(match_operand:SI 2 "s_register_operand" "r")
9920 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
48a08b9c 9921 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9922 "TARGET_ARM"
f54fd62e 9923 "#"
05ed98a1
RE
9924 [(set_attr "conds" "clob")
9925 (set_attr "length" "12")]
9926)
ff9940b0 9927
f54fd62e
RE
9928(define_insn "*if_not_arith"
9929 [(set (match_operand:SI 0 "s_register_operand" "=r")
9930 (if_then_else:SI
05ed98a1 9931 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9932 [(match_operand 4 "cc_register" "") (const_int 0)])
9933 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9934 (match_operator:SI 6 "shiftable_operator"
9935 [(match_operand:SI 2 "s_register_operand" "r")
9936 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
d5b7b3ae 9937 "TARGET_ARM"
f54fd62e 9938 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
05ed98a1
RE
9939 [(set_attr "conds" "use")
9940 (set_attr "length" "8")]
9941)
f54fd62e
RE
9942
9943(define_insn "*ifcompare_arith_not"
9944 [(set (match_operand:SI 0 "s_register_operand" "=r")
68df59d3 9945 (if_then_else:SI
05ed98a1 9946 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9947 [(match_operand:SI 4 "s_register_operand" "r")
9948 (match_operand:SI 5 "arm_add_operand" "rIL")])
68df59d3 9949 (match_operator:SI 7 "shiftable_operator"
f54fd62e
RE
9950 [(match_operand:SI 2 "s_register_operand" "r")
9951 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9952 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
48a08b9c 9953 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9954 "TARGET_ARM"
f54fd62e 9955 "#"
05ed98a1
RE
9956 [(set_attr "conds" "clob")
9957 (set_attr "length" "12")]
9958)
ff9940b0 9959
f54fd62e
RE
9960(define_insn "*if_arith_not"
9961 [(set (match_operand:SI 0 "s_register_operand" "=r")
9962 (if_then_else:SI
05ed98a1 9963 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9964 [(match_operand 4 "cc_register" "") (const_int 0)])
9965 (match_operator:SI 6 "shiftable_operator"
9966 [(match_operand:SI 2 "s_register_operand" "r")
9967 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9968 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
d5b7b3ae 9969 "TARGET_ARM"
f54fd62e 9970 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
05ed98a1
RE
9971 [(set_attr "conds" "use")
9972 (set_attr "length" "8")]
9973)
f54fd62e 9974
4cdb3ed4 9975(define_insn "*ifcompare_neg_move"
f54fd62e 9976 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
68df59d3 9977 (if_then_else:SI
05ed98a1 9978 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9979 [(match_operand:SI 3 "s_register_operand" "r,r")
9980 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9981 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9982 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
48a08b9c 9983 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9984 "TARGET_ARM"
f54fd62e 9985 "#"
05ed98a1
RE
9986 [(set_attr "conds" "clob")
9987 (set_attr "length" "8,12")]
9988)
f54fd62e
RE
9989
9990(define_insn "*if_neg_move"
9991 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9992 (if_then_else:SI
05ed98a1 9993 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
9994 [(match_operand 3 "cc_register" "") (const_int 0)])
9995 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9996 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
d5b7b3ae 9997 "TARGET_ARM"
f54fd62e
RE
9998 "@
9999 rsb%d4\\t%0, %2, #0
10000 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10001 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
05ed98a1
RE
10002 [(set_attr "conds" "use")
10003 (set_attr "length" "4,8,8")]
10004)
ff9940b0 10005
4cdb3ed4 10006(define_insn "*ifcompare_move_neg"
f54fd62e 10007 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
68df59d3 10008 (if_then_else:SI
05ed98a1 10009 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
10010 [(match_operand:SI 3 "s_register_operand" "r,r")
10011 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10012 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10013 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 10014 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 10015 "TARGET_ARM"
f54fd62e 10016 "#"
05ed98a1
RE
10017 [(set_attr "conds" "clob")
10018 (set_attr "length" "8,12")]
10019)
f54fd62e
RE
10020
10021(define_insn "*if_move_neg"
10022 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10023 (if_then_else:SI
05ed98a1 10024 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
10025 [(match_operand 3 "cc_register" "") (const_int 0)])
10026 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10027 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
d5b7b3ae 10028 "TARGET_ARM"
f54fd62e
RE
10029 "@
10030 rsb%D4\\t%0, %2, #0
10031 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10032 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
cca0a211
RE
10033 [(set_attr "conds" "use")
10034 (set_attr "length" "4,8,8")]
10035)
ff9940b0 10036
4cdb3ed4 10037(define_insn "*arith_adjacentmem"
ff9940b0
RE
10038 [(set (match_operand:SI 0 "s_register_operand" "=r")
10039 (match_operator:SI 1 "shiftable_operator"
10040 [(match_operand:SI 2 "memory_operand" "m")
10041 (match_operand:SI 3 "memory_operand" "m")]))
10042 (clobber (match_scratch:SI 4 "=r"))]
d5b7b3ae 10043 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
ff9940b0 10044 "*
5895f793
RE
10045 {
10046 rtx ldm[3];
10047 rtx arith[4];
15b5c4c1
RE
10048 rtx base_reg;
10049 HOST_WIDE_INT val1 = 0, val2 = 0;
ff9940b0 10050
5895f793
RE
10051 if (REGNO (operands[0]) > REGNO (operands[4]))
10052 {
10053 ldm[1] = operands[4];
10054 ldm[2] = operands[0];
10055 }
10056 else
10057 {
10058 ldm[1] = operands[0];
10059 ldm[2] = operands[4];
10060 }
15b5c4c1
RE
10061
10062 base_reg = XEXP (operands[2], 0);
10063
10064 if (!REG_P (base_reg))
10065 {
10066 val1 = INTVAL (XEXP (base_reg, 1));
10067 base_reg = XEXP (base_reg, 0);
10068 }
10069
10070 if (!REG_P (XEXP (operands[3], 0)))
5895f793 10071 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
15b5c4c1 10072
5895f793
RE
10073 arith[0] = operands[0];
10074 arith[3] = operands[1];
15b5c4c1 10075
5895f793
RE
10076 if (val1 < val2)
10077 {
10078 arith[1] = ldm[1];
10079 arith[2] = ldm[2];
10080 }
10081 else
10082 {
10083 arith[1] = ldm[2];
10084 arith[2] = ldm[1];
10085 }
15b5c4c1
RE
10086
10087 ldm[0] = base_reg;
10088 if (val1 !=0 && val2 != 0)
5895f793 10089 {
bcf640f7
PB
10090 rtx ops[3];
10091
15b5c4c1
RE
10092 if (val1 == 4 || val2 == 4)
10093 /* Other val must be 8, since we know they are adjacent and neither
10094 is zero. */
5b3e6663 10095 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
bcf640f7 10096 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
15b5c4c1 10097 {
15b5c4c1
RE
10098 ldm[0] = ops[0] = operands[4];
10099 ops[1] = base_reg;
10100 ops[2] = GEN_INT (val1);
10101 output_add_immediate (ops);
10102 if (val1 < val2)
5b3e6663 10103 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
15b5c4c1 10104 else
5b3e6663 10105 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
15b5c4c1 10106 }
bcf640f7
PB
10107 else
10108 {
10109 /* Offset is out of range for a single add, so use two ldr. */
10110 ops[0] = ldm[1];
10111 ops[1] = base_reg;
10112 ops[2] = GEN_INT (val1);
10113 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10114 ops[0] = ldm[2];
10115 ops[2] = GEN_INT (val2);
10116 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10117 }
5895f793 10118 }
15b5c4c1 10119 else if (val1 != 0)
5895f793 10120 {
5895f793 10121 if (val1 < val2)
5b3e6663 10122 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
5895f793 10123 else
5b3e6663 10124 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
5895f793
RE
10125 }
10126 else
10127 {
5895f793 10128 if (val1 < val2)
5b3e6663 10129 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
5895f793 10130 else
5b3e6663 10131 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
5895f793
RE
10132 }
10133 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10134 return \"\";
10135 }"
10136 [(set_attr "length" "12")
10137 (set_attr "predicable" "yes")
9b66ebb1 10138 (set_attr "type" "load1")]
5895f793 10139)
ff9940b0 10140
ff9940b0
RE
10141; This pattern is never tried by combine, so do it as a peephole
10142
bb6ae783 10143(define_peephole2
3053b100
RE
10144 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10145 (match_operand:SI 1 "arm_general_register_operand" ""))
48a08b9c 10146 (set (reg:CC CC_REGNUM)
589fe0fc 10147 (compare:CC (match_dup 1) (const_int 0)))]
3053b100 10148 "TARGET_ARM"
bb6ae783
RE
10149 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10150 (set (match_dup 0) (match_dup 1))])]
10151 ""
cca0a211 10152)
ff9940b0 10153
25b1c156
NC
10154; Peepholes to spot possible load- and store-multiples, if the ordering is
10155; reversed, check that the memory references aren't volatile.
ff9940b0
RE
10156
10157(define_peephole
f5c630c3 10158 [(set (match_operand:SI 0 "s_register_operand" "=rk")
589fe0fc 10159 (match_operand:SI 4 "memory_operand" "m"))
f5c630c3 10160 (set (match_operand:SI 1 "s_register_operand" "=rk")
589fe0fc 10161 (match_operand:SI 5 "memory_operand" "m"))
f5c630c3 10162 (set (match_operand:SI 2 "s_register_operand" "=rk")
589fe0fc 10163 (match_operand:SI 6 "memory_operand" "m"))
f5c630c3 10164 (set (match_operand:SI 3 "s_register_operand" "=rk")
589fe0fc 10165 (match_operand:SI 7 "memory_operand" "m"))]
d5b7b3ae 10166 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
589fe0fc
RE
10167 "*
10168 return emit_ldm_seq (operands, 4);
5895f793
RE
10169 "
10170)
ff9940b0
RE
10171
10172(define_peephole
f5c630c3 10173 [(set (match_operand:SI 0 "s_register_operand" "=rk")
589fe0fc 10174 (match_operand:SI 3 "memory_operand" "m"))
f5c630c3 10175 (set (match_operand:SI 1 "s_register_operand" "=rk")
589fe0fc 10176 (match_operand:SI 4 "memory_operand" "m"))
f5c630c3 10177 (set (match_operand:SI 2 "s_register_operand" "=rk")
589fe0fc 10178 (match_operand:SI 5 "memory_operand" "m"))]
d5b7b3ae 10179 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
589fe0fc
RE
10180 "*
10181 return emit_ldm_seq (operands, 3);
5895f793
RE
10182 "
10183)
ff9940b0
RE
10184
10185(define_peephole
f5c630c3 10186 [(set (match_operand:SI 0 "s_register_operand" "=rk")
589fe0fc 10187 (match_operand:SI 2 "memory_operand" "m"))
f5c630c3 10188 (set (match_operand:SI 1 "s_register_operand" "=rk")
589fe0fc 10189 (match_operand:SI 3 "memory_operand" "m"))]
d5b7b3ae 10190 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
589fe0fc
RE
10191 "*
10192 return emit_ldm_seq (operands, 2);
5895f793
RE
10193 "
10194)
ff9940b0
RE
10195
10196(define_peephole
589fe0fc 10197 [(set (match_operand:SI 4 "memory_operand" "=m")
f5c630c3 10198 (match_operand:SI 0 "s_register_operand" "rk"))
589fe0fc 10199 (set (match_operand:SI 5 "memory_operand" "=m")
f5c630c3 10200 (match_operand:SI 1 "s_register_operand" "rk"))
589fe0fc 10201 (set (match_operand:SI 6 "memory_operand" "=m")
f5c630c3 10202 (match_operand:SI 2 "s_register_operand" "rk"))
589fe0fc 10203 (set (match_operand:SI 7 "memory_operand" "=m")
f5c630c3 10204 (match_operand:SI 3 "s_register_operand" "rk"))]
d5b7b3ae 10205 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
589fe0fc
RE
10206 "*
10207 return emit_stm_seq (operands, 4);
5895f793
RE
10208 "
10209)
ff9940b0
RE
10210
10211(define_peephole
589fe0fc 10212 [(set (match_operand:SI 3 "memory_operand" "=m")
f5c630c3 10213 (match_operand:SI 0 "s_register_operand" "rk"))
589fe0fc 10214 (set (match_operand:SI 4 "memory_operand" "=m")
f5c630c3 10215 (match_operand:SI 1 "s_register_operand" "rk"))
589fe0fc 10216 (set (match_operand:SI 5 "memory_operand" "=m")
f5c630c3 10217 (match_operand:SI 2 "s_register_operand" "rk"))]
d5b7b3ae 10218 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
589fe0fc
RE
10219 "*
10220 return emit_stm_seq (operands, 3);
5895f793
RE
10221 "
10222)
ff9940b0
RE
10223
10224(define_peephole
589fe0fc 10225 [(set (match_operand:SI 2 "memory_operand" "=m")
f5c630c3 10226 (match_operand:SI 0 "s_register_operand" "rk"))
589fe0fc 10227 (set (match_operand:SI 3 "memory_operand" "=m")
f5c630c3 10228 (match_operand:SI 1 "s_register_operand" "rk"))]
d5b7b3ae 10229 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
589fe0fc
RE
10230 "*
10231 return emit_stm_seq (operands, 2);
5895f793
RE
10232 "
10233)
ff9940b0 10234
ff9940b0
RE
10235(define_split
10236 [(set (match_operand:SI 0 "s_register_operand" "")
10237 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10238 (const_int 0))
05ed98a1 10239 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
ff9940b0
RE
10240 [(match_operand:SI 3 "s_register_operand" "")
10241 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10242 (clobber (match_operand:SI 5 "s_register_operand" ""))]
d5b7b3ae 10243 "TARGET_ARM"
ff9940b0
RE
10244 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10245 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10246 (match_dup 5)))]
5895f793
RE
10247 ""
10248)
ff9940b0 10249
589fe0fc
RE
10250;; This split can be used because CC_Z mode implies that the following
10251;; branch will be an equality, or an unsigned inequality, so the sign
10252;; extension is not needed.
ff9940b0 10253
589fe0fc 10254(define_split
48a08b9c 10255 [(set (reg:CC_Z CC_REGNUM)
589fe0fc
RE
10256 (compare:CC_Z
10257 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
ff9940b0 10258 (const_int 24))
589fe0fc
RE
10259 (match_operand 1 "const_int_operand" "")))
10260 (clobber (match_scratch:SI 2 ""))]
d5b7b3ae
RE
10261 "TARGET_ARM
10262 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10263 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
589fe0fc 10264 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
48a08b9c 10265 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
589fe0fc 10266 "
ff9940b0 10267 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
5895f793
RE
10268 "
10269)
5b3e6663 10270;; ??? Check the patterns above for Thumb-2 usefulness
ff9940b0 10271
091426d3
RE
10272(define_expand "prologue"
10273 [(clobber (const_int 0))]
d5b7b3ae 10274 "TARGET_EITHER"
5b3e6663 10275 "if (TARGET_32BIT)
d5b7b3ae
RE
10276 arm_expand_prologue ();
10277 else
5b3e6663 10278 thumb1_expand_prologue ();
091426d3 10279 DONE;
d5b7b3ae
RE
10280 "
10281)
091426d3 10282
949d79eb 10283(define_expand "epilogue"
c9ca9b88 10284 [(clobber (const_int 0))]
d5b7b3ae 10285 "TARGET_EITHER"
949d79eb 10286 "
e3b5732b 10287 if (crtl->calls_eh_return)
c9ca9b88 10288 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
5b3e6663
PB
10289 if (TARGET_THUMB1)
10290 thumb1_expand_epilogue ();
d5b7b3ae 10291 else if (USE_RETURN_INSN (FALSE))
949d79eb
RE
10292 {
10293 emit_jump_insn (gen_return ());
10294 DONE;
10295 }
d5b7b3ae
RE
10296 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10297 gen_rtvec (1,
10298 gen_rtx_RETURN (VOIDmode)),
b15bca31 10299 VUNSPEC_EPILOGUE));
d5b7b3ae
RE
10300 DONE;
10301 "
10302)
949d79eb 10303
e3289412
NC
10304;; Note - although unspec_volatile's USE all hard registers,
10305;; USEs are ignored after relaod has completed. Thus we need
10306;; to add an unspec of the link register to ensure that flow
10307;; does not think that it is unused by the sibcall branch that
10308;; will replace the standard function epilogue.
0616531f 10309(define_insn "sibcall_epilogue"
e3289412
NC
10310 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10311 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
5b3e6663 10312 "TARGET_32BIT"
0616531f 10313 "*
a72d4945 10314 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
64e92a26 10315 return output_return_instruction (const_true_rtx, FALSE, FALSE);
a72d4945 10316 return arm_output_epilogue (next_nonnote_insn (insn));
0616531f
RE
10317 "
10318;; Length is absolute worst case
10319 [(set_attr "length" "44")
0732a089
RE
10320 (set_attr "type" "block")
10321 ;; We don't clobber the conditions, but the potential length of this
10322 ;; operation is sufficient to make conditionalizing the sequence
10323 ;; unlikely to be profitable.
10324 (set_attr "conds" "clob")]
0616531f
RE
10325)
10326
d5b7b3ae 10327(define_insn "*epilogue_insns"
b15bca31 10328 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
d5b7b3ae 10329 "TARGET_EITHER"
949d79eb 10330 "*
5b3e6663 10331 if (TARGET_32BIT)
a72d4945 10332 return arm_output_epilogue (NULL);
5b3e6663 10333 else /* TARGET_THUMB1 */
d5b7b3ae
RE
10334 return thumb_unexpanded_epilogue ();
10335 "
5895f793 10336 ; Length is absolute worst case
d5b7b3ae 10337 [(set_attr "length" "44")
0732a089
RE
10338 (set_attr "type" "block")
10339 ;; We don't clobber the conditions, but the potential length of this
10340 ;; operation is sufficient to make conditionalizing the sequence
10341 ;; unlikely to be profitable.
10342 (set_attr "conds" "clob")]
d5b7b3ae
RE
10343)
10344
10345(define_expand "eh_epilogue"
82955615
RE
10346 [(use (match_operand:SI 0 "register_operand" ""))
10347 (use (match_operand:SI 1 "register_operand" ""))
10348 (use (match_operand:SI 2 "register_operand" ""))]
d5b7b3ae
RE
10349 "TARGET_EITHER"
10350 "
5895f793
RE
10351 {
10352 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10353 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10354 {
10355 rtx ra = gen_rtx_REG (Pmode, 2);
10356
10357 emit_move_insn (ra, operands[2]);
10358 operands[2] = ra;
10359 }
9b598fa0
RE
10360 /* This is a hack -- we may have crystalized the function type too
10361 early. */
10362 cfun->machine->func_type = 0;
5895f793
RE
10363 }"
10364)
949d79eb 10365
ff9940b0
RE
10366;; This split is only used during output to reduce the number of patterns
10367;; that need assembler instructions adding to them. We allowed the setting
10368;; of the conditions to be implicit during rtl generation so that
10369;; the conditional compare patterns would work. However this conflicts to
f54fd62e 10370;; some extent with the conditional data operations, so we have to split them
ff9940b0
RE
10371;; up again here.
10372
5b3e6663
PB
10373;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10374;; conditional execution sufficient?
10375
ff9940b0
RE
10376(define_split
10377 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1
RE
10378 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10379 [(match_operand 2 "" "") (match_operand 3 "" "")])
10380 (match_dup 0)
10381 (match_operand 4 "" "")))
48a08b9c 10382 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 10383 "TARGET_ARM && reload_completed"
05ed98a1
RE
10384 [(set (match_dup 5) (match_dup 6))
10385 (cond_exec (match_dup 7)
10386 (set (match_dup 0) (match_dup 4)))]
10387 "
10388 {
10389 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10390 operands[2], operands[3]);
10391 enum rtx_code rc = GET_CODE (operands[1]);
10392
48a08b9c 10393 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
05ed98a1
RE
10394 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10395 if (mode == CCFPmode || mode == CCFPEmode)
10396 rc = reverse_condition_maybe_unordered (rc);
10397 else
10398 rc = reverse_condition (rc);
10399
10400 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10401 }"
10402)
10403
10404(define_split
10405 [(set (match_operand:SI 0 "s_register_operand" "")
10406 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10407 [(match_operand 2 "" "") (match_operand 3 "" "")])
10408 (match_operand 4 "" "")
10409 (match_dup 0)))
48a08b9c 10410 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 10411 "TARGET_ARM && reload_completed"
05ed98a1
RE
10412 [(set (match_dup 5) (match_dup 6))
10413 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10414 (set (match_dup 0) (match_dup 4)))]
10415 "
10416 {
10417 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10418 operands[2], operands[3]);
10419
48a08b9c 10420 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
05ed98a1
RE
10421 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10422 }"
10423)
10424
10425(define_split
10426 [(set (match_operand:SI 0 "s_register_operand" "")
10427 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
ff9940b0
RE
10428 [(match_operand 2 "" "") (match_operand 3 "" "")])
10429 (match_operand 4 "" "")
10430 (match_operand 5 "" "")))
48a08b9c 10431 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 10432 "TARGET_ARM && reload_completed"
05ed98a1
RE
10433 [(set (match_dup 6) (match_dup 7))
10434 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10435 (set (match_dup 0) (match_dup 4)))
10436 (cond_exec (match_dup 8)
10437 (set (match_dup 0) (match_dup 5)))]
10438 "
10439 {
10440 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10441 operands[2], operands[3]);
10442 enum rtx_code rc = GET_CODE (operands[1]);
10443
48a08b9c 10444 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
05ed98a1
RE
10445 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10446 if (mode == CCFPmode || mode == CCFPEmode)
10447 rc = reverse_condition_maybe_unordered (rc);
10448 else
10449 rc = reverse_condition (rc);
10450
10451 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10452 }"
10453)
10454
d5b7b3ae
RE
10455(define_split
10456 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 10457 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
d5b7b3ae
RE
10458 [(match_operand:SI 2 "s_register_operand" "")
10459 (match_operand:SI 3 "arm_add_operand" "")])
10460 (match_operand:SI 4 "arm_rhs_operand" "")
10461 (not:SI
10462 (match_operand:SI 5 "s_register_operand" ""))))
48a08b9c 10463 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 10464 "TARGET_ARM && reload_completed"
d5b7b3ae 10465 [(set (match_dup 6) (match_dup 7))
1646cf41
RE
10466 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10467 (set (match_dup 0) (match_dup 4)))
10468 (cond_exec (match_dup 8)
10469 (set (match_dup 0) (not:SI (match_dup 5))))]
d5b7b3ae 10470 "
5895f793
RE
10471 {
10472 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10473 operands[2], operands[3]);
1646cf41 10474 enum rtx_code rc = GET_CODE (operands[1]);
d5b7b3ae 10475
48a08b9c 10476 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
f1c25d3b 10477 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
1646cf41
RE
10478 if (mode == CCFPmode || mode == CCFPEmode)
10479 rc = reverse_condition_maybe_unordered (rc);
10480 else
10481 rc = reverse_condition (rc);
10482
10483 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
5895f793
RE
10484 }"
10485)
d5b7b3ae
RE
10486
10487(define_insn "*cond_move_not"
10488 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 10489 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
d5b7b3ae
RE
10490 [(match_operand 3 "cc_register" "") (const_int 0)])
10491 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10492 (not:SI
10493 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10494 "TARGET_ARM"
10495 "@
10496 mvn%D4\\t%0, %2
10497 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
cca0a211
RE
10498 [(set_attr "conds" "use")
10499 (set_attr "length" "4,8")]
10500)
d5b7b3ae 10501
ff9940b0
RE
10502;; The next two patterns occur when an AND operation is followed by a
10503;; scc insn sequence
10504
4cdb3ed4 10505(define_insn "*sign_extract_onebit"
ff9940b0
RE
10506 [(set (match_operand:SI 0 "s_register_operand" "=r")
10507 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10508 (const_int 1)
c1ff6200
JD
10509 (match_operand:SI 2 "const_int_operand" "n")))
10510 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 10511 "TARGET_ARM"
ff9940b0 10512 "*
cca0a211
RE
10513 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10514 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10515 return \"mvnne\\t%0, #0\";
10516 "
10517 [(set_attr "conds" "clob")
10518 (set_attr "length" "8")]
10519)
ff9940b0 10520
4cdb3ed4 10521(define_insn "*not_signextract_onebit"
ff9940b0
RE
10522 [(set (match_operand:SI 0 "s_register_operand" "=r")
10523 (not:SI
10524 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10525 (const_int 1)
c1ff6200
JD
10526 (match_operand:SI 2 "const_int_operand" "n"))))
10527 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 10528 "TARGET_ARM"
ff9940b0 10529 "*
cca0a211
RE
10530 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10531 output_asm_insn (\"tst\\t%1, %2\", operands);
10532 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10533 return \"movne\\t%0, #0\";
10534 "
10535 [(set_attr "conds" "clob")
10536 (set_attr "length" "12")]
10537)
5b3e6663 10538;; ??? The above patterns need auditing for Thumb-2
091426d3 10539
cca0a211
RE
10540;; Push multiple registers to the stack. Registers are in parallel (use ...)
10541;; expressions. For simplicity, the first register is also in the unspec
10542;; part.
4cdb3ed4 10543(define_insn "*push_multi"
091426d3
RE
10544 [(match_parallel 2 "multi_register_push"
10545 [(set (match_operand:BLK 0 "memory_operand" "=m")
b15bca31
RE
10546 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10547 UNSPEC_PUSH_MULT))])]
5b3e6663 10548 "TARGET_32BIT"
091426d3 10549 "*
5895f793
RE
10550 {
10551 int num_saves = XVECLEN (operands[2], 0);
3a5a4282 10552
5895f793 10553 /* For the StrongARM at least it is faster to
5b3e6663 10554 use STR to store only a single register.
7a085dce
KH
10555 In Thumb mode always use push, and the assembler will pick
10556 something appropriate. */
5b3e6663 10557 if (num_saves == 1 && TARGET_ARM)
5895f793
RE
10558 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10559 else
10560 {
10561 int i;
10562 char pattern[100];
3a5a4282 10563
5b3e6663
PB
10564 if (TARGET_ARM)
10565 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10566 else
10567 strcpy (pattern, \"push\\t{%1\");
5895f793 10568
880c4dcb 10569 for (i = 1; i < num_saves; i++)
5895f793
RE
10570 {
10571 strcat (pattern, \", %|\");
10572 strcat (pattern,
10573 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10574 }
10575
10576 strcat (pattern, \"}\");
10577 output_asm_insn (pattern, operands);
10578 }
10579
10580 return \"\";
10581 }"
10582 [(set_attr "type" "store4")]
10583)
4cdb3ed4 10584
3894f59e
RE
10585(define_insn "stack_tie"
10586 [(set (mem:BLK (scratch))
f5c630c3
PB
10587 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10588 (match_operand:SI 1 "s_register_operand" "rk")]
3894f59e
RE
10589 UNSPEC_PRLG_STK))]
10590 ""
10591 ""
10592 [(set_attr "length" "0")]
10593)
10594
38e01259 10595;; Similarly for the floating point registers
e9335bb6
RE
10596(define_insn "*push_fp_multi"
10597 [(match_parallel 2 "multi_register_push"
10598 [(set (match_operand:BLK 0 "memory_operand" "=m")
b15bca31
RE
10599 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10600 UNSPEC_PUSH_MULT))])]
5b3e6663 10601 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
e9335bb6 10602 "*
5895f793
RE
10603 {
10604 char pattern[100];
e9335bb6 10605
5895f793
RE
10606 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10607 output_asm_insn (pattern, operands);
10608 return \"\";
10609 }"
10610 [(set_attr "type" "f_store")]
10611)
e9335bb6 10612
4cdb3ed4
RE
10613;; Special patterns for dealing with the constant pool
10614
d5b7b3ae 10615(define_insn "align_4"
b15bca31 10616 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
d5b7b3ae 10617 "TARGET_EITHER"
4cdb3ed4 10618 "*
d5b7b3ae 10619 assemble_align (32);
4cdb3ed4 10620 return \"\";
d5b7b3ae
RE
10621 "
10622)
4cdb3ed4 10623
5a9335ef
NC
10624(define_insn "align_8"
10625 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
5848830f 10626 "TARGET_EITHER"
5a9335ef
NC
10627 "*
10628 assemble_align (64);
10629 return \"\";
10630 "
10631)
10632
d5b7b3ae 10633(define_insn "consttable_end"
b15bca31 10634 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
d5b7b3ae 10635 "TARGET_EITHER"
4cdb3ed4 10636 "*
d5b7b3ae 10637 making_const_table = FALSE;
4cdb3ed4 10638 return \"\";
d5b7b3ae
RE
10639 "
10640)
4cdb3ed4 10641
d5b7b3ae 10642(define_insn "consttable_1"
b15bca31 10643 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
5b3e6663 10644 "TARGET_THUMB1"
4cdb3ed4 10645 "*
d5b7b3ae 10646 making_const_table = TRUE;
c8af3574 10647 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
d5b7b3ae 10648 assemble_zeros (3);
4cdb3ed4 10649 return \"\";
d5b7b3ae
RE
10650 "
10651 [(set_attr "length" "4")]
10652)
4cdb3ed4 10653
d5b7b3ae 10654(define_insn "consttable_2"
b15bca31 10655 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
5b3e6663 10656 "TARGET_THUMB1"
4cdb3ed4 10657 "*
d5b7b3ae 10658 making_const_table = TRUE;
c8af3574 10659 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
d5b7b3ae 10660 assemble_zeros (2);
4cdb3ed4 10661 return \"\";
d5b7b3ae
RE
10662 "
10663 [(set_attr "length" "4")]
10664)
10665
10666(define_insn "consttable_4"
b15bca31 10667 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
d5b7b3ae
RE
10668 "TARGET_EITHER"
10669 "*
10670 {
10671 making_const_table = TRUE;
10672 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10673 {
10674 case MODE_FLOAT:
10675 {
b216cd4a
ZW
10676 REAL_VALUE_TYPE r;
10677 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10678 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
d5b7b3ae
RE
10679 break;
10680 }
10681 default:
c8af3574 10682 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
a7fe25b8 10683 mark_symbol_refs_as_used (operands[0]);
d5b7b3ae
RE
10684 break;
10685 }
10686 return \"\";
10687 }"
10688 [(set_attr "length" "4")]
10689)
10690
10691(define_insn "consttable_8"
b15bca31 10692 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
d5b7b3ae
RE
10693 "TARGET_EITHER"
10694 "*
10695 {
10696 making_const_table = TRUE;
10697 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10698 {
10699 case MODE_FLOAT:
10700 {
b216cd4a
ZW
10701 REAL_VALUE_TYPE r;
10702 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10703 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
d5b7b3ae
RE
10704 break;
10705 }
10706 default:
c8af3574 10707 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
d5b7b3ae
RE
10708 break;
10709 }
10710 return \"\";
10711 }"
10712 [(set_attr "length" "8")]
10713)
10714
88f77cba
JB
10715(define_insn "consttable_16"
10716 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10717 "TARGET_EITHER"
10718 "*
10719 {
10720 making_const_table = TRUE;
10721 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10722 {
10723 case MODE_FLOAT:
10724 {
10725 REAL_VALUE_TYPE r;
10726 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10727 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10728 break;
10729 }
10730 default:
10731 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10732 break;
10733 }
10734 return \"\";
10735 }"
10736 [(set_attr "length" "16")]
10737)
10738
d5b7b3ae
RE
10739;; Miscellaneous Thumb patterns
10740
657d9449 10741(define_expand "tablejump"
82955615 10742 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
657d9449 10743 (use (label_ref (match_operand 1 "" "")))])]
5b3e6663 10744 "TARGET_THUMB1"
657d9449
RE
10745 "
10746 if (flag_pic)
10747 {
10748 /* Hopefully, CSE will eliminate this copy. */
10749 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10750 rtx reg2 = gen_reg_rtx (SImode);
10751
10752 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10753 operands[0] = reg2;
10754 }
10755 "
10756)
10757
68d560d4 10758;; NB never uses BX.
5b3e6663 10759(define_insn "*thumb1_tablejump"
d5b7b3ae
RE
10760 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10761 (use (label_ref (match_operand 1 "" "")))]
5b3e6663 10762 "TARGET_THUMB1"
657d9449 10763 "mov\\t%|pc, %0"
d5b7b3ae
RE
10764 [(set_attr "length" "2")]
10765)
cca0a211 10766
d19fb8e3
NC
10767;; V5 Instructions,
10768
7dba8395
RH
10769(define_insn "clzsi2"
10770 [(set (match_operand:SI 0 "s_register_operand" "=r")
10771 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 10772 "TARGET_32BIT && arm_arch5"
e912eadf 10773 "clz%?\\t%0, %1"
c956e102
MS
10774 [(set_attr "predicable" "yes")
10775 (set_attr "insn" "clz")])
d19fb8e3 10776
b15bca31 10777;; V5E instructions.
d19fb8e3
NC
10778
10779(define_insn "prefetch"
fa980e6b
RE
10780 [(prefetch (match_operand:SI 0 "address_operand" "p")
10781 (match_operand:SI 1 "" "")
10782 (match_operand:SI 2 "" ""))]
5b3e6663 10783 "TARGET_32BIT && arm_arch5e"
a00b07c5 10784 "pld\\t%a0")
d19fb8e3 10785
cca0a211
RE
10786;; General predication pattern
10787
10788(define_cond_exec
10789 [(match_operator 0 "arm_comparison_operator"
10790 [(match_operand 1 "cc_register" "")
10791 (const_int 0)])]
5b3e6663 10792 "TARGET_32BIT"
cca0a211
RE
10793 ""
10794)
10795
6bacc7b0
NC
10796(define_insn "prologue_use"
10797 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10798 ""
10799 "%@ %0 needed for prologue"
10800)
82955615 10801
c9ca9b88
PB
10802
10803;; Patterns for exception handling
10804
10805(define_expand "eh_return"
10806 [(use (match_operand 0 "general_operand" ""))]
10807 "TARGET_EITHER"
10808 "
10809 {
5b3e6663 10810 if (TARGET_32BIT)
c9ca9b88
PB
10811 emit_insn (gen_arm_eh_return (operands[0]));
10812 else
10813 emit_insn (gen_thumb_eh_return (operands[0]));
10814 DONE;
10815 }"
10816)
10817
10818;; We can't expand this before we know where the link register is stored.
10819(define_insn_and_split "arm_eh_return"
10820 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10821 VUNSPEC_EH_RETURN)
10822 (clobber (match_scratch:SI 1 "=&r"))]
10823 "TARGET_ARM"
10824 "#"
10825 "&& reload_completed"
10826 [(const_int 0)]
10827 "
10828 {
10829 arm_set_return_address (operands[0], operands[1]);
10830 DONE;
10831 }"
10832)
10833
10834(define_insn_and_split "thumb_eh_return"
10835 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10836 VUNSPEC_EH_RETURN)
10837 (clobber (match_scratch:SI 1 "=&l"))]
5b3e6663 10838 "TARGET_THUMB1"
c9ca9b88
PB
10839 "#"
10840 "&& reload_completed"
10841 [(const_int 0)]
10842 "
10843 {
10844 thumb_set_return_address (operands[0], operands[1]);
10845 DONE;
10846 }"
10847)
10848
d3585b76
DJ
10849\f
10850;; TLS support
10851
10852(define_insn "load_tp_hard"
10853 [(set (match_operand:SI 0 "register_operand" "=r")
10854 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10855 "TARGET_HARD_TP"
10856 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10857 [(set_attr "predicable" "yes")]
10858)
10859
10860;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10861(define_insn "load_tp_soft"
10862 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10863 (clobber (reg:SI LR_REGNUM))
10864 (clobber (reg:SI IP_REGNUM))
10865 (clobber (reg:CC CC_REGNUM))]
10866 "TARGET_SOFT_TP"
10867 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10868 [(set_attr "conds" "clob")]
10869)
10870
82955615
RE
10871;; Load the FPA co-processor patterns
10872(include "fpa.md")
10873;; Load the Maverick co-processor patterns
10874(include "cirrus.md")
88f77cba
JB
10875;; Vector bits common to IWMMXT and Neon
10876(include "vec-common.md")
5a9335ef
NC
10877;; Load the Intel Wireless Multimedia Extension patterns
10878(include "iwmmxt.md")
9b66ebb1
PB
10879;; Load the VFP co-processor patterns
10880(include "vfp.md")
5b3e6663
PB
10881;; Thumb-2 patterns
10882(include "thumb2.md")
88f77cba
JB
10883;; Neon patterns
10884(include "neon.md")
9b66ebb1 10885