arm.md revision 132718
1100894Srwatson;;- Machine description for ARM for GNU compiler
2100894Srwatson;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3100894Srwatson;;  2001, 2002, 2003 2004  Free Software Foundation, Inc.
4113681Srwatson;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5100894Srwatson;;  and Martin Simmons (@harleqn.co.uk).
6100894Srwatson;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
7100894Srwatson
8100894Srwatson;; This file is part of GCC.
9100894Srwatson
10106392Srwatson;; GCC is free software; you can redistribute it and/or modify it
11106392Srwatson;; under the terms of the GNU General Public License as published
12106392Srwatson;; by the Free Software Foundation; either version 2, or (at your
13106392Srwatson;; option) any later version.
14100894Srwatson
15100894Srwatson;; GCC is distributed in the hope that it will be useful, but WITHOUT
16100894Srwatson;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17100894Srwatson;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18100894Srwatson;; License for more details.
19100894Srwatson
20100894Srwatson;; You should have received a copy of the GNU General Public License
21100894Srwatson;; along with GCC; see the file COPYING.  If not, write to
22100894Srwatson;; the Free Software Foundation, 59 Temple Place - Suite 330,
23100894Srwatson;; Boston, MA 02111-1307, USA.
24100894Srwatson
25100894Srwatson;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26100894Srwatson
27100894Srwatson
28100894Srwatson;;---------------------------------------------------------------------------
29100894Srwatson;; Constants
30100894Srwatson
31100894Srwatson;; Register numbers
32100894Srwatson(define_constants
33100894Srwatson  [(IP_REGNUM	    12)		; Scratch register
34100894Srwatson   (SP_REGNUM	    13)		; Stack pointer
35100894Srwatson   (LR_REGNUM       14)		; Return address register
36116182Sobrien   (PC_REGNUM	    15)		; Program counter
37116182Sobrien   (CC_REGNUM       24)		; Condition code pseudo register
38116182Sobrien   (LAST_ARM_REGNUM 15)
39116182Sobrien  ]
40100894Srwatson)
41101173Srwatson;; 3rd operand to select_dominance_cc_mode
42100894Srwatson(define_constants
43106856Srwatson  [(DOM_CC_X_AND_Y  0)
44106468Srwatson   (DOM_CC_NX_OR_Y  1)
45100979Srwatson   (DOM_CC_X_OR_Y   2)
46100979Srwatson  ]
47102949Sbde)
48100979Srwatson
49100979Srwatson;; UNSPEC Usage:
50100979Srwatson;; Note: sin and cos are no-longer used.
51116701Srwatson
52100979Srwatson(define_constants
53100979Srwatson  [(UNSPEC_SIN       0)	; `sin' operation (MODE_FLOAT):
54100979Srwatson			;   operand 0 is the result,
55100979Srwatson			;   operand 1 the parameter.
56100979Srwatson   (UNPSEC_COS	     1)	; `cos' operation (MODE_FLOAT):
57100979Srwatson			;   operand 0 is the result,
58100894Srwatson			;   operand 1 the parameter.
59100979Srwatson   (UNSPEC_PUSH_MULT 2)	; `push multiple' operation:
60100979Srwatson			;   operand 0 is the first register,
61100979Srwatson			;   subsequent registers are in parallel (use ...)
62100979Srwatson			;   expressions.
63100979Srwatson   (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
64100979Srwatson			;   usage, that is, we will add the pic_register
65100979Srwatson			;   value to it before trying to dereference it.
66121361Srwatson   (UNSPEC_PIC_BASE  4)	; Adding the PC value to the offset to the
67100979Srwatson			;   GLOBAL_OFFSET_TABLE.  The operation is fully
68121361Srwatson			;   described by the RTL but must be wrapped to
69100979Srwatson			;   prevent combine from trying to rip it apart.
70100979Srwatson   (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
71100979Srwatson			;   being scheduled before the stack adjustment insn.
72100979Srwatson   (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73121361Srwatson   			; this unspec is used to prevent the deletion of
74103514Srwatson   			; instructions setting registers for EH handling
75103514Srwatson   			; and stack frame generation.  Operand 0 is the
76104236Srwatson   			; register to "use".
77103514Srwatson   (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78103136Srwatson   (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79103136Srwatson   (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80103136Srwatson   (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81103136Srwatson   (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82121361Srwatson   (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83101892Srwatson   (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84100979Srwatson   (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85100979Srwatson   (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86100979Srwatson   (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87100979Srwatson   (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88101988Srwatson   (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89121361Srwatson   (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
90104517Srwatson  ]
91100979Srwatson)
92107105Srwatson
93107105Srwatson;; UNSPEC_VOLATILE Usage:
94101988Srwatson
95100979Srwatson(define_constants
96100979Srwatson  [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
97100979Srwatson			;   insn in the code.
98100979Srwatson   (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99122524Srwatson			;   instruction epilogue sequence that isn't expanded
100122524Srwatson			;   into normal RTL.  Used for both normal and sibcall
101104521Srwatson			;   epilogues.
102122524Srwatson   (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
103104521Srwatson			;   for inlined constants.
104122524Srwatson   (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
105105694Srwatson			;   table.
106119184Srwatson   (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
107122524Srwatson			;   an 8-bit object.
108104521Srwatson   (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
109104521Srwatson			;   a 16-bit object.
110104521Srwatson   (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
111105694Srwatson			;   a 32-bit object.
112105694Srwatson   (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
113105694Srwatson			;   a 64-bit object.
114122524Srwatson   (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
115105694Srwatson   (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
116105694Srwatson   (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
117122524Srwatson   (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
118122524Srwatson   (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119122524Srwatson   (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
120122524Srwatson  ]
121122524Srwatson)
122122524Srwatson
123122524Srwatson;;---------------------------------------------------------------------------
124122524Srwatson;; Attributes
125122524Srwatson
126122524Srwatson; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127122524Srwatson; generating ARM code.  This is used to control the length of some insn
128105694Srwatson; patterns that share the same RTL in both ARM and Thumb code.
129107105Srwatson(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
130107105Srwatson
131107105Srwatson; PROG_MODE attribute is used to determine whether condition codes are
132122524Srwatson; clobbered by a call insn: they are if in prog32 mode.  This is controlled
133107105Srwatson; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134107105Srwatson(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
135105988Srwatson
136122524Srwatson; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137104521Srwatson; scheduling decisions for the load unit and the multiplier.
138104521Srwatson(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
139105694Srwatson
140122524Srwatson;; Operand number of an input operand that is shifted.  Zero if the
141119184Srwatson;; given instruction does not shift one of its input operands.
142104521Srwatson(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143104521Srwatson(define_attr "shift" "" (const_int 0))
144104521Srwatson
145105694Srwatson; Floating Point Unit.  If we only have floating point emulation, then there
146105694Srwatson; is no point in scheduling the floating point insns.  (Well, for best
147105694Srwatson; performance we should try and group them together).
148122524Srwatson(define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
149122524Srwatson  (const (symbol_ref "arm_fpu_attr")))
150105694Srwatson
151105694Srwatson; LENGTH of an instruction (in bytes)
152122524Srwatson(define_attr "length" "" (const_int 4))
153122524Srwatson
154122524Srwatson; POOL_RANGE is how far away from a constant pool entry that this insn
155122524Srwatson; can be placed.  If the distance is zero, then this insn will never
156122524Srwatson; reference the pool.
157122524Srwatson; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
158122524Srwatson; before its address.
159122524Srwatson(define_attr "pool_range" "" (const_int 0))
160122524Srwatson(define_attr "neg_pool_range" "" (const_int 0))
161105694Srwatson
162107105Srwatson; An assembler sequence may clobber the condition codes without us knowing.
163107105Srwatson; If such an insn references the pool, then we have no way of knowing how,
164107105Srwatson; so use the most conservative value for pool_range.
165122524Srwatson(define_asm_attributes
166122524Srwatson [(set_attr "conds" "clob")
167107105Srwatson  (set_attr "length" "4")
168107105Srwatson  (set_attr "pool_range" "250")])
169121361Srwatson
170105694Srwatson; TYPE attribute is used to detect floating point instructions which, if
171122159Srwatson; running on a co-processor can run in parallel with other, basic instructions
172105694Srwatson; If write-buffer scheduling is enabled then it can also be used in the
173104522Srwatson; scheduling of writes.
174104522Srwatson
175121507Srwatson; Classification of each insn
176104522Srwatson; normal	any data instruction that doesn't hit memory or fp regs
177104522Srwatson; mult		a multiply instruction
178104522Srwatson; block		blockage insn, this blocks all functional units
179104522Srwatson; float		a floating point arithmetic operation (subject to expansion)
180121361Srwatson; fdivd		DFmode floating point division
181105694Srwatson; fdivs		SFmode floating point division
182105694Srwatson; fmul		Floating point multiply
183105694Srwatson; ffmul		Fast floating point multiply
184105694Srwatson; farith	Floating point arithmetic (4 cycle)
185121507Srwatson; ffarith	Fast floating point arithmetic (2 cycle)
186105694Srwatson; float_em	a floating point arithmetic operation that is normally emulated
187105694Srwatson;		even on a machine with an fpa.
188105694Srwatson; f_load	a floating point load from memory
189105694Srwatson; f_store	a floating point store to memory
190104522Srwatson; f_mem_r	a transfer of a floating point register to a real reg via mem
191104522Srwatson; r_mem_f	the reverse of f_mem_r
192104522Srwatson; f_2_r		fast transfer float to arm (no memory needed)
193104522Srwatson; r_2_f		fast transfer arm to float
194104521Srwatson; call		a subroutine call
195104522Srwatson; load		any load from memory
196104522Srwatson; store1	store 1 word to memory from arm registers
197104522Srwatson; store2	store 2 words
198104522Srwatson; store3	store 3 words
199104522Srwatson; store4	store 4 words
200104522Srwatson;  Additions for Cirrus Maverick co-processor:
201104522Srwatson; mav_farith	Floating point arithmetic (4 cycle)
202104522Srwatson; mav_dmult	Double multiplies (7 cycle)
203104522Srwatson;
204104522Srwatson(define_attr "type"
205104522Srwatson	"normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4,mav_farith,mav_dmult" 
206104522Srwatson	(const_string "normal"))
207104522Srwatson
208104522Srwatson; Load scheduling, set from the arm_ld_sched variable
209104522Srwatson; initialized by arm_override_options() 
210104522Srwatson(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
211104522Srwatson
212104522Srwatson; condition codes: this one is used by final_prescan_insn to speed up
213104522Srwatson; conditionalizing instructions.  It saves having to scan the rtl to see if
214104522Srwatson; it uses or alters the condition codes.
215104522Srwatson; 
216104522Srwatson; USE means that the condition codes are used by the insn in the process of
217104522Srwatson;   outputting code, this means (at present) that we can't use the insn in
218104522Srwatson;   inlined branches
219104522Srwatson;
220104522Srwatson; SET means that the purpose of the insn is to set the condition codes in a
221104522Srwatson;   well defined manner.
222104522Srwatson;
223104522Srwatson; CLOB means that the condition codes are altered in an undefined manner, if
224104522Srwatson;   they are altered at all
225123173Srwatson;
226104522Srwatson; JUMP_CLOB is used when the condition cannot be represented by a single
227104522Srwatson;   instruction (UNEQ and LTGT).  These cannot be predicated.
228123173Srwatson;
229104522Srwatson; NOCOND means that the condition codes are neither altered nor affect the
230104522Srwatson;   output of this insn
231105988Srwatson
232122524Srwatson(define_attr "conds" "use,set,clob,jump_clob,nocond"
233106468Srwatson	(if_then_else (eq_attr "type" "call")
234122524Srwatson	 (if_then_else (eq_attr "prog_mode" "prog32")
235106468Srwatson	  (const_string "clob") (const_string "nocond"))
236106468Srwatson	 (const_string "nocond")))
237106468Srwatson
238106468Srwatson; Predicable means that the insn can be conditionally executed based on
239106468Srwatson; an automatically added predicate (additional patterns are generated by 
240106468Srwatson; gen...).  We default to 'no' because no Thumb patterns match this rule
241106468Srwatson; and not all ARM patterns do.
242106468Srwatson(define_attr "predicable" "no,yes" (const_string "no"))
243106468Srwatson
244106468Srwatson; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
245106468Srwatson; have one.  Later ones, such as StrongARM, have write-back caches, so don't
246106468Srwatson; suffer blockages enough to warrant modelling this (and it can adversely
247106468Srwatson; affect the schedule).
248106468Srwatson(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
249106468Srwatson
250111119Simp; WRITE_CONFLICT implies that a read following an unrelated write is likely
251106468Srwatson; to stall the processor.  Used with model_wbuf above.
252106468Srwatson(define_attr "write_conflict" "no,yes"
253106468Srwatson  (if_then_else (eq_attr "type"
254106468Srwatson		 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
255106468Srwatson		(const_string "yes")
256106468Srwatson		(const_string "no")))
257122524Srwatson
258122524Srwatson; Classify the insns into those that take one cycle and those that take more
259106468Srwatson; than one on the main cpu execution unit.
260106468Srwatson(define_attr "core_cycles" "single,multi"
261122524Srwatson  (if_then_else (eq_attr "type"
262106468Srwatson		 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
263106468Srwatson		(const_string "single")
264122524Srwatson	        (const_string "multi")))
265106468Srwatson
266106468Srwatson;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
267106468Srwatson;; distant label.  Only applicable to Thumb code.
268100979Srwatson(define_attr "far_jump" "yes,no" (const_string "no"))
269106468Srwatson
270100979Srwatson(define_automaton "arm")
271122524Srwatson
272122524Srwatson;; Write buffer
273122524Srwatson;
274122524Srwatson; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
275106468Srwatson;
276100979Srwatson; The write buffer on some of the arm6 processors is hard to model exactly.
277100979Srwatson; There is room in the buffer for up to two addresses and up to eight words
278100979Srwatson; of memory, but the two needn't be split evenly.  When writing the two
279100979Srwatson; addresses are fully pipelined.  However, a read from memory that is not
280100979Srwatson; currently in the cache will block until the writes have completed.
281100979Srwatson; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
282100979Srwatson; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
283107271Srwatson; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
284100979Srwatson; cycle to add as well.
285100979Srwatson(define_cpu_unit "write_buf" "arm")
286100979Srwatson
287100979Srwatson;; Write blockage unit
288100979Srwatson;
289100979Srwatson; The write_blockage unit models (partially), the fact that reads will stall
290100979Srwatson; until the write buffer empties.
291100979Srwatson; The f_mem_r and r_mem_f could also block, but they are to the stack,
292100979Srwatson; so we don't model them here
293100979Srwatson(define_cpu_unit "write_blockage" "arm")
294100979Srwatson
295100979Srwatson;; Core
296100979Srwatson;
297100979Srwatson(define_cpu_unit "core" "arm")
298100979Srwatson
299100979Srwatson(define_insn_reservation "r_mem_f_wbuf" 5
300100979Srwatson  (and (eq_attr "model_wbuf" "yes")
301100979Srwatson       (eq_attr "type" "r_mem_f"))
302100979Srwatson  "core+write_buf*3")
303100979Srwatson
304100979Srwatson(define_insn_reservation "store1_wbuf" 5
305100979Srwatson  (and (eq_attr "model_wbuf" "yes")
306100979Srwatson       (eq_attr "type" "store1"))
307100979Srwatson  "core+write_buf*3+write_blockage*5")
308100979Srwatson
309100979Srwatson(define_insn_reservation "store2_wbuf" 7
310100979Srwatson  (and (eq_attr "model_wbuf" "yes")
311100979Srwatson       (eq_attr "type" "store2"))
312100979Srwatson  "core+write_buf*4+write_blockage*7")
313100979Srwatson
314100979Srwatson(define_insn_reservation "store3_wbuf" 9
315100979Srwatson  (and (eq_attr "model_wbuf" "yes")
316100979Srwatson       (eq_attr "type" "store3"))
317100979Srwatson  "core+write_buf*5+write_blockage*9")
318100979Srwatson
319100979Srwatson(define_insn_reservation "store4_wbuf" 11
320100979Srwatson  (and (eq_attr "model_wbuf" "yes")
321100979Srwatson       (eq_attr "type" "store4"))
322104546Srwatson  "core+write_buf*6+write_blockage*11")
323104546Srwatson
324100979Srwatson(define_insn_reservation "store2" 3
325100979Srwatson  (and (eq_attr "model_wbuf" "no")
326100979Srwatson       (eq_attr "type" "store2"))
327100979Srwatson  "core*3")
328103136Srwatson
329103136Srwatson(define_insn_reservation "store3" 4
330103136Srwatson  (and (eq_attr "model_wbuf" "no")
331100979Srwatson       (eq_attr "type" "store3"))
332100979Srwatson  "core*4")
333100979Srwatson
334100979Srwatson(define_insn_reservation "store4" 5
335100979Srwatson  (and (eq_attr "model_wbuf" "no")
336100979Srwatson       (eq_attr "type" "store4"))
337100979Srwatson  "core*5")
338100979Srwatson
339100979Srwatson(define_insn_reservation "store1_ldsched" 1
340100979Srwatson  (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1"))
341100979Srwatson  "core")
342100979Srwatson
343100979Srwatson(define_insn_reservation "load_ldsched_xscale" 3
344100979Srwatson  (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
345100979Srwatson       (eq_attr "is_xscale" "yes"))
346100979Srwatson  "core")
347100979Srwatson
348100979Srwatson(define_insn_reservation "load_ldsched" 2
349100979Srwatson  (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
350100979Srwatson       (eq_attr "is_xscale" "no"))
351100979Srwatson  "core")
352100979Srwatson
353100979Srwatson(define_insn_reservation "load_or_store" 2
354100979Srwatson  (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1"))
355100979Srwatson  "core*2")
356100979Srwatson
357100979Srwatson(define_insn_reservation "mult" 16
358100979Srwatson  (and (eq_attr "ldsched" "no") (eq_attr "type" "mult"))
359100979Srwatson  "core*16")
360100979Srwatson
361100979Srwatson(define_insn_reservation "mult_ldsched_strongarm" 3
362100979Srwatson  (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
363100979Srwatson       (eq_attr "type" "mult"))
364104546Srwatson  "core*2")
365104546Srwatson
366100979Srwatson(define_insn_reservation "mult_ldsched" 4
367100979Srwatson  (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
368100979Srwatson       (eq_attr "type" "mult"))
369100979Srwatson  "core*4")
370100979Srwatson
371100979Srwatson(define_insn_reservation "multi_cycle" 32
372100979Srwatson  (and (eq_attr "core_cycles" "multi")
373100979Srwatson       (eq_attr "type" "!mult,load,store1,store2,store3,store4"))
374102949Sbde  "core*32")
375102949Sbde
376102949Sbde(define_insn_reservation "single_cycle" 1
377102949Sbde  (eq_attr "core_cycles" "single")
378100979Srwatson  "core")
379100979Srwatson
380100979Srwatson
381100979Srwatson;;---------------------------------------------------------------------------
382100979Srwatson;; Insn patterns
383100979Srwatson;;
384100979Srwatson;; Addition insns.
385100979Srwatson
386100979Srwatson;; Note: For DImode insns, there is normally no reason why operands should
387100979Srwatson;; not be in the same register, what we don't want is for something being
388100979Srwatson;; written to partially overlap something that is an input.
389100979Srwatson;; Cirrus 64bit additions should not be split because we have a native
390100979Srwatson;; 64bit addition instructions.
391100979Srwatson
392100979Srwatson(define_expand "adddi3"
393100979Srwatson [(parallel
394100979Srwatson   [(set (match_operand:DI           0 "s_register_operand" "")
395100979Srwatson	  (plus:DI (match_operand:DI 1 "s_register_operand" "")
396100979Srwatson	           (match_operand:DI 2 "s_register_operand" "")))
397100979Srwatson    (clobber (reg:CC CC_REGNUM))])]
398113955Salc  "TARGET_EITHER"
399100979Srwatson  "
400100979Srwatson  if (TARGET_CIRRUS)
401100979Srwatson    {
402100979Srwatson      if (!cirrus_fp_register (operands[0], DImode))
403100979Srwatson        operands[0] = force_reg (DImode, operands[0]);
404113955Salc      if (!cirrus_fp_register (operands[1], DImode))
405100979Srwatson        operands[1] = force_reg (DImode, operands[1]);
406100979Srwatson      emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
407100979Srwatson      DONE;
408100979Srwatson    }
409100979Srwatson
410100979Srwatson  if (TARGET_THUMB)
411100979Srwatson    {
412100979Srwatson      if (GET_CODE (operands[1]) != REG)
413100979Srwatson        operands[1] = force_reg (SImode, operands[1]);
414100979Srwatson      if (GET_CODE (operands[2]) != REG)
415100979Srwatson        operands[2] = force_reg (SImode, operands[2]);
416100979Srwatson     }
417100979Srwatson  "
418100979Srwatson)
419100979Srwatson
420100979Srwatson(define_insn "*thumb_adddi3"
421100979Srwatson  [(set (match_operand:DI          0 "register_operand" "=l")
422100979Srwatson	(plus:DI (match_operand:DI 1 "register_operand" "%0")
423100979Srwatson		 (match_operand:DI 2 "register_operand" "l")))
424100979Srwatson   (clobber (reg:CC CC_REGNUM))
425100979Srwatson  ]
426100979Srwatson  "TARGET_THUMB"
427100979Srwatson  "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
428100979Srwatson  [(set_attr "length" "4")]
429100979Srwatson)
430100979Srwatson
431100979Srwatson(define_insn_and_split "*arm_adddi3"
432100979Srwatson  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
433100979Srwatson	(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
434100979Srwatson		 (match_operand:DI 2 "s_register_operand" "r,  0")))
435100979Srwatson   (clobber (reg:CC CC_REGNUM))]
436100979Srwatson  "TARGET_ARM && !TARGET_CIRRUS"
437100979Srwatson  "#"
438100979Srwatson  "TARGET_ARM && reload_completed"
439100979Srwatson  [(parallel [(set (reg:CC_C CC_REGNUM)
440100979Srwatson		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
441100979Srwatson				 (match_dup 1)))
442121361Srwatson	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
443100979Srwatson   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
444100979Srwatson			       (plus:SI (match_dup 4) (match_dup 5))))]
445100979Srwatson  "
446100979Srwatson  {
447100979Srwatson    operands[3] = gen_highpart (SImode, operands[0]);
448100979Srwatson    operands[0] = gen_lowpart (SImode, operands[0]);
449100979Srwatson    operands[4] = gen_highpart (SImode, operands[1]);
450100979Srwatson    operands[1] = gen_lowpart (SImode, operands[1]);
451100979Srwatson    operands[5] = gen_highpart (SImode, operands[2]);
452100979Srwatson    operands[2] = gen_lowpart (SImode, operands[2]);
453100979Srwatson  }"
454100979Srwatson  [(set_attr "conds" "clob")
455100979Srwatson   (set_attr "length" "8")]
456100979Srwatson)
457100979Srwatson
458100979Srwatson(define_insn_and_split "*adddi_sesidi_di"
459100979Srwatson  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
460100979Srwatson	(plus:DI (sign_extend:DI
461100979Srwatson		  (match_operand:SI 2 "s_register_operand" "r,r"))
462100979Srwatson		 (match_operand:DI 1 "s_register_operand" "r,0")))
463100979Srwatson   (clobber (reg:CC CC_REGNUM))]
464100979Srwatson  "TARGET_ARM && !TARGET_CIRRUS"
465100979Srwatson  "#"
466100979Srwatson  "TARGET_ARM && reload_completed"
467100979Srwatson  [(parallel [(set (reg:CC_C CC_REGNUM)
468100979Srwatson		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
469100979Srwatson				 (match_dup 1)))
470100979Srwatson	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
471100979Srwatson   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
472100979Srwatson			       (plus:SI (ashiftrt:SI (match_dup 2)
473100979Srwatson						     (const_int 31))
474100979Srwatson					(match_dup 4))))]
475100979Srwatson  "
476100979Srwatson  {
477102103Srwatson    operands[3] = gen_highpart (SImode, operands[0]);
478102103Srwatson    operands[0] = gen_lowpart (SImode, operands[0]);
479100979Srwatson    operands[4] = gen_highpart (SImode, operands[1]);
480100979Srwatson    operands[1] = gen_lowpart (SImode, operands[1]);
481100979Srwatson    operands[2] = gen_lowpart (SImode, operands[2]);
482100979Srwatson  }"
483100979Srwatson  [(set_attr "conds" "clob")
484100979Srwatson   (set_attr "length" "8")]
485100979Srwatson)
486100979Srwatson
487100979Srwatson(define_insn_and_split "*adddi_zesidi_di"
488100979Srwatson  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
489100979Srwatson	(plus:DI (zero_extend:DI
490100979Srwatson		  (match_operand:SI 2 "s_register_operand" "r,r"))
491100979Srwatson		 (match_operand:DI 1 "s_register_operand" "r,0")))
492102103Srwatson   (clobber (reg:CC CC_REGNUM))]
493102103Srwatson  "TARGET_ARM && !TARGET_CIRRUS"
494100979Srwatson  "#"
495100979Srwatson  "TARGET_ARM && reload_completed"
496100979Srwatson  [(parallel [(set (reg:CC_C CC_REGNUM)
497100979Srwatson		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
498100979Srwatson				 (match_dup 1)))
499100979Srwatson	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
500100979Srwatson   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
501100979Srwatson			       (plus:SI (match_dup 4) (const_int 0))))]
502100979Srwatson  "
503100979Srwatson  {
504100979Srwatson    operands[3] = gen_highpart (SImode, operands[0]);
505100979Srwatson    operands[0] = gen_lowpart (SImode, operands[0]);
506100979Srwatson    operands[4] = gen_highpart (SImode, operands[1]);
507102103Srwatson    operands[1] = gen_lowpart (SImode, operands[1]);
508102103Srwatson    operands[2] = gen_lowpart (SImode, operands[2]);
509100979Srwatson  }"
510100979Srwatson  [(set_attr "conds" "clob")
511100979Srwatson   (set_attr "length" "8")]
512100979Srwatson)
513100979Srwatson
514100979Srwatson(define_expand "addsi3"
515100979Srwatson  [(set (match_operand:SI          0 "s_register_operand" "")
516	(plus:SI (match_operand:SI 1 "s_register_operand" "")
517		 (match_operand:SI 2 "reg_or_int_operand" "")))]
518  "TARGET_EITHER"
519  "
520  if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
521    {
522      arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
523			  operands[1],
524			  (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
525      DONE;
526    }
527  "
528)
529
530; If there is a scratch available, this will be faster than synthesizing the
531; addition.
532(define_peephole2
533  [(match_scratch:SI 3 "r")
534   (set (match_operand:SI          0 "s_register_operand" "")
535	(plus:SI (match_operand:SI 1 "s_register_operand" "")
536		 (match_operand:SI 2 "const_int_operand"  "")))]
537  "TARGET_ARM &&
538   !(const_ok_for_arm (INTVAL (operands[2]))
539     || const_ok_for_arm (-INTVAL (operands[2])))
540    && const_ok_for_arm (~INTVAL (operands[2]))"
541  [(set (match_dup 3) (match_dup 2))
542   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
543  ""
544)
545
546(define_insn_and_split "*arm_addsi3"
547  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
548	(plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
549		 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
550  "TARGET_ARM"
551  "@
552   add%?\\t%0, %1, %2
553   sub%?\\t%0, %1, #%n2
554   #"
555  "TARGET_ARM &&
556   GET_CODE (operands[2]) == CONST_INT
557   && !(const_ok_for_arm (INTVAL (operands[2]))
558        || const_ok_for_arm (-INTVAL (operands[2])))"
559  [(clobber (const_int 0))]
560  "
561  arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
562		      operands[1], 0);
563  DONE;
564  "
565  [(set_attr "length" "4,4,16")
566   (set_attr "predicable" "yes")]
567)
568
569;; Register group 'k' is a single register group containing only the stack
570;; register.  Trying to reload it will always fail catastrophically,
571;; so never allow those alternatives to match if reloading is needed.
572
573(define_insn "*thumb_addsi3"
574  [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
575	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
576		 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
577  "TARGET_THUMB"
578  "*
579   static const char * const asms[] = 
580   {
581     \"add\\t%0, %0, %2\",
582     \"sub\\t%0, %0, #%n2\",
583     \"add\\t%0, %1, %2\",
584     \"add\\t%0, %0, %2\",
585     \"add\\t%0, %0, %2\",
586     \"add\\t%0, %1, %2\",
587     \"add\\t%0, %1, %2\"
588   };
589   if ((which_alternative == 2 || which_alternative == 6)
590       && GET_CODE (operands[2]) == CONST_INT
591       && INTVAL (operands[2]) < 0)
592     return \"sub\\t%0, %1, #%n2\";
593   return asms[which_alternative];
594  "
595  [(set_attr "length" "2")]
596)
597
598;; Reloading and elimination of the frame pointer can
599;; sometimes cause this optimization to be missed.
600(define_peephole2
601  [(set (match_operand:SI 0 "register_operand" "")
602	(match_operand:SI 1 "const_int_operand" ""))
603   (set (match_dup 0)
604	(plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
605  "TARGET_THUMB
606   && REGNO (operands[2]) == STACK_POINTER_REGNUM 
607   && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
608   && (INTVAL (operands[1]) & 3) == 0"
609  [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
610  ""
611)
612
613(define_insn "*addsi3_compare0"
614  [(set (reg:CC_NOOV CC_REGNUM)
615	(compare:CC_NOOV
616	 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
617		  (match_operand:SI 2 "arm_add_operand"    "rI,L"))
618	 (const_int 0)))
619   (set (match_operand:SI 0 "s_register_operand" "=r,r")
620	(plus:SI (match_dup 1) (match_dup 2)))]
621  "TARGET_ARM"
622  "@
623   add%?s\\t%0, %1, %2
624   sub%?s\\t%0, %1, #%n2"
625  [(set_attr "conds" "set")]
626)
627
628(define_insn "*addsi3_compare0_scratch"
629  [(set (reg:CC_NOOV CC_REGNUM)
630	(compare:CC_NOOV
631	 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
632		  (match_operand:SI 1 "arm_add_operand"    "rI,L"))
633	 (const_int 0)))]
634  "TARGET_ARM"
635  "@
636   cmn%?\\t%0, %1
637   cmp%?\\t%0, #%n1"
638  [(set_attr "conds" "set")]
639)
640
641;; These patterns are the same ones as the two regular addsi3_compare0
642;; patterns, except we write them slightly different - the combiner
643;; tends to generate them this way.
644(define_insn "*addsi3_compare0_for_combiner"
645  [(set (reg:CC CC_REGNUM)
646	(compare:CC
647	 (match_operand:SI 1 "s_register_operand" "r,r")
648	 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
649   (set (match_operand:SI 0 "s_register_operand" "=r,r")
650	(plus:SI (match_dup 1) (match_dup 2)))]
651  "TARGET_ARM"
652  "@
653   add%?s\\t%0, %1, %2
654   sub%?s\\t%0, %1, #%n2"
655  [(set_attr "conds" "set")]
656)
657
658(define_insn "*addsi3_compare0_scratch_for_combiner"
659  [(set (reg:CC CC_REGNUM)
660	(compare:CC
661	 (match_operand:SI 0 "s_register_operand" "r,r")
662	 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
663  "TARGET_ARM"
664  "@
665   cmn%?\\t%0, %1
666   cmp%?\\t%0, #%n1"
667  [(set_attr "conds" "set")]
668)
669
670;; This is the canonicalization of addsi3_compare0_for_combiner when the
671;; addend is a constant.
672(define_insn "*cmpsi2_addneg"
673  [(set (reg:CC CC_REGNUM)
674	(compare:CC
675	 (match_operand:SI 1 "s_register_operand" "r,r")
676	 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
677   (set (match_operand:SI 0 "s_register_operand" "=r,r")
678	(plus:SI (match_dup 1)
679		 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
680  "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
681  "@
682   sub%?s\\t%0, %1, %2
683   add%?s\\t%0, %1, #%n2"
684  [(set_attr "conds" "set")]
685)
686
687;; Convert the sequence
688;;  sub  rd, rn, #1
689;;  cmn  rd, #1	(equivalent to cmp rd, #-1)
690;;  bne  dest
691;; into
692;;  subs rd, rn, #1
693;;  bcs  dest	((unsigned)rn >= 1)
694;; similarly for the beq variant using bcc.
695;; This is a common looping idiom (while (n--))
696(define_peephole2
697  [(set (match_operand:SI 0 "s_register_operand" "")
698	(plus:SI (match_operand:SI 1 "s_register_operand" "")
699		 (const_int -1)))
700   (set (match_operand 2 "cc_register" "")
701	(compare (match_dup 0) (const_int -1)))
702   (set (pc)
703	(if_then_else (match_operator 3 "equality_operator"
704		       [(match_dup 2) (const_int 0)])
705		      (match_operand 4 "" "")
706		      (match_operand 5 "" "")))]
707  "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
708  [(parallel[
709    (set (match_dup 2)
710	 (compare:CC
711	  (match_dup 1) (const_int 1)))
712    (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
713   (set (pc)
714	(if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
715		      (match_dup 4)
716		      (match_dup 5)))]
717  "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
718   operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
719				  ? GEU : LTU),
720				 VOIDmode, 
721				 operands[2], const0_rtx);"
722)
723
724;; The next four insns work because they compare the result with one of
725;; the operands, and we know that the use of the condition code is
726;; either GEU or LTU, so we can use the carry flag from the addition
727;; instead of doing the compare a second time.
728(define_insn "*addsi3_compare_op1"
729  [(set (reg:CC_C CC_REGNUM)
730	(compare:CC_C
731	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
732		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
733	 (match_dup 1)))
734   (set (match_operand:SI 0 "s_register_operand" "=r,r")
735	(plus:SI (match_dup 1) (match_dup 2)))]
736  "TARGET_ARM"
737  "@
738   add%?s\\t%0, %1, %2
739   sub%?s\\t%0, %1, #%n2"
740  [(set_attr "conds" "set")]
741)
742
743(define_insn "*addsi3_compare_op2"
744  [(set (reg:CC_C CC_REGNUM)
745	(compare:CC_C
746	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
747		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
748	 (match_dup 2)))
749   (set (match_operand:SI 0 "s_register_operand" "=r,r")
750	(plus:SI (match_dup 1) (match_dup 2)))]
751  "TARGET_ARM"
752  "@
753   add%?s\\t%0, %1, %2
754   sub%?s\\t%0, %1, #%n2"
755  [(set_attr "conds" "set")]
756)
757
758(define_insn "*compare_addsi2_op0"
759  [(set (reg:CC_C CC_REGNUM)
760	(compare:CC_C
761	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
762		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
763	 (match_dup 0)))]
764  "TARGET_ARM"
765  "@
766   cmn%?\\t%0, %1
767   cmp%?\\t%0, #%n1"
768  [(set_attr "conds" "set")]
769)
770
771(define_insn "*compare_addsi2_op1"
772  [(set (reg:CC_C CC_REGNUM)
773	(compare:CC_C
774	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
775		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
776	 (match_dup 1)))]
777  "TARGET_ARM"
778  "@
779   cmn%?\\t%0, %1
780   cmp%?\\t%0, #%n1"
781  [(set_attr "conds" "set")]
782)
783
784(define_insn "*addsi3_carryin"
785  [(set (match_operand:SI 0 "s_register_operand" "=r")
786	(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
787		 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
788			  (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
789  "TARGET_ARM"
790  "adc%?\\t%0, %1, %2"
791  [(set_attr "conds" "use")]
792)
793
794(define_insn "*addsi3_carryin_shift"
795  [(set (match_operand:SI 0 "s_register_operand" "=r")
796	(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
797		 (plus:SI
798		   (match_operator:SI 2 "shift_operator"
799		      [(match_operand:SI 3 "s_register_operand" "r")
800		       (match_operand:SI 4 "reg_or_int_operand" "rM")])
801		    (match_operand:SI 1 "s_register_operand" "r"))))]
802  "TARGET_ARM"
803  "adc%?\\t%0, %1, %3%S2"
804  [(set_attr "conds" "use")]
805)
806
807(define_insn "*addsi3_carryin_alt1"
808  [(set (match_operand:SI 0 "s_register_operand" "=r")
809	(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
810			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
811		 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
812  "TARGET_ARM"
813  "adc%?\\t%0, %1, %2"
814  [(set_attr "conds" "use")]
815)
816
817(define_insn "*addsi3_carryin_alt2"
818  [(set (match_operand:SI 0 "s_register_operand" "=r")
819	(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
820			  (match_operand:SI 1 "s_register_operand" "r"))
821		 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
822  "TARGET_ARM"
823  "adc%?\\t%0, %1, %2"
824  [(set_attr "conds" "use")]
825)
826
827(define_insn "*addsi3_carryin_alt3"
828  [(set (match_operand:SI 0 "s_register_operand" "=r")
829	(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
830			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
831		 (match_operand:SI 1 "s_register_operand" "r")))]
832  "TARGET_ARM"
833  "adc%?\\t%0, %1, %2"
834  [(set_attr "conds" "use")]
835)
836
837(define_insn "incscc"
838  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
839        (plus:SI (match_operator:SI 2 "arm_comparison_operator"
840                    [(match_operand:CC 3 "cc_register" "") (const_int 0)])
841                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
842  "TARGET_ARM"
843  "@
844  add%d2\\t%0, %1, #1
845  mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
846  [(set_attr "conds" "use")
847   (set_attr "length" "4,8")]
848)
849
850; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
851(define_split
852  [(set (match_operand:SI 0 "s_register_operand" "")
853	(plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
854			    (match_operand:SI 2 "s_register_operand" ""))
855		 (const_int -1)))
856   (clobber (match_operand:SI 3 "s_register_operand" ""))]
857  "TARGET_ARM"
858  [(set (match_dup 3) (match_dup 1))
859   (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
860  "
861  operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
862")
863
864(define_expand "addsf3"
865  [(set (match_operand:SF          0 "s_register_operand" "")
866	(plus:SF (match_operand:SF 1 "s_register_operand" "")
867		 (match_operand:SF 2 "fpa_add_operand" "")))]
868  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
869  "
870  if (TARGET_CIRRUS
871      && !cirrus_fp_register (operands[2], SFmode))
872    operands[2] = force_reg (SFmode, operands[2]);
873")
874
875(define_expand "adddf3"
876  [(set (match_operand:DF          0 "s_register_operand" "")
877	(plus:DF (match_operand:DF 1 "s_register_operand" "")
878		 (match_operand:DF 2 "fpa_add_operand" "")))]
879  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
880  "
881  if (TARGET_CIRRUS
882      && !cirrus_fp_register (operands[2], DFmode))
883    operands[2] = force_reg (DFmode, operands[2]);
884")
885
886(define_expand "subdi3"
887 [(parallel
888   [(set (match_operand:DI            0 "s_register_operand" "")
889	  (minus:DI (match_operand:DI 1 "s_register_operand" "")
890	            (match_operand:DI 2 "s_register_operand" "")))
891    (clobber (reg:CC CC_REGNUM))])]
892  "TARGET_EITHER"
893  "
894  if (TARGET_CIRRUS
895      && TARGET_ARM
896      && cirrus_fp_register (operands[0], DImode)
897      && cirrus_fp_register (operands[1], DImode))
898    {
899      emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
900      DONE;
901    }
902
903  if (TARGET_THUMB)
904    {
905      if (GET_CODE (operands[1]) != REG)
906        operands[1] = force_reg (SImode, operands[1]);
907      if (GET_CODE (operands[2]) != REG)
908        operands[2] = force_reg (SImode, operands[2]);
909     }	
910  "
911)
912
913(define_insn "*arm_subdi3"
914  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
915	(minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
916		  (match_operand:DI 2 "s_register_operand" "r,0,0")))
917   (clobber (reg:CC CC_REGNUM))]
918  "TARGET_ARM"
919  "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
920  [(set_attr "conds" "clob")
921   (set_attr "length" "8")]
922)
923
924(define_insn "*thumb_subdi3"
925  [(set (match_operand:DI           0 "register_operand" "=l")
926	(minus:DI (match_operand:DI 1 "register_operand"  "0")
927		  (match_operand:DI 2 "register_operand"  "l")))
928   (clobber (reg:CC CC_REGNUM))]
929  "TARGET_THUMB"
930  "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
931  [(set_attr "length" "4")]
932)
933
934(define_insn "*subdi_di_zesidi"
935  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
936	(minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
937		  (zero_extend:DI
938		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
939   (clobber (reg:CC CC_REGNUM))]
940  "TARGET_ARM"
941  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
942  [(set_attr "conds" "clob")
943   (set_attr "length" "8")]
944)
945
946(define_insn "*subdi_di_sesidi"
947  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
948	(minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
949		  (sign_extend:DI
950		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
951   (clobber (reg:CC CC_REGNUM))]
952  "TARGET_ARM"
953  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
954  [(set_attr "conds" "clob")
955   (set_attr "length" "8")]
956)
957
958(define_insn "*subdi_zesidi_di"
959  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
960	(minus:DI (zero_extend:DI
961		   (match_operand:SI 2 "s_register_operand"  "r,r"))
962		  (match_operand:DI  1 "s_register_operand" "?r,0")))
963   (clobber (reg:CC CC_REGNUM))]
964  "TARGET_ARM"
965  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
966  [(set_attr "conds" "clob")
967   (set_attr "length" "8")]
968)
969
970(define_insn "*subdi_sesidi_di"
971  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
972	(minus:DI (sign_extend:DI
973		   (match_operand:SI 2 "s_register_operand"   "r,r"))
974		  (match_operand:DI  1 "s_register_operand"  "?r,0")))
975   (clobber (reg:CC CC_REGNUM))]
976  "TARGET_ARM"
977  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
978  [(set_attr "conds" "clob")
979   (set_attr "length" "8")]
980)
981
982(define_insn "*subdi_zesidi_zesidi"
983  [(set (match_operand:DI            0 "s_register_operand" "=r")
984	(minus:DI (zero_extend:DI
985		   (match_operand:SI 1 "s_register_operand"  "r"))
986		  (zero_extend:DI
987		   (match_operand:SI 2 "s_register_operand"  "r"))))
988   (clobber (reg:CC CC_REGNUM))]
989  "TARGET_ARM"
990  "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
991  [(set_attr "conds" "clob")
992   (set_attr "length" "8")]
993)
994
995(define_expand "subsi3"
996  [(set (match_operand:SI           0 "s_register_operand" "")
997	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
998		  (match_operand:SI 2 "s_register_operand" "")))]
999  "TARGET_EITHER"
1000  "
1001  if (GET_CODE (operands[1]) == CONST_INT)
1002    {
1003      if (TARGET_ARM)
1004        {
1005          arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1006	  		      operands[2],
1007			      (no_new_pseudos ? 0
1008			       :  preserve_subexpressions_p ()));
1009          DONE;
1010	}
1011      else /* TARGET_THUMB */
1012        operands[1] = force_reg (SImode, operands[1]);
1013    }
1014  "
1015)
1016
1017(define_insn "*thumb_subsi3_insn"
1018  [(set (match_operand:SI           0 "register_operand" "=l")
1019	(minus:SI (match_operand:SI 1 "register_operand" "l")
1020		  (match_operand:SI 2 "register_operand" "l")))]
1021  "TARGET_THUMB"
1022  "sub\\t%0, %1, %2"
1023  [(set_attr "length" "2")]
1024)
1025
1026(define_insn_and_split "*arm_subsi3_insn"
1027  [(set (match_operand:SI           0 "s_register_operand" "=r,r")
1028	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1029		  (match_operand:SI 2 "s_register_operand" "r,r")))]
1030  "TARGET_ARM"
1031  "@
1032   rsb%?\\t%0, %2, %1
1033   #"
1034  "TARGET_ARM
1035   && GET_CODE (operands[1]) == CONST_INT
1036   && !const_ok_for_arm (INTVAL (operands[1]))"
1037  [(clobber (const_int 0))]
1038  "
1039  arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1040		      operands[2], 0);
1041  DONE;
1042  "
1043  [(set_attr "length" "4,16")
1044   (set_attr "predicable" "yes")]
1045)
1046
1047(define_peephole2
1048  [(match_scratch:SI 3 "r")
1049   (set (match_operand:SI           0 "s_register_operand" "")
1050	(minus:SI (match_operand:SI 1 "const_int_operand" "")
1051		  (match_operand:SI 2 "s_register_operand" "")))]
1052  "TARGET_ARM
1053   && !const_ok_for_arm (INTVAL (operands[1]))
1054   && const_ok_for_arm (~INTVAL (operands[1]))"
1055  [(set (match_dup 3) (match_dup 1))
1056   (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1057  ""
1058)
1059
1060(define_insn "*subsi3_compare0"
1061  [(set (reg:CC_NOOV CC_REGNUM)
1062	(compare:CC_NOOV
1063	 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1064		   (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1065	 (const_int 0)))
1066   (set (match_operand:SI 0 "s_register_operand" "=r,r")
1067	(minus:SI (match_dup 1) (match_dup 2)))]
1068  "TARGET_ARM"
1069  "@
1070   sub%?s\\t%0, %1, %2
1071   rsb%?s\\t%0, %2, %1"
1072  [(set_attr "conds" "set")]
1073)
1074
1075(define_insn "decscc"
1076  [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1077        (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1078		  (match_operator:SI 2 "arm_comparison_operator"
1079                   [(match_operand   3 "cc_register" "") (const_int 0)])))]
1080  "TARGET_ARM"
1081  "@
1082   sub%d2\\t%0, %1, #1
1083   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1084  [(set_attr "conds" "use")
1085   (set_attr "length" "*,8")]
1086)
1087
1088(define_expand "subsf3"
1089  [(set (match_operand:SF           0 "s_register_operand" "")
1090	(minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1091		  (match_operand:SF 2 "fpa_rhs_operand" "")))]
1092  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1093  "
1094  if (TARGET_CIRRUS)
1095    {
1096      if (!cirrus_fp_register (operands[1], SFmode))
1097        operands[1] = force_reg (SFmode, operands[1]);
1098      if (!cirrus_fp_register (operands[2], SFmode))
1099        operands[2] = force_reg (SFmode, operands[2]);
1100    }
1101")
1102
1103(define_expand "subdf3"
1104  [(set (match_operand:DF           0 "s_register_operand" "")
1105	(minus:DF (match_operand:DF 1 "fpa_rhs_operand"     "")
1106		  (match_operand:DF 2 "fpa_rhs_operand"    "")))]
1107  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1108  "
1109  if (TARGET_CIRRUS)
1110    {
1111       if (!cirrus_fp_register (operands[1], DFmode))
1112         operands[1] = force_reg (DFmode, operands[1]);
1113       if (!cirrus_fp_register (operands[2], DFmode))
1114         operands[2] = force_reg (DFmode, operands[2]);
1115    }
1116")
1117
1118
1119;; Multiplication insns
1120
1121(define_expand "mulsi3"
1122  [(set (match_operand:SI          0 "s_register_operand" "")
1123	(mult:SI (match_operand:SI 2 "s_register_operand" "")
1124		 (match_operand:SI 1 "s_register_operand" "")))]
1125  "TARGET_EITHER"
1126  ""
1127)
1128
1129;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1130(define_insn "*arm_mulsi3"
1131  [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1132	(mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1133		 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1134  "TARGET_ARM"
1135  "mul%?\\t%0, %2, %1"
1136  [(set_attr "type" "mult")
1137   (set_attr "predicable" "yes")]
1138)
1139
1140; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1141; 1 and 2; are the same, because reload will make operand 0 match 
1142; operand 1 without realizing that this conflicts with operand 2.  We fix 
1143; this by adding another alternative to match this case, and then `reload' 
1144; it ourselves.  This alternative must come first.
1145(define_insn "*thumb_mulsi3"
1146  [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1147	(mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1148		 (match_operand:SI 2 "register_operand" "l,l,l")))]
1149  "TARGET_THUMB"
1150  "*
1151  if (which_alternative < 2)
1152    return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1153  else
1154    return \"mul\\t%0, %0, %2\";
1155  "
1156  [(set_attr "length" "4,4,2")
1157   (set_attr "type" "mult")]
1158)
1159
1160(define_insn "*mulsi3_compare0"
1161  [(set (reg:CC_NOOV CC_REGNUM)
1162	(compare:CC_NOOV (mult:SI
1163			  (match_operand:SI 2 "s_register_operand" "r,r")
1164			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
1165			 (const_int 0)))
1166   (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1167	(mult:SI (match_dup 2) (match_dup 1)))]
1168  "TARGET_ARM && !arm_arch_xscale"
1169  "mul%?s\\t%0, %2, %1"
1170  [(set_attr "conds" "set")
1171   (set_attr "type" "mult")]
1172)
1173
1174(define_insn "*mulsi_compare0_scratch"
1175  [(set (reg:CC_NOOV CC_REGNUM)
1176	(compare:CC_NOOV (mult:SI
1177			  (match_operand:SI 2 "s_register_operand" "r,r")
1178			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
1179			 (const_int 0)))
1180   (clobber (match_scratch:SI 0 "=&r,&r"))]
1181  "TARGET_ARM && !arm_arch_xscale"
1182  "mul%?s\\t%0, %2, %1"
1183  [(set_attr "conds" "set")
1184   (set_attr "type" "mult")]
1185)
1186
1187;; Unnamed templates to match MLA instruction.
1188
1189(define_insn "*mulsi3addsi"
1190  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1191	(plus:SI
1192	  (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1193		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1194	  (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1195  "TARGET_ARM"
1196  "mla%?\\t%0, %2, %1, %3"
1197  [(set_attr "type" "mult")
1198   (set_attr "predicable" "yes")]
1199)
1200
1201(define_insn "*mulsi3addsi_compare0"
1202  [(set (reg:CC_NOOV CC_REGNUM)
1203	(compare:CC_NOOV
1204	 (plus:SI (mult:SI
1205		   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1206		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1207		  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1208	 (const_int 0)))
1209   (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1210	(plus:SI (mult:SI (match_dup 2) (match_dup 1))
1211		 (match_dup 3)))]
1212  "TARGET_ARM && !arm_arch_xscale"
1213  "mla%?s\\t%0, %2, %1, %3"
1214  [(set_attr "conds" "set")
1215   (set_attr "type" "mult")]
1216)
1217
1218(define_insn "*mulsi3addsi_compare0_scratch"
1219  [(set (reg:CC_NOOV CC_REGNUM)
1220	(compare:CC_NOOV
1221	 (plus:SI (mult:SI
1222		   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1223		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1224		  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1225	 (const_int 0)))
1226   (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1227  "TARGET_ARM && !arm_arch_xscale"
1228  "mla%?s\\t%0, %2, %1, %3"
1229  [(set_attr "conds" "set")
1230   (set_attr "type" "mult")]
1231)
1232
1233;; Unnamed template to match long long multiply-accumulate (smlal)
1234
1235(define_insn "*mulsidi3adddi"
1236  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1237	(plus:DI
1238	 (mult:DI
1239	  (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1240	  (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1241	 (match_operand:DI 1 "s_register_operand" "0")))]
1242  "TARGET_ARM && arm_fast_multiply"
1243  "smlal%?\\t%Q0, %R0, %3, %2"
1244  [(set_attr "type" "mult")
1245   (set_attr "predicable" "yes")]
1246)
1247
1248(define_insn "mulsidi3"
1249  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1250	(mult:DI
1251	 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1252	 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1253  "TARGET_ARM && arm_fast_multiply"
1254  "smull%?\\t%Q0, %R0, %1, %2"
1255  [(set_attr "type" "mult")
1256   (set_attr "predicable" "yes")]
1257)
1258
1259(define_insn "umulsidi3"
1260  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1261	(mult:DI
1262	 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1263	 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1264  "TARGET_ARM && arm_fast_multiply"
1265  "umull%?\\t%Q0, %R0, %1, %2"
1266  [(set_attr "type" "mult")
1267   (set_attr "predicable" "yes")]
1268)
1269
1270;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1271
1272(define_insn "*umulsidi3adddi"
1273  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1274	(plus:DI
1275	 (mult:DI
1276	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1277	  (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1278	 (match_operand:DI 1 "s_register_operand" "0")))]
1279  "TARGET_ARM && arm_fast_multiply"
1280  "umlal%?\\t%Q0, %R0, %3, %2"
1281  [(set_attr "type" "mult")
1282   (set_attr "predicable" "yes")]
1283)
1284
1285(define_insn "smulsi3_highpart"
1286  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1287	(truncate:SI
1288	 (lshiftrt:DI
1289	  (mult:DI
1290	   (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1291	   (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1292	  (const_int 32))))
1293   (clobber (match_scratch:SI 3 "=&r,&r"))]
1294  "TARGET_ARM && arm_fast_multiply"
1295  "smull%?\\t%3, %0, %2, %1"
1296  [(set_attr "type" "mult")
1297   (set_attr "predicable" "yes")]
1298)
1299
1300(define_insn "umulsi3_highpart"
1301  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1302	(truncate:SI
1303	 (lshiftrt:DI
1304	  (mult:DI
1305	   (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1306	   (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1307	  (const_int 32))))
1308   (clobber (match_scratch:SI 3 "=&r,&r"))]
1309  "TARGET_ARM && arm_fast_multiply"
1310  "umull%?\\t%3, %0, %2, %1"
1311  [(set_attr "type" "mult")
1312   (set_attr "predicable" "yes")]
1313)
1314
1315(define_insn "mulhisi3"
1316  [(set (match_operand:SI 0 "s_register_operand" "=r")
1317	(mult:SI (sign_extend:SI
1318		  (match_operand:HI 1 "s_register_operand" "%r"))
1319		 (sign_extend:SI
1320		  (match_operand:HI 2 "s_register_operand" "r"))))]
1321  "TARGET_ARM && arm_arch5e"
1322  "smulbb%?\\t%0, %1, %2"
1323  [(set_attr "type" "mult")
1324   (set_attr "predicable" "yes")]
1325)
1326
1327(define_insn "*mulhisi3tb"
1328  [(set (match_operand:SI 0 "s_register_operand" "=r")
1329	(mult:SI (ashiftrt:SI
1330		  (match_operand:SI 1 "s_register_operand" "r")
1331		  (const_int 16))
1332		 (sign_extend:SI
1333		  (match_operand:HI 2 "s_register_operand" "r"))))]
1334  "TARGET_ARM && arm_arch5e"
1335  "smultb%?\\t%0, %1, %2"
1336  [(set_attr "type" "mult")
1337   (set_attr "predicable" "yes")]
1338)
1339
1340(define_insn "*mulhisi3bt"
1341  [(set (match_operand:SI 0 "s_register_operand" "=r")
1342	(mult:SI (sign_extend:SI
1343		  (match_operand:HI 1 "s_register_operand" "r"))
1344		 (ashiftrt:SI
1345		  (match_operand:SI 2 "s_register_operand" "r")
1346		  (const_int 16))))]
1347  "TARGET_ARM && arm_arch5e"
1348  "smulbt%?\\t%0, %1, %2"
1349  [(set_attr "type" "mult")
1350   (set_attr "predicable" "yes")]
1351)
1352
1353(define_insn "*mulhisi3tt"
1354  [(set (match_operand:SI 0 "s_register_operand" "=r")
1355	(mult:SI (ashiftrt:SI
1356		  (match_operand:SI 1 "s_register_operand" "r")
1357		  (const_int 16))
1358		 (ashiftrt:SI
1359		  (match_operand:SI 2 "s_register_operand" "r")
1360		  (const_int 16))))]
1361  "TARGET_ARM && arm_arch5e"
1362  "smultt%?\\t%0, %1, %2"
1363  [(set_attr "type" "mult")
1364   (set_attr "predicable" "yes")]
1365)
1366
1367(define_insn "*mulhisi3addsi"
1368  [(set (match_operand:SI 0 "s_register_operand" "=r")
1369	(plus:SI (match_operand:SI 1 "s_register_operand" "r")
1370		 (mult:SI (sign_extend:SI
1371			   (match_operand:HI 2 "s_register_operand" "%r"))
1372			  (sign_extend:SI
1373			   (match_operand:HI 3 "s_register_operand" "r")))))]
1374  "TARGET_ARM && arm_arch5e"
1375  "smlabb%?\\t%0, %2, %3, %1"
1376  [(set_attr "type" "mult")
1377   (set_attr "predicable" "yes")]
1378)
1379
1380(define_insn "*mulhidi3adddi"
1381  [(set (match_operand:DI 0 "s_register_operand" "=r")
1382	(plus:DI
1383	  (match_operand:DI 1 "s_register_operand" "0")
1384	  (mult:DI (sign_extend:DI
1385	 	    (match_operand:HI 2 "s_register_operand" "%r"))
1386		   (sign_extend:DI
1387		    (match_operand:HI 3 "s_register_operand" "r")))))]
1388  "TARGET_ARM && arm_arch5e"
1389  "smlalbb%?\\t%Q0, %R0, %2, %3"
1390  [(set_attr "type" "mult")
1391   (set_attr "predicable" "yes")])
1392
1393(define_expand "mulsf3"
1394  [(set (match_operand:SF          0 "s_register_operand" "")
1395	(mult:SF (match_operand:SF 1 "s_register_operand" "")
1396		 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1397  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1398  "
1399  if (TARGET_CIRRUS
1400      && !cirrus_fp_register (operands[2], SFmode))
1401    operands[2] = force_reg (SFmode, operands[2]);
1402")
1403
1404(define_expand "muldf3"
1405  [(set (match_operand:DF          0 "s_register_operand" "")
1406	(mult:DF (match_operand:DF 1 "s_register_operand" "")
1407		 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1408  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1409  "
1410  if (TARGET_CIRRUS
1411      && !cirrus_fp_register (operands[2], DFmode))
1412    operands[2] = force_reg (DFmode, operands[2]);
1413")
1414
1415;; Division insns
1416
1417(define_expand "divsf3"
1418  [(set (match_operand:SF 0 "s_register_operand" "")
1419	(div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1420		(match_operand:SF 2 "fpa_rhs_operand" "")))]
1421  "TARGET_ARM && TARGET_HARD_FLOAT"
1422  "")
1423
1424(define_expand "divdf3"
1425  [(set (match_operand:DF 0 "s_register_operand" "")
1426	(div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1427		(match_operand:DF 2 "fpa_rhs_operand" "")))]
1428  "TARGET_ARM && TARGET_HARD_FLOAT"
1429  "")
1430
1431;; Modulo insns
1432
1433(define_expand "modsf3"
1434  [(set (match_operand:SF 0 "s_register_operand" "")
1435	(mod:SF (match_operand:SF 1 "s_register_operand" "")
1436		(match_operand:SF 2 "fpa_rhs_operand" "")))]
1437  "TARGET_ARM && TARGET_HARD_FLOAT"
1438  "")
1439
1440(define_expand "moddf3"
1441  [(set (match_operand:DF 0 "s_register_operand" "")
1442	(mod:DF (match_operand:DF 1 "s_register_operand" "")
1443		(match_operand:DF 2 "fpa_rhs_operand" "")))]
1444  "TARGET_ARM && TARGET_HARD_FLOAT"
1445  "")
1446
1447;; Boolean and,ior,xor insns
1448
1449;; Split up double word logical operations
1450
1451;; Split up simple DImode logical operations.  Simply perform the logical
1452;; operation on the upper and lower halves of the registers.
1453(define_split
1454  [(set (match_operand:DI 0 "s_register_operand" "")
1455	(match_operator:DI 6 "logical_binary_operator"
1456	  [(match_operand:DI 1 "s_register_operand" "")
1457	   (match_operand:DI 2 "s_register_operand" "")]))]
1458  "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1459  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1460   (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1461  "
1462  {
1463    operands[3] = gen_highpart (SImode, operands[0]);
1464    operands[0] = gen_lowpart (SImode, operands[0]);
1465    operands[4] = gen_highpart (SImode, operands[1]);
1466    operands[1] = gen_lowpart (SImode, operands[1]);
1467    operands[5] = gen_highpart (SImode, operands[2]);
1468    operands[2] = gen_lowpart (SImode, operands[2]);
1469  }"
1470)
1471
1472(define_split
1473  [(set (match_operand:DI 0 "s_register_operand" "")
1474	(match_operator:DI 6 "logical_binary_operator"
1475	  [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1476	   (match_operand:DI 1 "s_register_operand" "")]))]
1477  "TARGET_ARM && reload_completed"
1478  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1479   (set (match_dup 3) (match_op_dup:SI 6
1480			[(ashiftrt:SI (match_dup 2) (const_int 31))
1481			 (match_dup 4)]))]
1482  "
1483  {
1484    operands[3] = gen_highpart (SImode, operands[0]);
1485    operands[0] = gen_lowpart (SImode, operands[0]);
1486    operands[4] = gen_highpart (SImode, operands[1]);
1487    operands[1] = gen_lowpart (SImode, operands[1]);
1488    operands[5] = gen_highpart (SImode, operands[2]);
1489    operands[2] = gen_lowpart (SImode, operands[2]);
1490  }"
1491)
1492
1493;; The zero extend of operand 2 means we can just copy the high part of
1494;; operand1 into operand0.
1495(define_split
1496  [(set (match_operand:DI 0 "s_register_operand" "")
1497	(ior:DI
1498	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1499	  (match_operand:DI 1 "s_register_operand" "")))]
1500  "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1501  [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1502   (set (match_dup 3) (match_dup 4))]
1503  "
1504  {
1505    operands[4] = gen_highpart (SImode, operands[1]);
1506    operands[3] = gen_highpart (SImode, operands[0]);
1507    operands[0] = gen_lowpart (SImode, operands[0]);
1508    operands[1] = gen_lowpart (SImode, operands[1]);
1509  }"
1510)
1511
1512;; The zero extend of operand 2 means we can just copy the high part of
1513;; operand1 into operand0.
1514(define_split
1515  [(set (match_operand:DI 0 "s_register_operand" "")
1516	(xor:DI
1517	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1518	  (match_operand:DI 1 "s_register_operand" "")))]
1519  "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1520  [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1521   (set (match_dup 3) (match_dup 4))]
1522  "
1523  {
1524    operands[4] = gen_highpart (SImode, operands[1]);
1525    operands[3] = gen_highpart (SImode, operands[0]);
1526    operands[0] = gen_lowpart (SImode, operands[0]);
1527    operands[1] = gen_lowpart (SImode, operands[1]);
1528  }"
1529)
1530
1531(define_insn "anddi3"
1532  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1533	(and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1534		(match_operand:DI 2 "s_register_operand"   "r,r")))]
1535  "TARGET_ARM && ! TARGET_IWMMXT"
1536  "#"
1537  [(set_attr "length" "8")]
1538)
1539
1540(define_insn_and_split "*anddi_zesidi_di"
1541  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1542	(and:DI (zero_extend:DI
1543		 (match_operand:SI 2 "s_register_operand" "r,r"))
1544		(match_operand:DI 1 "s_register_operand" "?r,0")))]
1545  "TARGET_ARM"
1546  "#"
1547  "TARGET_ARM && reload_completed"
1548  ; The zero extend of operand 2 clears the high word of the output
1549  ; operand.
1550  [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1551   (set (match_dup 3) (const_int 0))]
1552  "
1553  {
1554    operands[3] = gen_highpart (SImode, operands[0]);
1555    operands[0] = gen_lowpart (SImode, operands[0]);
1556    operands[1] = gen_lowpart (SImode, operands[1]);
1557  }"
1558  [(set_attr "length" "8")]
1559)
1560
1561(define_insn "*anddi_sesdi_di"
1562  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1563	(and:DI (sign_extend:DI
1564		 (match_operand:SI 2 "s_register_operand" "r,r"))
1565		(match_operand:DI  1 "s_register_operand" "?r,0")))]
1566  "TARGET_ARM"
1567  "#"
1568  [(set_attr "length" "8")]
1569)
1570
1571(define_expand "andsi3"
1572  [(set (match_operand:SI         0 "s_register_operand" "")
1573	(and:SI (match_operand:SI 1 "s_register_operand" "")
1574		(match_operand:SI 2 "reg_or_int_operand" "")))]
1575  "TARGET_EITHER"
1576  "
1577  if (TARGET_ARM)
1578    {
1579      if (GET_CODE (operands[2]) == CONST_INT)
1580        {
1581          arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1582			      operands[1],
1583			      (no_new_pseudos
1584			       ? 0 : preserve_subexpressions_p ()));
1585          DONE;
1586        }
1587    }
1588  else /* TARGET_THUMB */
1589    {
1590      if (GET_CODE (operands[2]) != CONST_INT)
1591        operands[2] = force_reg (SImode, operands[2]);
1592      else
1593        {
1594          int i;
1595	  
1596          if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1597  	    {
1598	      operands[2] = force_reg (SImode,
1599				       GEN_INT (~INTVAL (operands[2])));
1600	      
1601	      emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1602	      
1603	      DONE;
1604	    }
1605
1606          for (i = 9; i <= 31; i++)
1607	    {
1608	      if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1609	        {
1610	          emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1611			 	        const0_rtx));
1612	          DONE;
1613	        }
1614	      else if ((((HOST_WIDE_INT) 1) << i) - 1
1615		       == ~INTVAL (operands[2]))
1616	        {
1617	          rtx shift = GEN_INT (i);
1618	          rtx reg = gen_reg_rtx (SImode);
1619		
1620	          emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1621	          emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1622		  
1623	          DONE;
1624	        }
1625	    }
1626
1627          operands[2] = force_reg (SImode, operands[2]);
1628        }
1629    }
1630  "
1631)
1632
1633(define_insn_and_split "*arm_andsi3_insn"
1634  [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1635	(and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1636		(match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1637  "TARGET_ARM"
1638  "@
1639   and%?\\t%0, %1, %2
1640   bic%?\\t%0, %1, #%B2
1641   #"
1642  "TARGET_ARM
1643   && GET_CODE (operands[2]) == CONST_INT
1644   && !(const_ok_for_arm (INTVAL (operands[2]))
1645	|| const_ok_for_arm (~INTVAL (operands[2])))"
1646  [(clobber (const_int 0))]
1647  "
1648  arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1649		       operands[1], 0);
1650  DONE;
1651  "
1652  [(set_attr "length" "4,4,16")
1653   (set_attr "predicable" "yes")]
1654)
1655
1656(define_insn "*thumb_andsi3_insn"
1657  [(set (match_operand:SI         0 "register_operand" "=l")
1658	(and:SI (match_operand:SI 1 "register_operand" "%0")
1659		(match_operand:SI 2 "register_operand" "l")))]
1660  "TARGET_THUMB"
1661  "and\\t%0, %0, %2"
1662  [(set_attr "length" "2")]
1663)
1664
1665(define_insn "*andsi3_compare0"
1666  [(set (reg:CC_NOOV CC_REGNUM)
1667	(compare:CC_NOOV
1668	 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1669		 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1670	 (const_int 0)))
1671   (set (match_operand:SI          0 "s_register_operand" "=r,r")
1672	(and:SI (match_dup 1) (match_dup 2)))]
1673  "TARGET_ARM"
1674  "@
1675   and%?s\\t%0, %1, %2
1676   bic%?s\\t%0, %1, #%B2"
1677  [(set_attr "conds" "set")]
1678)
1679
1680(define_insn "*andsi3_compare0_scratch"
1681  [(set (reg:CC_NOOV CC_REGNUM)
1682	(compare:CC_NOOV
1683	 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1684		 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1685	 (const_int 0)))
1686   (clobber (match_scratch:SI 2 "=X,r"))]
1687  "TARGET_ARM"
1688  "@
1689   tst%?\\t%0, %1
1690   bic%?s\\t%2, %0, #%B1"
1691  [(set_attr "conds" "set")]
1692)
1693
1694(define_insn "*zeroextractsi_compare0_scratch"
1695  [(set (reg:CC_NOOV CC_REGNUM)
1696	(compare:CC_NOOV (zero_extract:SI
1697			  (match_operand:SI 0 "s_register_operand" "r")
1698		 	  (match_operand 1 "const_int_operand" "n")
1699			  (match_operand 2 "const_int_operand" "n"))
1700			 (const_int 0)))]
1701  "TARGET_ARM
1702  && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1703      && INTVAL (operands[1]) > 0 
1704      && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1705      && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1706  "*
1707  operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1708			 << INTVAL (operands[2]));
1709  output_asm_insn (\"tst%?\\t%0, %1\", operands);
1710  return \"\";
1711  "
1712  [(set_attr "conds" "set")]
1713)
1714
1715(define_insn "*ne_zeroextractsi"
1716  [(set (match_operand:SI 0 "s_register_operand" "=r")
1717	(ne:SI (zero_extract:SI
1718		(match_operand:SI 1 "s_register_operand" "r")
1719		(match_operand:SI 2 "const_int_operand" "n")
1720		(match_operand:SI 3 "const_int_operand" "n"))
1721	       (const_int 0)))
1722   (clobber (reg:CC CC_REGNUM))]
1723  "TARGET_ARM
1724   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1725       && INTVAL (operands[2]) > 0 
1726       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1727       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1728  "*
1729  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1730			 << INTVAL (operands[3]));
1731  output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1732  return \"movne\\t%0, #1\";
1733  "
1734  [(set_attr "conds" "clob")
1735   (set_attr "length" "8")]
1736)
1737
1738(define_split
1739  [(set (match_operand:SI 0 "s_register_operand" "")
1740	(zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1741			 (match_operand:SI 2 "const_int_operand" "")
1742			 (match_operand:SI 3 "const_int_operand" "")))
1743   (clobber (match_operand:SI 4 "s_register_operand" ""))]
1744  "TARGET_THUMB"
1745  [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1746   (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1747  "{
1748     HOST_WIDE_INT temp = INTVAL (operands[2]);
1749
1750     operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1751     operands[3] = GEN_INT (32 - temp);
1752   }"
1753)
1754
1755(define_split
1756  [(set (match_operand:SI 0 "s_register_operand" "")
1757	(match_operator:SI 1 "shiftable_operator"
1758	 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1759			   (match_operand:SI 3 "const_int_operand" "")
1760			   (match_operand:SI 4 "const_int_operand" ""))
1761	  (match_operand:SI 5 "s_register_operand" "")]))
1762   (clobber (match_operand:SI 6 "s_register_operand" ""))]
1763  "TARGET_ARM"
1764  [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1765   (set (match_dup 0)
1766	(match_op_dup 1
1767	 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1768	  (match_dup 5)]))]
1769  "{
1770     HOST_WIDE_INT temp = INTVAL (operands[3]);
1771
1772     operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1773     operands[4] = GEN_INT (32 - temp);
1774   }"
1775)
1776  
1777(define_split
1778  [(set (match_operand:SI 0 "s_register_operand" "")
1779	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1780			 (match_operand:SI 2 "const_int_operand" "")
1781			 (match_operand:SI 3 "const_int_operand" "")))]
1782  "TARGET_THUMB"
1783  [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1784   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1785  "{
1786     HOST_WIDE_INT temp = INTVAL (operands[2]);
1787
1788     operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1789     operands[3] = GEN_INT (32 - temp);
1790   }"
1791)
1792
1793(define_split
1794  [(set (match_operand:SI 0 "s_register_operand" "")
1795	(match_operator:SI 1 "shiftable_operator"
1796	 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1797			   (match_operand:SI 3 "const_int_operand" "")
1798			   (match_operand:SI 4 "const_int_operand" ""))
1799	  (match_operand:SI 5 "s_register_operand" "")]))
1800   (clobber (match_operand:SI 6 "s_register_operand" ""))]
1801  "TARGET_ARM"
1802  [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1803   (set (match_dup 0)
1804	(match_op_dup 1
1805	 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1806	  (match_dup 5)]))]
1807  "{
1808     HOST_WIDE_INT temp = INTVAL (operands[3]);
1809
1810     operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1811     operands[4] = GEN_INT (32 - temp);
1812   }"
1813)
1814  
1815;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1816;;; represented by the bitfield, then this will produce incorrect results.
1817;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1818;;; which have a real bit-field insert instruction, the truncation happens
1819;;; in the bit-field insert instruction itself.  Since arm does not have a
1820;;; bit-field insert instruction, we would have to emit code here to truncate
1821;;; the value before we insert.  This loses some of the advantage of having
1822;;; this insv pattern, so this pattern needs to be reevalutated.
1823
1824(define_expand "insv"
1825  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1826                         (match_operand:SI 1 "general_operand" "")
1827                         (match_operand:SI 2 "general_operand" ""))
1828        (match_operand:SI 3 "reg_or_int_operand" ""))]
1829  "TARGET_ARM"
1830  "
1831  {
1832    int start_bit = INTVAL (operands[2]);
1833    int width = INTVAL (operands[1]);
1834    HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1835    rtx target, subtarget;
1836
1837    target = operands[0];
1838    /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1839       subreg as the final target.  */
1840    if (GET_CODE (target) == SUBREG)
1841      {
1842	subtarget = gen_reg_rtx (SImode);
1843	if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1844	    < GET_MODE_SIZE (SImode))
1845	  target = SUBREG_REG (target);
1846      }
1847    else
1848      subtarget = target;    
1849
1850    if (GET_CODE (operands[3]) == CONST_INT)
1851      {
1852	/* Since we are inserting a known constant, we may be able to
1853	   reduce the number of bits that we have to clear so that
1854	   the mask becomes simple.  */
1855	/* ??? This code does not check to see if the new mask is actually
1856	   simpler.  It may not be.  */
1857	rtx op1 = gen_reg_rtx (SImode);
1858	/* ??? Truncate operand3 to fit in the bitfield.  See comment before
1859	   start of this pattern.  */
1860	HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1861	HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1862
1863	emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1864	emit_insn (gen_iorsi3 (subtarget, op1,
1865			       GEN_INT (op3_value << start_bit)));
1866      }
1867    else if (start_bit == 0
1868	     && !(const_ok_for_arm (mask)
1869		  || const_ok_for_arm (~mask)))
1870      {
1871	/* A Trick, since we are setting the bottom bits in the word,
1872	   we can shift operand[3] up, operand[0] down, OR them together
1873	   and rotate the result back again.  This takes 3 insns, and
1874	   the third might be mergeable into another op.  */
1875	/* The shift up copes with the possibility that operand[3] is
1876           wider than the bitfield.  */
1877	rtx op0 = gen_reg_rtx (SImode);
1878	rtx op1 = gen_reg_rtx (SImode);
1879
1880	emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1881	emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1882	emit_insn (gen_iorsi3  (op1, op1, op0));
1883	emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1884      }
1885    else if ((width + start_bit == 32)
1886	     && !(const_ok_for_arm (mask)
1887		  || const_ok_for_arm (~mask)))
1888      {
1889	/* Similar trick, but slightly less efficient.  */
1890
1891	rtx op0 = gen_reg_rtx (SImode);
1892	rtx op1 = gen_reg_rtx (SImode);
1893
1894	emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1895	emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1896	emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1897	emit_insn (gen_iorsi3 (subtarget, op1, op0));
1898      }
1899    else
1900      {
1901	rtx op0 = GEN_INT (mask);
1902	rtx op1 = gen_reg_rtx (SImode);
1903	rtx op2 = gen_reg_rtx (SImode);
1904
1905	if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1906	  {
1907	    rtx tmp = gen_reg_rtx (SImode);
1908
1909	    emit_insn (gen_movsi (tmp, op0));
1910	    op0 = tmp;
1911	  }
1912
1913	/* Mask out any bits in operand[3] that are not needed.  */
1914	   emit_insn (gen_andsi3 (op1, operands[3], op0));
1915
1916	if (GET_CODE (op0) == CONST_INT
1917	    && (const_ok_for_arm (mask << start_bit)
1918		|| const_ok_for_arm (~(mask << start_bit))))
1919	  {
1920	    op0 = GEN_INT (~(mask << start_bit));
1921	    emit_insn (gen_andsi3 (op2, operands[0], op0));
1922	  }
1923	else
1924	  {
1925	    if (GET_CODE (op0) == CONST_INT)
1926	      {
1927		rtx tmp = gen_reg_rtx (SImode);
1928
1929		emit_insn (gen_movsi (tmp, op0));
1930		op0 = tmp;
1931	      }
1932
1933	    if (start_bit != 0)
1934	      emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1935	    
1936	    emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1937	  }
1938
1939	if (start_bit != 0)
1940          emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1941
1942	emit_insn (gen_iorsi3 (subtarget, op1, op2));
1943      }
1944
1945    if (subtarget != target)
1946      {
1947	/* If TARGET is still a SUBREG, then it must be wider than a word,
1948	   so we must be careful only to set the subword we were asked to.  */
1949	if (GET_CODE (target) == SUBREG)
1950	  emit_move_insn (target, subtarget);
1951	else
1952	  emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1953      }
1954
1955    DONE;
1956  }"
1957)
1958
1959; constants for op 2 will never be given to these patterns.
1960(define_insn_and_split "*anddi_notdi_di"
1961  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1962	(and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1963		(match_operand:DI 2 "s_register_operand" "0,r")))]
1964  "TARGET_ARM"
1965  "#"
1966  "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1967  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1968   (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1969  "
1970  {
1971    operands[3] = gen_highpart (SImode, operands[0]);
1972    operands[0] = gen_lowpart (SImode, operands[0]);
1973    operands[4] = gen_highpart (SImode, operands[1]);
1974    operands[1] = gen_lowpart (SImode, operands[1]);
1975    operands[5] = gen_highpart (SImode, operands[2]);
1976    operands[2] = gen_lowpart (SImode, operands[2]);
1977  }"
1978  [(set_attr "length" "8")
1979   (set_attr "predicable" "yes")]
1980)
1981  
1982(define_insn_and_split "*anddi_notzesidi_di"
1983  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1984	(and:DI (not:DI (zero_extend:DI
1985			 (match_operand:SI 2 "s_register_operand" "r,r")))
1986		(match_operand:DI 1 "s_register_operand" "0,?r")))]
1987  "TARGET_ARM"
1988  "@
1989   bic%?\\t%Q0, %Q1, %2
1990   #"
1991  ; (not (zero_extend ...)) allows us to just copy the high word from
1992  ; operand1 to operand0.
1993  "TARGET_ARM
1994   && reload_completed
1995   && operands[0] != operands[1]"
1996  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1997   (set (match_dup 3) (match_dup 4))]
1998  "
1999  {
2000    operands[3] = gen_highpart (SImode, operands[0]);
2001    operands[0] = gen_lowpart (SImode, operands[0]);
2002    operands[4] = gen_highpart (SImode, operands[1]);
2003    operands[1] = gen_lowpart (SImode, operands[1]);
2004  }"
2005  [(set_attr "length" "4,8")
2006   (set_attr "predicable" "yes")]
2007)
2008  
2009(define_insn_and_split "*anddi_notsesidi_di"
2010  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2011	(and:DI (not:DI (sign_extend:DI
2012			 (match_operand:SI 2 "s_register_operand" "r,r")))
2013		(match_operand:DI 1 "s_register_operand" "0,r")))]
2014  "TARGET_ARM"
2015  "#"
2016  "TARGET_ARM && reload_completed"
2017  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2018   (set (match_dup 3) (and:SI (not:SI
2019				(ashiftrt:SI (match_dup 2) (const_int 31)))
2020			       (match_dup 4)))]
2021  "
2022  {
2023    operands[3] = gen_highpart (SImode, operands[0]);
2024    operands[0] = gen_lowpart (SImode, operands[0]);
2025    operands[4] = gen_highpart (SImode, operands[1]);
2026    operands[1] = gen_lowpart (SImode, operands[1]);
2027  }"
2028  [(set_attr "length" "8")
2029   (set_attr "predicable" "yes")]
2030)
2031  
2032(define_insn "andsi_notsi_si"
2033  [(set (match_operand:SI 0 "s_register_operand" "=r")
2034	(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2035		(match_operand:SI 1 "s_register_operand" "r")))]
2036  "TARGET_ARM"
2037  "bic%?\\t%0, %1, %2"
2038  [(set_attr "predicable" "yes")]
2039)
2040
2041(define_insn "bicsi3"
2042  [(set (match_operand:SI                 0 "register_operand" "=l")
2043	(and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2044		(match_operand:SI         2 "register_operand" "0")))]
2045  "TARGET_THUMB"
2046  "bic\\t%0, %0, %1"
2047  [(set_attr "length" "2")]
2048)
2049
2050(define_insn "andsi_not_shiftsi_si"
2051  [(set (match_operand:SI                   0 "s_register_operand" "=r")
2052	(and:SI (not:SI (match_operator:SI  4 "shift_operator"
2053			 [(match_operand:SI 2 "s_register_operand"  "r")
2054			  (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2055		(match_operand:SI           1 "s_register_operand"  "r")))]
2056  "TARGET_ARM"
2057  "bic%?\\t%0, %1, %2%S4"
2058  [(set_attr "predicable" "yes")
2059   (set_attr "shift" "2")
2060   ]
2061)
2062
2063(define_insn "*andsi_notsi_si_compare0"
2064  [(set (reg:CC_NOOV CC_REGNUM)
2065	(compare:CC_NOOV
2066	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2067		 (match_operand:SI 1 "s_register_operand" "r"))
2068	 (const_int 0)))
2069   (set (match_operand:SI 0 "s_register_operand" "=r")
2070	(and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2071  "TARGET_ARM"
2072  "bic%?s\\t%0, %1, %2"
2073  [(set_attr "conds" "set")]
2074)
2075
2076(define_insn "*andsi_notsi_si_compare0_scratch"
2077  [(set (reg:CC_NOOV CC_REGNUM)
2078	(compare:CC_NOOV
2079	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080		 (match_operand:SI 1 "s_register_operand" "r"))
2081	 (const_int 0)))
2082   (clobber (match_scratch:SI 0 "=r"))]
2083  "TARGET_ARM"
2084  "bic%?s\\t%0, %1, %2"
2085  [(set_attr "conds" "set")]
2086)
2087
2088(define_insn "iordi3"
2089  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2090	(ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2091		(match_operand:DI 2 "s_register_operand"   "r,r")))]
2092  "TARGET_ARM && ! TARGET_IWMMXT"
2093  "#"
2094  [(set_attr "length" "8")
2095   (set_attr "predicable" "yes")]
2096)
2097
2098(define_insn "*iordi_zesidi_di"
2099  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2100	(ior:DI (zero_extend:DI
2101		 (match_operand:SI 2 "s_register_operand" "r,r"))
2102		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2103  "TARGET_ARM"
2104  "@
2105   orr%?\\t%Q0, %Q1, %2
2106   #"
2107  [(set_attr "length" "4,8")
2108   (set_attr "predicable" "yes")]
2109)
2110
2111(define_insn "*iordi_sesidi_di"
2112  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2113	(ior:DI (sign_extend:DI
2114		 (match_operand:SI 2 "s_register_operand" "r,r"))
2115		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2116  "TARGET_ARM"
2117  "#"
2118  [(set_attr "length" "8")
2119   (set_attr "predicable" "yes")]
2120)
2121
2122(define_expand "iorsi3"
2123  [(set (match_operand:SI         0 "s_register_operand" "")
2124	(ior:SI (match_operand:SI 1 "s_register_operand" "")
2125		(match_operand:SI 2 "reg_or_int_operand" "")))]
2126  "TARGET_EITHER"
2127  "
2128  if (GET_CODE (operands[2]) == CONST_INT)
2129    {
2130      if (TARGET_ARM)
2131        {
2132          arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2133		 	      operands[1],
2134			      (no_new_pseudos
2135			      ? 0 : preserve_subexpressions_p ()));
2136          DONE;
2137	}
2138      else /* TARGET_THUMB */
2139	operands [2] = force_reg (SImode, operands [2]);
2140    }
2141  "
2142)
2143
2144(define_insn_and_split "*arm_iorsi3"
2145  [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2146	(ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2147		(match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2148  "TARGET_ARM"
2149  "@
2150   orr%?\\t%0, %1, %2
2151   #"
2152  "TARGET_ARM
2153   && GET_CODE (operands[2]) == CONST_INT
2154   && !const_ok_for_arm (INTVAL (operands[2]))"
2155  [(clobber (const_int 0))]
2156  "
2157  arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2158		      operands[1], 0);
2159  DONE;
2160  "
2161  [(set_attr "length" "4,16")
2162   (set_attr "predicable" "yes")]
2163)
2164
2165(define_insn "*thumb_iorsi3"
2166  [(set (match_operand:SI         0 "register_operand" "=l")
2167	(ior:SI (match_operand:SI 1 "register_operand" "%0")
2168		(match_operand:SI 2 "register_operand" "l")))]
2169  "TARGET_THUMB"
2170  "orr\\t%0, %0, %2"
2171  [(set_attr "length" "2")]
2172)
2173
2174(define_peephole2
2175  [(match_scratch:SI 3 "r")
2176   (set (match_operand:SI         0 "s_register_operand" "")
2177	(ior:SI (match_operand:SI 1 "s_register_operand" "")
2178		(match_operand:SI 2 "const_int_operand" "")))]
2179  "TARGET_ARM
2180   && !const_ok_for_arm (INTVAL (operands[2]))
2181   && const_ok_for_arm (~INTVAL (operands[2]))"
2182  [(set (match_dup 3) (match_dup 2))
2183   (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2184  ""
2185)
2186
2187(define_insn "*iorsi3_compare0"
2188  [(set (reg:CC_NOOV CC_REGNUM)
2189	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2190				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2191			 (const_int 0)))
2192   (set (match_operand:SI 0 "s_register_operand" "=r")
2193	(ior:SI (match_dup 1) (match_dup 2)))]
2194  "TARGET_ARM"
2195  "orr%?s\\t%0, %1, %2"
2196  [(set_attr "conds" "set")]
2197)
2198
2199(define_insn "*iorsi3_compare0_scratch"
2200  [(set (reg:CC_NOOV CC_REGNUM)
2201	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2202				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2203			 (const_int 0)))
2204   (clobber (match_scratch:SI 0 "=r"))]
2205  "TARGET_ARM"
2206  "orr%?s\\t%0, %1, %2"
2207  [(set_attr "conds" "set")]
2208)
2209
2210(define_insn "xordi3"
2211  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2212	(xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2213		(match_operand:DI 2 "s_register_operand"   "r,r")))]
2214  "TARGET_ARM && !TARGET_IWMMXT"
2215  "#"
2216  [(set_attr "length" "8")
2217   (set_attr "predicable" "yes")]
2218)
2219
2220(define_insn "*xordi_zesidi_di"
2221  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2222	(xor:DI (zero_extend:DI
2223		 (match_operand:SI 2 "s_register_operand" "r,r"))
2224		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2225  "TARGET_ARM"
2226  "@
2227   eor%?\\t%Q0, %Q1, %2
2228   #"
2229  [(set_attr "length" "4,8")
2230   (set_attr "predicable" "yes")]
2231)
2232
2233(define_insn "*xordi_sesidi_di"
2234  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2235	(xor:DI (sign_extend:DI
2236		 (match_operand:SI 2 "s_register_operand" "r,r"))
2237		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2238  "TARGET_ARM"
2239  "#"
2240  [(set_attr "length" "8")
2241   (set_attr "predicable" "yes")]
2242)
2243
2244(define_expand "xorsi3"
2245  [(set (match_operand:SI         0 "s_register_operand" "")
2246	(xor:SI (match_operand:SI 1 "s_register_operand" "")
2247		(match_operand:SI 2 "arm_rhs_operand"  "")))]
2248  "TARGET_EITHER"
2249  "if (TARGET_THUMB)
2250     if (GET_CODE (operands[2]) == CONST_INT)
2251       operands[2] = force_reg (SImode, operands[2]);
2252  "
2253)
2254
2255(define_insn "*arm_xorsi3"
2256  [(set (match_operand:SI         0 "s_register_operand" "=r")
2257	(xor:SI (match_operand:SI 1 "s_register_operand" "r")
2258		(match_operand:SI 2 "arm_rhs_operand" "rI")))]
2259  "TARGET_ARM"
2260  "eor%?\\t%0, %1, %2"
2261  [(set_attr "predicable" "yes")]
2262)
2263
2264(define_insn "*thumb_xorsi3"
2265  [(set (match_operand:SI         0 "register_operand" "=l")
2266	(xor:SI (match_operand:SI 1 "register_operand" "%0")
2267		(match_operand:SI 2 "register_operand" "l")))]
2268  "TARGET_THUMB"
2269  "eor\\t%0, %0, %2"
2270  [(set_attr "length" "2")]
2271)
2272
2273(define_insn "*xorsi3_compare0"
2274  [(set (reg:CC_NOOV CC_REGNUM)
2275	(compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2276				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2277			 (const_int 0)))
2278   (set (match_operand:SI 0 "s_register_operand" "=r")
2279	(xor:SI (match_dup 1) (match_dup 2)))]
2280  "TARGET_ARM"
2281  "eor%?s\\t%0, %1, %2"
2282  [(set_attr "conds" "set")]
2283)
2284
2285(define_insn "*xorsi3_compare0_scratch"
2286  [(set (reg:CC_NOOV CC_REGNUM)
2287	(compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2288				 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2289			 (const_int 0)))]
2290  "TARGET_ARM"
2291  "teq%?\\t%0, %1"
2292  [(set_attr "conds" "set")]
2293)
2294
2295; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2296; (NOT D) we can sometimes merge the final NOT into one of the following
2297; insns.
2298
2299(define_split
2300  [(set (match_operand:SI 0 "s_register_operand" "")
2301	(ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2302			(not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2303		(match_operand:SI 3 "arm_rhs_operand" "")))
2304   (clobber (match_operand:SI 4 "s_register_operand" ""))]
2305  "TARGET_ARM"
2306  [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2307			      (not:SI (match_dup 3))))
2308   (set (match_dup 0) (not:SI (match_dup 4)))]
2309  ""
2310)
2311
2312(define_insn "*andsi_iorsi3_notsi"
2313  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2314	(and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2315			(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2316		(not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2317  "TARGET_ARM"
2318  "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2319  [(set_attr "length" "8")
2320   (set_attr "predicable" "yes")]
2321)
2322
2323(define_split
2324  [(set (match_operand:SI 0 "s_register_operand" "")
2325	(match_operator:SI 1 "logical_binary_operator"
2326	 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2327			   (match_operand:SI 3 "const_int_operand" "")
2328			   (match_operand:SI 4 "const_int_operand" ""))
2329	  (match_operator:SI 9 "logical_binary_operator"
2330	   [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2331			 (match_operand:SI 6 "const_int_operand" ""))
2332	    (match_operand:SI 7 "s_register_operand" "")])]))
2333   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2334  "TARGET_ARM
2335   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2336   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2337  [(set (match_dup 8)
2338	(match_op_dup 1
2339	 [(ashift:SI (match_dup 2) (match_dup 4))
2340	  (match_dup 5)]))
2341   (set (match_dup 0)
2342	(match_op_dup 1
2343	 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2344	  (match_dup 7)]))]
2345  "
2346  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2347")
2348
2349(define_split
2350  [(set (match_operand:SI 0 "s_register_operand" "")
2351	(match_operator:SI 1 "logical_binary_operator"
2352	 [(match_operator:SI 9 "logical_binary_operator"
2353	   [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2354			 (match_operand:SI 6 "const_int_operand" ""))
2355	    (match_operand:SI 7 "s_register_operand" "")])
2356	  (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2357			   (match_operand:SI 3 "const_int_operand" "")
2358			   (match_operand:SI 4 "const_int_operand" ""))]))
2359   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2360  "TARGET_ARM
2361   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2362   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2363  [(set (match_dup 8)
2364	(match_op_dup 1
2365	 [(ashift:SI (match_dup 2) (match_dup 4))
2366	  (match_dup 5)]))
2367   (set (match_dup 0)
2368	(match_op_dup 1
2369	 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2370	  (match_dup 7)]))]
2371  "
2372  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2373")
2374
2375(define_split
2376  [(set (match_operand:SI 0 "s_register_operand" "")
2377	(match_operator:SI 1 "logical_binary_operator"
2378	 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2379			   (match_operand:SI 3 "const_int_operand" "")
2380			   (match_operand:SI 4 "const_int_operand" ""))
2381	  (match_operator:SI 9 "logical_binary_operator"
2382	   [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2383			 (match_operand:SI 6 "const_int_operand" ""))
2384	    (match_operand:SI 7 "s_register_operand" "")])]))
2385   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2386  "TARGET_ARM
2387   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2388   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2389  [(set (match_dup 8)
2390	(match_op_dup 1
2391	 [(ashift:SI (match_dup 2) (match_dup 4))
2392	  (match_dup 5)]))
2393   (set (match_dup 0)
2394	(match_op_dup 1
2395	 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2396	  (match_dup 7)]))]
2397  "
2398  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2399")
2400
2401(define_split
2402  [(set (match_operand:SI 0 "s_register_operand" "")
2403	(match_operator:SI 1 "logical_binary_operator"
2404	 [(match_operator:SI 9 "logical_binary_operator"
2405	   [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2406			 (match_operand:SI 6 "const_int_operand" ""))
2407	    (match_operand:SI 7 "s_register_operand" "")])
2408	  (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2409			   (match_operand:SI 3 "const_int_operand" "")
2410			   (match_operand:SI 4 "const_int_operand" ""))]))
2411   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2412  "TARGET_ARM
2413   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2414   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2415  [(set (match_dup 8)
2416	(match_op_dup 1
2417	 [(ashift:SI (match_dup 2) (match_dup 4))
2418	  (match_dup 5)]))
2419   (set (match_dup 0)
2420	(match_op_dup 1
2421	 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2422	  (match_dup 7)]))]
2423  "
2424  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2425")
2426
2427
2428;; Minimum and maximum insns
2429
2430(define_insn "smaxsi3"
2431  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2432	(smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2433		 (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2434   (clobber (reg:CC CC_REGNUM))]
2435  "TARGET_ARM"
2436  "@
2437   cmp\\t%1, %2\;movlt\\t%0, %2
2438   cmp\\t%1, %2\;movge\\t%0, %1
2439   cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2440  [(set_attr "conds" "clob")
2441   (set_attr "length" "8,8,12")]
2442)
2443
2444(define_insn "sminsi3"
2445  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2446	(smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2447		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2448   (clobber (reg:CC CC_REGNUM))]
2449  "TARGET_ARM"
2450  "@
2451   cmp\\t%1, %2\;movge\\t%0, %2
2452   cmp\\t%1, %2\;movlt\\t%0, %1
2453   cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2454  [(set_attr "conds" "clob")
2455   (set_attr "length" "8,8,12")]
2456)
2457
2458(define_insn "umaxsi3"
2459  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2460	(umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2461		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2462   (clobber (reg:CC CC_REGNUM))]
2463  "TARGET_ARM"
2464  "@
2465   cmp\\t%1, %2\;movcc\\t%0, %2
2466   cmp\\t%1, %2\;movcs\\t%0, %1
2467   cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2468  [(set_attr "conds" "clob")
2469   (set_attr "length" "8,8,12")]
2470)
2471
2472(define_insn "uminsi3"
2473  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2474	(umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2475		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2476   (clobber (reg:CC CC_REGNUM))]
2477  "TARGET_ARM"
2478  "@
2479   cmp\\t%1, %2\;movcs\\t%0, %2
2480   cmp\\t%1, %2\;movcc\\t%0, %1
2481   cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2482  [(set_attr "conds" "clob")
2483   (set_attr "length" "8,8,12")]
2484)
2485
2486(define_insn "*store_minmaxsi"
2487  [(set (match_operand:SI 0 "memory_operand" "=m")
2488	(match_operator:SI 3 "minmax_operator"
2489	 [(match_operand:SI 1 "s_register_operand" "r")
2490	  (match_operand:SI 2 "s_register_operand" "r")]))
2491   (clobber (reg:CC CC_REGNUM))]
2492  "TARGET_ARM"
2493  "*
2494  operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2495			 operands[2]);
2496  output_asm_insn (\"cmp\\t%1, %2\", operands);
2497  output_asm_insn (\"str%d3\\t%1, %0\", operands);
2498  output_asm_insn (\"str%D3\\t%2, %0\", operands);
2499  return \"\";
2500  "
2501  [(set_attr "conds" "clob")
2502   (set_attr "length" "12")
2503   (set_attr "type" "store1")]
2504)
2505
2506; Reject the frame pointer in operand[1], since reloading this after
2507; it has been eliminated can cause carnage.
2508(define_insn "*minmax_arithsi"
2509  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2510	(match_operator:SI 4 "shiftable_operator"
2511	 [(match_operator:SI 5 "minmax_operator"
2512	   [(match_operand:SI 2 "s_register_operand" "r,r")
2513	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2514	  (match_operand:SI 1 "s_register_operand" "0,?r")]))
2515   (clobber (reg:CC CC_REGNUM))]
2516  "TARGET_ARM
2517   && (GET_CODE (operands[1]) != REG
2518       || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2519           && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2520  "*
2521  {
2522    enum rtx_code code = GET_CODE (operands[4]);
2523
2524    operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2525			   operands[3]);
2526    output_asm_insn (\"cmp\\t%2, %3\", operands);
2527    output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2528    if (which_alternative != 0 || operands[3] != const0_rtx
2529        || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2530      output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2531    return \"\";
2532  }"
2533  [(set_attr "conds" "clob")
2534   (set_attr "length" "12")]
2535)
2536
2537
2538;; Shift and rotation insns
2539
2540(define_expand "ashlsi3"
2541  [(set (match_operand:SI            0 "s_register_operand" "")
2542	(ashift:SI (match_operand:SI 1 "s_register_operand" "")
2543		   (match_operand:SI 2 "arm_rhs_operand" "")))]
2544  "TARGET_EITHER"
2545  "
2546  if (GET_CODE (operands[2]) == CONST_INT
2547      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2548    {
2549      emit_insn (gen_movsi (operands[0], const0_rtx));
2550      DONE;
2551    }
2552  "
2553)
2554
2555(define_insn "*thumb_ashlsi3"
2556  [(set (match_operand:SI            0 "register_operand" "=l,l")
2557	(ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2558		   (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2559  "TARGET_THUMB"
2560  "lsl\\t%0, %1, %2"
2561  [(set_attr "length" "2")]
2562)
2563
2564(define_expand "ashrsi3"
2565  [(set (match_operand:SI              0 "s_register_operand" "")
2566	(ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2567		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2568  "TARGET_EITHER"
2569  "
2570  if (GET_CODE (operands[2]) == CONST_INT
2571      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2572    operands[2] = GEN_INT (31);
2573  "
2574)
2575
2576(define_insn "*thumb_ashrsi3"
2577  [(set (match_operand:SI              0 "register_operand" "=l,l")
2578	(ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2579		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2580  "TARGET_THUMB"
2581  "asr\\t%0, %1, %2"
2582  [(set_attr "length" "2")]
2583)
2584
2585(define_expand "lshrsi3"
2586  [(set (match_operand:SI              0 "s_register_operand" "")
2587	(lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2588		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2589  "TARGET_EITHER"
2590  "
2591  if (GET_CODE (operands[2]) == CONST_INT
2592      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2593    {
2594      emit_insn (gen_movsi (operands[0], const0_rtx));
2595      DONE;
2596    }
2597  "
2598)
2599
2600(define_insn "*thumb_lshrsi3"
2601  [(set (match_operand:SI              0 "register_operand" "=l,l")
2602	(lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2603		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2604  "TARGET_THUMB"
2605  "lsr\\t%0, %1, %2"
2606  [(set_attr "length" "2")]
2607)
2608
2609(define_expand "rotlsi3"
2610  [(set (match_operand:SI              0 "s_register_operand" "")
2611	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2612		     (match_operand:SI 2 "reg_or_int_operand" "")))]
2613  "TARGET_ARM"
2614  "
2615  if (GET_CODE (operands[2]) == CONST_INT)
2616    operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2617  else
2618    {
2619      rtx reg = gen_reg_rtx (SImode);
2620      emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2621      operands[2] = reg;
2622    }
2623  "
2624)
2625
2626(define_expand "rotrsi3"
2627  [(set (match_operand:SI              0 "s_register_operand" "")
2628	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2629		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2630  "TARGET_EITHER"
2631  "
2632  if (TARGET_ARM)
2633    {
2634      if (GET_CODE (operands[2]) == CONST_INT
2635          && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2636        operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2637    }
2638  else /* TARGET_THUMB */
2639    {
2640      if (GET_CODE (operands [2]) == CONST_INT)
2641        operands [2] = force_reg (SImode, operands[2]);
2642    }
2643  "
2644)
2645
2646(define_insn "*thumb_rotrsi3"
2647  [(set (match_operand:SI              0 "register_operand" "=l")
2648	(rotatert:SI (match_operand:SI 1 "register_operand" "0")
2649		     (match_operand:SI 2 "register_operand" "l")))]
2650  "TARGET_THUMB"
2651  "ror\\t%0, %0, %2"
2652  [(set_attr "length" "2")]
2653)
2654
2655(define_expand "ashldi3"
2656  [(set (match_operand:DI            0 "s_register_operand" "")
2657	(ashift:DI (match_operand:DI 1 "general_operand"    "")
2658		   (match_operand:SI 2 "general_operand"    "")))]
2659  "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
2660  "
2661  if (! s_register_operand (operands[1], DImode))
2662    operands[1] = copy_to_mode_reg (DImode, operands[1]);
2663  if (! s_register_operand (operands[2], SImode))
2664    operands[2] = copy_to_mode_reg (SImode, operands[2]);
2665  "
2666)
2667
2668(define_insn "*arm_shiftsi3"
2669  [(set (match_operand:SI   0 "s_register_operand" "=r")
2670	(match_operator:SI  3 "shift_operator"
2671	 [(match_operand:SI 1 "s_register_operand"  "r")
2672	  (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2673  "TARGET_ARM"
2674  "mov%?\\t%0, %1%S3"
2675  [(set_attr "predicable" "yes")
2676   (set_attr "shift" "1")
2677   ]
2678)
2679
2680(define_insn "*shiftsi3_compare0"
2681  [(set (reg:CC_NOOV CC_REGNUM)
2682	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2683			  [(match_operand:SI 1 "s_register_operand" "r")
2684			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
2685			 (const_int 0)))
2686   (set (match_operand:SI 0 "s_register_operand" "=r")
2687	(match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2688  "TARGET_ARM"
2689  "mov%?s\\t%0, %1%S3"
2690  [(set_attr "conds" "set")
2691   (set_attr "shift" "1")
2692   ]
2693)
2694
2695(define_insn "*shiftsi3_compare0_scratch"
2696  [(set (reg:CC_NOOV CC_REGNUM)
2697	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2698			  [(match_operand:SI 1 "s_register_operand" "r")
2699			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
2700			 (const_int 0)))
2701   (clobber (match_scratch:SI 0 "=r"))]
2702  "TARGET_ARM"
2703  "mov%?s\\t%0, %1%S3"
2704  [(set_attr "conds" "set")
2705   (set_attr "shift" "1")
2706   ]
2707)
2708
2709(define_insn "*notsi_shiftsi"
2710  [(set (match_operand:SI 0 "s_register_operand" "=r")
2711	(not:SI (match_operator:SI 3 "shift_operator"
2712		 [(match_operand:SI 1 "s_register_operand" "r")
2713		  (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2714  "TARGET_ARM"
2715  "mvn%?\\t%0, %1%S3"
2716  [(set_attr "predicable" "yes")
2717   (set_attr "shift" "1")
2718   ]
2719)
2720
2721(define_insn "*notsi_shiftsi_compare0"
2722  [(set (reg:CC_NOOV CC_REGNUM)
2723	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2724			  [(match_operand:SI 1 "s_register_operand" "r")
2725			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2726			 (const_int 0)))
2727   (set (match_operand:SI 0 "s_register_operand" "=r")
2728	(not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2729  "TARGET_ARM"
2730  "mvn%?s\\t%0, %1%S3"
2731  [(set_attr "conds" "set")
2732   (set_attr "shift" "1")
2733   ]
2734)
2735
2736(define_insn "*not_shiftsi_compare0_scratch"
2737  [(set (reg:CC_NOOV CC_REGNUM)
2738	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2739			  [(match_operand:SI 1 "s_register_operand" "r")
2740			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2741			 (const_int 0)))
2742   (clobber (match_scratch:SI 0 "=r"))]
2743  "TARGET_ARM"
2744  "mvn%?s\\t%0, %1%S3"
2745  [(set_attr "conds" "set")
2746   (set_attr "shift" "1")
2747  ]
2748)
2749
2750;; We don't really have extzv, but defining this using shifts helps
2751;; to reduce register pressure later on.
2752
2753(define_expand "extzv"
2754  [(set (match_dup 4)
2755	(ashift:SI (match_operand:SI   1 "register_operand" "")
2756		   (match_operand:SI   2 "const_int_operand" "")))
2757   (set (match_operand:SI              0 "register_operand" "")
2758	(lshiftrt:SI (match_dup 4)
2759		     (match_operand:SI 3 "const_int_operand" "")))]
2760  "TARGET_THUMB"
2761  "
2762  {
2763    HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2764    HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2765    
2766    operands[3] = GEN_INT (rshift);
2767    
2768    if (lshift == 0)
2769      {
2770        emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2771        DONE;
2772      }
2773      
2774    operands[2] = GEN_INT (lshift);
2775    operands[4] = gen_reg_rtx (SImode);
2776  }"
2777)
2778
2779
2780;; Unary arithmetic insns
2781
2782(define_expand "negdi2"
2783 [(parallel
2784   [(set (match_operand:DI          0 "s_register_operand" "")
2785	  (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2786    (clobber (reg:CC CC_REGNUM))])]
2787  "TARGET_EITHER"
2788  "
2789  if (TARGET_THUMB)
2790    {
2791      if (GET_CODE (operands[1]) != REG)
2792        operands[1] = force_reg (SImode, operands[1]);
2793     }
2794  "
2795)
2796
2797;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2798;; The second alternative is to allow the common case of a *full* overlap.
2799(define_insn "*arm_negdi2"
2800  [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2801	(neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2802   (clobber (reg:CC CC_REGNUM))]
2803  "TARGET_ARM"
2804  "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2805  [(set_attr "conds" "clob")
2806   (set_attr "length" "8")]
2807)
2808
2809(define_insn "*thumb_negdi2"
2810  [(set (match_operand:DI         0 "register_operand" "=&l")
2811	(neg:DI (match_operand:DI 1 "register_operand"   "l")))
2812   (clobber (reg:CC CC_REGNUM))]
2813  "TARGET_THUMB"
2814  "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2815  [(set_attr "length" "6")]
2816)
2817
2818(define_expand "negsi2"
2819  [(set (match_operand:SI         0 "s_register_operand" "")
2820	(neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2821  "TARGET_EITHER"
2822  ""
2823)
2824
2825(define_insn "*arm_negsi2"
2826  [(set (match_operand:SI         0 "s_register_operand" "=r")
2827	(neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2828  "TARGET_ARM"
2829  "rsb%?\\t%0, %1, #0"
2830  [(set_attr "predicable" "yes")]
2831)
2832
2833(define_insn "*thumb_negsi2"
2834  [(set (match_operand:SI         0 "register_operand" "=l")
2835	(neg:SI (match_operand:SI 1 "register_operand" "l")))]
2836  "TARGET_THUMB"
2837  "neg\\t%0, %1"
2838  [(set_attr "length" "2")]
2839)
2840
2841(define_expand "negsf2"
2842  [(set (match_operand:SF         0 "s_register_operand" "")
2843	(neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2844  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2845  ""
2846)
2847
2848(define_expand "negdf2"
2849  [(set (match_operand:DF         0 "s_register_operand" "")
2850	(neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2851  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2852  "")
2853
2854;; abssi2 doesn't really clobber the condition codes if a different register
2855;; is being set.  To keep things simple, assume during rtl manipulations that
2856;; it does, but tell the final scan operator the truth.  Similarly for
2857;; (neg (abs...))
2858
2859(define_expand "abssi2"
2860  [(parallel
2861    [(set (match_operand:SI         0 "s_register_operand" "")
2862	  (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2863     (clobber (reg:CC CC_REGNUM))])]
2864  "TARGET_ARM"
2865  "")
2866
2867(define_insn "*arm_abssi2"
2868  [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2869	(abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2870   (clobber (reg:CC CC_REGNUM))]
2871  "TARGET_ARM"
2872  "@
2873   cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2874   eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2875  [(set_attr "conds" "clob,*")
2876   (set_attr "shift" "1")
2877   ;; predicable can't be set based on the variant, so left as no
2878   (set_attr "length" "8")]
2879)
2880
2881(define_insn "*neg_abssi2"
2882  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2883	(neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2884   (clobber (reg:CC CC_REGNUM))]
2885  "TARGET_ARM"
2886  "@
2887   cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2888   eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2889  [(set_attr "conds" "clob,*")
2890   (set_attr "shift" "1")
2891   ;; predicable can't be set based on the variant, so left as no
2892   (set_attr "length" "8")]
2893)
2894
2895(define_expand "abssf2"
2896  [(set (match_operand:SF         0 "s_register_operand" "")
2897	(abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2898  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2899  "")
2900
2901(define_expand "absdf2"
2902  [(set (match_operand:DF         0 "s_register_operand" "")
2903	(abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2904  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2905  "")
2906
2907(define_expand "sqrtsf2"
2908  [(set (match_operand:SF 0 "s_register_operand" "")
2909	(sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2910  "TARGET_ARM && TARGET_HARD_FLOAT"
2911  "")
2912
2913(define_expand "sqrtdf2"
2914  [(set (match_operand:DF 0 "s_register_operand" "")
2915	(sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2916  "TARGET_ARM && TARGET_HARD_FLOAT"
2917  "")
2918
2919(define_insn_and_split "one_cmpldi2"
2920  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2921	(not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2922  "TARGET_ARM"
2923  "#"
2924  "TARGET_ARM && reload_completed"
2925  [(set (match_dup 0) (not:SI (match_dup 1)))
2926   (set (match_dup 2) (not:SI (match_dup 3)))]
2927  "
2928  {
2929    operands[2] = gen_highpart (SImode, operands[0]);
2930    operands[0] = gen_lowpart (SImode, operands[0]);
2931    operands[3] = gen_highpart (SImode, operands[1]);
2932    operands[1] = gen_lowpart (SImode, operands[1]);
2933  }"
2934  [(set_attr "length" "8")
2935   (set_attr "predicable" "yes")]
2936)
2937
2938(define_expand "one_cmplsi2"
2939  [(set (match_operand:SI         0 "s_register_operand" "")
2940	(not:SI (match_operand:SI 1 "s_register_operand" "")))]
2941  "TARGET_EITHER"
2942  ""
2943)
2944
2945(define_insn "*arm_one_cmplsi2"
2946  [(set (match_operand:SI         0 "s_register_operand" "=r")
2947	(not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2948  "TARGET_ARM"
2949  "mvn%?\\t%0, %1"
2950  [(set_attr "predicable" "yes")]
2951)
2952
2953(define_insn "*thumb_one_cmplsi2"
2954  [(set (match_operand:SI         0 "register_operand" "=l")
2955	(not:SI (match_operand:SI 1 "register_operand"  "l")))]
2956  "TARGET_THUMB"
2957  "mvn\\t%0, %1"
2958  [(set_attr "length" "2")]
2959)
2960
2961(define_insn "*notsi_compare0"
2962  [(set (reg:CC_NOOV CC_REGNUM)
2963	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2964			 (const_int 0)))
2965   (set (match_operand:SI 0 "s_register_operand" "=r")
2966	(not:SI (match_dup 1)))]
2967  "TARGET_ARM"
2968  "mvn%?s\\t%0, %1"
2969  [(set_attr "conds" "set")]
2970)
2971
2972(define_insn "*notsi_compare0_scratch"
2973  [(set (reg:CC_NOOV CC_REGNUM)
2974	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2975			 (const_int 0)))
2976   (clobber (match_scratch:SI 0 "=r"))]
2977  "TARGET_ARM"
2978  "mvn%?s\\t%0, %1"
2979  [(set_attr "conds" "set")]
2980)
2981
2982;; Fixed <--> Floating conversion insns
2983
2984(define_expand "floatsisf2"
2985  [(set (match_operand:SF           0 "s_register_operand" "")
2986	(float:SF (match_operand:SI 1 "s_register_operand" "")))]
2987  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2988  "
2989  if (TARGET_CIRRUS)
2990    {
2991      emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2992      DONE;
2993    }
2994")
2995
2996(define_expand "floatsidf2"
2997  [(set (match_operand:DF           0 "s_register_operand" "")
2998	(float:DF (match_operand:SI 1 "s_register_operand" "")))]
2999  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3000  "
3001  if (TARGET_CIRRUS)
3002    {
3003      emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3004      DONE;
3005    }
3006")
3007
3008(define_expand "fix_truncsfsi2"
3009  [(set (match_operand:SI         0 "s_register_operand" "")
3010	(fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3011  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3012  "
3013  if (TARGET_CIRRUS)
3014    {
3015      if (!cirrus_fp_register (operands[0], SImode))
3016        operands[0] = force_reg (SImode, operands[0]);
3017      if (!cirrus_fp_register (operands[1], SFmode))
3018        operands[1] = force_reg (SFmode, operands[0]);
3019      emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3020      DONE;
3021    }
3022")
3023
3024(define_expand "fix_truncdfsi2"
3025  [(set (match_operand:SI         0 "s_register_operand" "")
3026	(fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3027  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3028  "
3029  if (TARGET_CIRRUS)
3030    {
3031      if (!cirrus_fp_register (operands[1], DFmode))
3032        operands[1] = force_reg (DFmode, operands[0]);
3033      emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3034      DONE;
3035    }
3036")
3037
3038;; Truncation insns
3039
3040(define_expand "truncdfsf2"
3041  [(set (match_operand:SF  0 "s_register_operand" "")
3042	(float_truncate:SF
3043 	 (match_operand:DF 1 "s_register_operand" "")))]
3044  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3045  ""
3046)
3047
3048;; Zero and sign extension instructions.
3049
3050(define_insn "zero_extendsidi2"
3051  [(set (match_operand:DI 0 "s_register_operand" "=r")
3052        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3053  "TARGET_ARM"
3054  "*
3055    if (REGNO (operands[1])
3056        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3057      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3058    return \"mov%?\\t%R0, #0\";
3059  "
3060  [(set_attr "length" "8")
3061   (set_attr "predicable" "yes")]
3062)
3063
3064(define_insn "zero_extendqidi2"
3065  [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3066	(zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3067  "TARGET_ARM"
3068  "@
3069   and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3070   ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3071  [(set_attr "length" "8")
3072   (set_attr "predicable" "yes")
3073   (set_attr "type" "*,load")
3074   (set_attr "pool_range" "*,4092")
3075   (set_attr "neg_pool_range" "*,4084")]
3076)
3077
3078(define_insn "extendsidi2"
3079  [(set (match_operand:DI 0 "s_register_operand" "=r")
3080        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3081  "TARGET_ARM"
3082  "*
3083    if (REGNO (operands[1])
3084        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3085      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3086    return \"mov%?\\t%R0, %Q0, asr #31\";
3087  "
3088  [(set_attr "length" "8")
3089   (set_attr "shift" "1")
3090   (set_attr "predicable" "yes")]
3091)
3092
3093(define_expand "zero_extendhisi2"
3094  [(set (match_dup 2)
3095	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3096		   (const_int 16)))
3097   (set (match_operand:SI 0 "s_register_operand" "")
3098	(lshiftrt:SI (match_dup 2) (const_int 16)))]
3099  "TARGET_EITHER"
3100  "
3101  {
3102    if (TARGET_ARM)
3103      {
3104        if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3105          {
3106           /* Note: We do not have to worry about TARGET_MMU_TRAPS
3107	      here because the insn below will generate an LDRH instruction
3108	      rather than an LDR instruction, so we cannot get an unaligned
3109	      word access.  */
3110            emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3111			            gen_rtx_ZERO_EXTEND (SImode,
3112							 operands[1])));
3113            DONE;
3114          }
3115        if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3116          {
3117            emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3118            DONE;
3119          }
3120        if (!s_register_operand (operands[1], HImode))
3121          operands[1] = copy_to_mode_reg (HImode, operands[1]);
3122        operands[1] = gen_lowpart (SImode, operands[1]);
3123        operands[2] = gen_reg_rtx (SImode);
3124      }
3125    else /* TARGET_THUMB */
3126      {
3127        if (GET_CODE (operands[1]) == MEM)
3128	  {
3129	    rtx tmp;
3130
3131	    tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3132	    tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3133	    emit_insn (tmp);
3134	  }
3135	else
3136	  {
3137	    rtx ops[3];
3138	    
3139	    if (!s_register_operand (operands[1], HImode))
3140	      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3141	    operands[1] = gen_lowpart (SImode, operands[1]);
3142	    operands[2] = gen_reg_rtx (SImode);
3143	    
3144	    ops[0] = operands[2];
3145	    ops[1] = operands[1];
3146	    ops[2] = GEN_INT (16);
3147	    
3148	    emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3149				    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3150
3151	    ops[0] = operands[0];
3152	    ops[1] = operands[2];
3153	    ops[2] = GEN_INT (16);
3154
3155	    emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3156				    gen_rtx_LSHIFTRT (SImode, ops[1],
3157						      ops[2])));
3158	  }
3159	DONE; 
3160      }
3161  }"
3162)
3163
3164(define_insn "*thumb_zero_extendhisi2"
3165  [(set (match_operand:SI                 0 "register_operand" "=l")
3166	(zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3167  "TARGET_THUMB"
3168  "*
3169  rtx mem = XEXP (operands[1], 0);
3170
3171  if (GET_CODE (mem) == CONST)
3172    mem = XEXP (mem, 0);
3173    
3174  if (GET_CODE (mem) == LABEL_REF)
3175    return \"ldr\\t%0, %1\";
3176    
3177  if (GET_CODE (mem) == PLUS)
3178    {
3179      rtx a = XEXP (mem, 0);
3180      rtx b = XEXP (mem, 1);
3181
3182      /* This can happen due to bugs in reload.  */
3183      if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3184        {
3185          rtx ops[2];
3186          ops[0] = operands[0];
3187          ops[1] = a;
3188      
3189          output_asm_insn (\"mov	%0, %1\", ops);
3190
3191          XEXP (mem, 0) = operands[0];
3192       }
3193
3194      else if (   GET_CODE (a) == LABEL_REF
3195	       && GET_CODE (b) == CONST_INT)
3196        return \"ldr\\t%0, %1\";
3197    }
3198    
3199  return \"ldrh\\t%0, %1\";
3200  "
3201  [(set_attr "length" "4")
3202   (set_attr "type" "load")
3203   (set_attr "pool_range" "60")]
3204)
3205
3206(define_insn "*arm_zero_extendhisi2"
3207  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3208	(zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3209  "TARGET_ARM && arm_arch4"
3210  "ldr%?h\\t%0, %1"
3211  [(set_attr "type" "load")
3212   (set_attr "predicable" "yes")
3213   (set_attr "pool_range" "256")
3214   (set_attr "neg_pool_range" "244")]
3215)
3216
3217(define_split
3218  [(set (match_operand:SI 0 "s_register_operand" "")
3219	(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3220   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3221  "TARGET_ARM && (!arm_arch4)"
3222  [(set (match_dup 2) (match_dup 1))
3223   (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3224  "
3225  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3226    FAIL;
3227  "
3228)
3229
3230(define_split
3231  [(set (match_operand:SI 0 "s_register_operand" "")
3232	(match_operator:SI 3 "shiftable_operator"
3233	 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3234	  (match_operand:SI 4 "s_register_operand" "")]))
3235   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3236  "TARGET_ARM && (!arm_arch4)"
3237  [(set (match_dup 2) (match_dup 1))
3238   (set (match_dup 0)
3239	(match_op_dup 3
3240	 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3241  "
3242  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3243    FAIL;
3244  "
3245)
3246
3247(define_expand "zero_extendqisi2"
3248  [(set (match_operand:SI 0 "s_register_operand" "")
3249	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3250  "TARGET_EITHER"
3251  "
3252  if (GET_CODE (operands[1]) != MEM)
3253    {
3254      if (TARGET_ARM)
3255        {
3256          emit_insn (gen_andsi3 (operands[0],
3257				 gen_lowpart (SImode, operands[1]),
3258			         GEN_INT (255)));
3259        }
3260      else /* TARGET_THUMB */
3261        {
3262          rtx temp = gen_reg_rtx (SImode);
3263	  rtx ops[3];
3264	  
3265          operands[1] = copy_to_mode_reg (QImode, operands[1]);
3266          operands[1] = gen_lowpart (SImode, operands[1]);
3267
3268	  ops[0] = temp;
3269	  ops[1] = operands[1];
3270	  ops[2] = GEN_INT (24);
3271
3272	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3273				  gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3274	  
3275          ops[0] = operands[0];
3276	  ops[1] = temp;
3277	  ops[2] = GEN_INT (24);
3278
3279	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3280				  gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3281	}
3282      DONE;
3283    }
3284  "
3285)
3286
3287(define_insn "*thumb_zero_extendqisi2"
3288  [(set (match_operand:SI                 0 "register_operand" "=l")
3289	(zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3290  "TARGET_THUMB"
3291  "ldrb\\t%0, %1"
3292  [(set_attr "length" "2")
3293   (set_attr "type" "load")
3294   (set_attr "pool_range" "32")]
3295)
3296
3297(define_insn "*arm_zero_extendqisi2"
3298  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3299	(zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3300  "TARGET_ARM"
3301  "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3302  [(set_attr "type" "load")
3303   (set_attr "predicable" "yes")
3304   (set_attr "pool_range" "4096")
3305   (set_attr "neg_pool_range" "4084")]
3306)
3307
3308(define_split
3309  [(set (match_operand:SI 0 "s_register_operand" "")
3310	(zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3311   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3312  "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3313  [(set (match_dup 2) (match_dup 1))
3314   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3315  ""
3316)
3317
3318(define_insn "*compareqi_eq0"
3319  [(set (reg:CC_Z CC_REGNUM)
3320	(compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3321			 (const_int 0)))]
3322  "TARGET_ARM"
3323  "tst\\t%0, #255"
3324  [(set_attr "conds" "set")]
3325)
3326
3327(define_expand "extendhisi2"
3328  [(set (match_dup 2)
3329	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3330		   (const_int 16)))
3331   (set (match_operand:SI 0 "s_register_operand" "")
3332	(ashiftrt:SI (match_dup 2)
3333		     (const_int 16)))]
3334  "TARGET_EITHER"
3335  "
3336  {
3337    if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3338      {
3339       /* Note: We do not have to worry about TARGET_MMU_TRAPS
3340	  here because the insn below will generate an LDRH instruction
3341	  rather than an LDR instruction, so we cannot get an unaligned
3342	  word access.  */
3343        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3344		   gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3345        DONE;
3346      }
3347
3348    if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3349      {
3350        emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3351        DONE;
3352      }
3353    if (!s_register_operand (operands[1], HImode))
3354      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3355    operands[1] = gen_lowpart (SImode, operands[1]);
3356    operands[2] = gen_reg_rtx (SImode);
3357
3358    if (TARGET_THUMB)
3359      {
3360	rtx ops[3];
3361	
3362	ops[0] = operands[2];
3363	ops[1] = operands[1];
3364	ops[2] = GEN_INT (16);
3365	
3366        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3367				gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3368	    
3369	ops[0] = operands[0];
3370	ops[1] = operands[2];
3371	ops[2] = GEN_INT (16);
3372	
3373        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3374				gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3375	
3376	DONE;
3377      }
3378  }"
3379)
3380
3381(define_insn "*thumb_extendhisi2_insn"
3382  [(set (match_operand:SI                 0 "register_operand" "=l")
3383	(sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3384   (clobber (match_scratch:SI             2                   "=&l"))]
3385  "TARGET_THUMB"
3386  "*
3387  {
3388    rtx ops[4];
3389    rtx mem = XEXP (operands[1], 0);
3390
3391    /* This code used to try to use 'V', and fix the address only if it was
3392       offsettable, but this fails for e.g. REG+48 because 48 is outside the
3393       range of QImode offsets, and offsettable_address_p does a QImode
3394       address check.  */
3395       
3396    if (GET_CODE (mem) == CONST)
3397      mem = XEXP (mem, 0);
3398    
3399    if (GET_CODE (mem) == LABEL_REF)
3400      return \"ldr\\t%0, %1\";
3401    
3402    if (GET_CODE (mem) == PLUS)
3403      {
3404        rtx a = XEXP (mem, 0);
3405        rtx b = XEXP (mem, 1);
3406
3407        if (GET_CODE (a) == LABEL_REF
3408	    && GET_CODE (b) == CONST_INT)
3409          return \"ldr\\t%0, %1\";
3410
3411        if (GET_CODE (b) == REG)
3412          return \"ldrsh\\t%0, %1\";
3413	  
3414        ops[1] = a;
3415        ops[2] = b;
3416      }
3417    else
3418      {
3419        ops[1] = mem;
3420        ops[2] = const0_rtx;
3421      }
3422      
3423    if (GET_CODE (ops[1]) != REG)
3424      {
3425        debug_rtx (ops[1]);
3426        abort ();
3427      }
3428
3429    ops[0] = operands[0];
3430    ops[3] = operands[2];
3431    output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3432    return \"\";
3433  }"
3434  [(set_attr "length" "4")
3435   (set_attr "type" "load")
3436   (set_attr "pool_range" "1020")]
3437)
3438
3439(define_expand "extendhisi2_mem"
3440  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3441   (set (match_dup 3)
3442	(zero_extend:SI (match_dup 7)))
3443   (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3444   (set (match_operand:SI 0 "" "")
3445	(ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3446  "TARGET_ARM"
3447  "
3448  {
3449    rtx mem1, mem2;
3450    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3451
3452    mem1 = gen_rtx_MEM (QImode, addr);
3453    MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3454    mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3455    MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3456    operands[0] = gen_lowpart (SImode, operands[0]);
3457    operands[1] = mem1;
3458    operands[2] = gen_reg_rtx (SImode);
3459    operands[3] = gen_reg_rtx (SImode);
3460    operands[6] = gen_reg_rtx (SImode);
3461    operands[7] = mem2;
3462
3463    if (BYTES_BIG_ENDIAN)
3464      {
3465	operands[4] = operands[2];
3466	operands[5] = operands[3];
3467      }
3468    else
3469      {
3470	operands[4] = operands[3];
3471	operands[5] = operands[2];
3472      }
3473  }"
3474)
3475
3476(define_insn "*arm_extendhisi_insn"
3477  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3478	(sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3479  "TARGET_ARM && arm_arch4"
3480  "ldr%?sh\\t%0, %1"
3481  [(set_attr "type" "load")
3482   (set_attr "predicable" "yes")
3483   (set_attr "pool_range" "256")
3484   (set_attr "neg_pool_range" "244")]
3485)
3486
3487(define_split
3488  [(set (match_operand:SI                 0 "s_register_operand" "")
3489	(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3490   (clobber (match_operand:SI             2 "s_register_operand" ""))]
3491  "TARGET_ARM && (!arm_arch4)"
3492  [(set (match_dup 2) (match_dup 1))
3493   (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3494  "
3495  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3496    FAIL;
3497  "
3498)
3499
3500(define_split
3501  [(set (match_operand:SI                   0 "s_register_operand" "")
3502	(match_operator:SI                  3 "shiftable_operator"
3503	 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3504	  (match_operand:SI                 4 "s_register_operand" "")]))
3505   (clobber (match_operand:SI               2 "s_register_operand" ""))]
3506  "TARGET_ARM && (!arm_arch4)"
3507  [(set (match_dup 2) (match_dup 1))
3508   (set (match_dup 0)
3509	(match_op_dup 3
3510	 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3511  "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3512     FAIL;
3513  "
3514)
3515
3516(define_expand "extendqihi2"
3517  [(set (match_dup 2)
3518	(ashift:SI (match_operand:QI 1 "general_operand" "")
3519		   (const_int 24)))
3520   (set (match_operand:HI 0 "s_register_operand" "")
3521	(ashiftrt:SI (match_dup 2)
3522		     (const_int 24)))]
3523  "TARGET_ARM"
3524  "
3525  {
3526    if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3527      {
3528	emit_insn (gen_rtx_SET (VOIDmode,
3529				operands[0],
3530				gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3531	DONE;
3532      }
3533    if (!s_register_operand (operands[1], QImode))
3534      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3535    operands[0] = gen_lowpart (SImode, operands[0]);
3536    operands[1] = gen_lowpart (SImode, operands[1]);
3537    operands[2] = gen_reg_rtx (SImode);
3538  }"
3539)
3540
3541; Rather than restricting all byte accesses to memory addresses that ldrsb
3542; can handle, we fix up the ones that ldrsb can't grok with a split.
3543(define_insn "*extendqihi_insn"
3544  [(set (match_operand:HI                 0 "s_register_operand" "=r")
3545	(sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3546  "TARGET_ARM && arm_arch4"
3547  "*
3548  /* If the address is invalid, this will split the instruction into two.  */
3549  if (bad_signed_byte_operand (operands[1], VOIDmode))
3550    return \"#\";
3551  return \"ldr%?sb\\t%0, %1\";
3552  "
3553  [(set_attr "type" "load")
3554   (set_attr "predicable" "yes")
3555   (set_attr "length" "8")
3556   (set_attr "pool_range" "256")
3557   (set_attr "neg_pool_range" "244")]
3558)
3559
3560(define_split
3561  [(set (match_operand:HI 0 "s_register_operand" "")
3562	(sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3563  "TARGET_ARM && arm_arch4 && reload_completed"
3564  [(set (match_dup 3) (match_dup 1))
3565   (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3566  "
3567  {
3568    HOST_WIDE_INT offset;
3569
3570    operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3571    operands[2] = gen_rtx_MEM (QImode, operands[3]);
3572    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3573    operands[1] = XEXP (operands[1], 0);
3574    if (GET_CODE (operands[1]) == PLUS
3575	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3576	&& !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3577	     || const_ok_for_arm (-offset)))
3578      {
3579	HOST_WIDE_INT low = (offset > 0
3580			     ? (offset & 0xff) : -((-offset) & 0xff));
3581	XEXP (operands[2], 0) = plus_constant (operands[3], low);
3582	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3583      }
3584    /* Ensure the sum is in correct canonical form.  */
3585    else if (GET_CODE (operands[1]) == PLUS
3586	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3587	     && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3588      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3589					   XEXP (operands[1], 1),
3590					   XEXP (operands[1], 0));
3591  }"
3592)
3593
3594(define_expand "extendqisi2"
3595  [(set (match_dup 2)
3596	(ashift:SI (match_operand:QI 1 "general_operand" "")
3597		   (const_int 24)))
3598   (set (match_operand:SI 0 "s_register_operand" "")
3599	(ashiftrt:SI (match_dup 2)
3600		     (const_int 24)))]
3601  "TARGET_EITHER"
3602  "
3603  {
3604    if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3605      {
3606        emit_insn (gen_rtx_SET (VOIDmode,
3607			        operands[0],
3608			        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3609        DONE;
3610      }
3611    if (!s_register_operand (operands[1], QImode))
3612      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3613    operands[1] = gen_lowpart (SImode, operands[1]);
3614    operands[2] = gen_reg_rtx (SImode);
3615    
3616    if (TARGET_THUMB)
3617      {
3618	rtx ops[3];
3619	
3620	ops[0] = operands[2];
3621	ops[1] = operands[1];
3622	ops[2] = GEN_INT (24);
3623	
3624        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3625		   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3626
3627	ops[0] = operands[0];
3628	ops[1] = operands[2];
3629	ops[2] = GEN_INT (24);
3630	
3631        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3632		   gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3633	
3634	DONE;
3635      }
3636  }"
3637)
3638
3639; Rather than restricting all byte accesses to memory addresses that ldrsb
3640; can handle, we fix up the ones that ldrsb can't grok with a split.
3641(define_insn "*arm_extendqisi_insn"
3642  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3643	(sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3644  "TARGET_ARM && arm_arch4"
3645  "*
3646  /* If the address is invalid, this will split the instruction into two.  */
3647  if (bad_signed_byte_operand (operands[1], VOIDmode))
3648    return \"#\";
3649  return \"ldr%?sb\\t%0, %1\";
3650  "
3651  [(set_attr "type" "load")
3652   (set_attr "predicable" "yes")
3653   (set_attr "length" "8")
3654   (set_attr "pool_range" "256")
3655   (set_attr "neg_pool_range" "244")]
3656)
3657
3658(define_split
3659  [(set (match_operand:SI 0 "s_register_operand" "")
3660	(sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3661  "TARGET_ARM && arm_arch4 && reload_completed"
3662  [(set (match_dup 0) (match_dup 1))
3663   (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3664  "
3665  {
3666    HOST_WIDE_INT offset;
3667
3668    operands[2] = gen_rtx_MEM (QImode, operands[0]);
3669    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3670    operands[1] = XEXP (operands[1], 0);
3671    if (GET_CODE (operands[1]) == PLUS
3672	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3673	&& !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3674	     || const_ok_for_arm (-offset)))
3675      {
3676	HOST_WIDE_INT low = (offset > 0
3677			     ? (offset & 0xff) : -((-offset) & 0xff));
3678	XEXP (operands[2], 0) = plus_constant (operands[0], low);
3679	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3680      }
3681    /* Ensure the sum is in correct canonical form.  */
3682    else if (GET_CODE (operands[1]) == PLUS
3683	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3684	     && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3685      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3686					   XEXP (operands[1], 1),
3687					   XEXP (operands[1], 0));
3688  }"
3689)
3690
3691(define_insn "*thumb_extendqisi2_insn"
3692  [(set (match_operand:SI                 0 "register_operand" "=l,l")
3693	(sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3694  "TARGET_THUMB"
3695  "*
3696  {
3697    rtx ops[3];
3698    rtx mem = XEXP (operands[1], 0);
3699    
3700    if (GET_CODE (mem) == CONST)
3701      mem = XEXP (mem, 0);
3702    
3703    if (GET_CODE (mem) == LABEL_REF)
3704      return \"ldr\\t%0, %1\";
3705
3706    if (GET_CODE (mem) == PLUS
3707        && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3708      return \"ldr\\t%0, %1\";
3709      
3710    if (which_alternative == 0)
3711      return \"ldrsb\\t%0, %1\";
3712      
3713    ops[0] = operands[0];
3714    
3715    if (GET_CODE (mem) == PLUS)
3716      {
3717        rtx a = XEXP (mem, 0);
3718	rtx b = XEXP (mem, 1);
3719	
3720        ops[1] = a;
3721        ops[2] = b;
3722
3723        if (GET_CODE (a) == REG)
3724	  {
3725	    if (GET_CODE (b) == REG)
3726              output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3727            else if (REGNO (a) == REGNO (ops[0]))
3728	      {
3729                output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3730		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3731		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3732	      }
3733	    else
3734              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3735	  }
3736        else if (GET_CODE (b) != REG)
3737	  abort ();
3738	else
3739          {
3740            if (REGNO (b) == REGNO (ops[0]))
3741	      {
3742                output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3743		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3744		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3745	      }
3746	    else
3747              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3748          }
3749      }
3750    else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3751      {
3752        output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3753	output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3754	output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3755      }
3756    else
3757      {
3758        ops[1] = mem;
3759        ops[2] = const0_rtx;
3760	
3761        output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3762      }
3763    return \"\";
3764  }"
3765  [(set_attr "length" "2,6")
3766   (set_attr "type" "load,load")
3767   (set_attr "pool_range" "32,32")]
3768)
3769
3770(define_expand "extendsfdf2"
3771  [(set (match_operand:DF                  0 "s_register_operand" "")
3772	(float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3773  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3774  ""
3775)
3776
3777;; Move insns (including loads and stores)
3778
3779;; XXX Just some ideas about movti.
3780;; I don't think these are a good idea on the arm, there just aren't enough
3781;; registers
3782;;(define_expand "loadti"
3783;;  [(set (match_operand:TI 0 "s_register_operand" "")
3784;;	(mem:TI (match_operand:SI 1 "address_operand" "")))]
3785;;  "" "")
3786
3787;;(define_expand "storeti"
3788;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3789;;	(match_operand:TI 1 "s_register_operand" ""))]
3790;;  "" "")
3791
3792;;(define_expand "movti"
3793;;  [(set (match_operand:TI 0 "general_operand" "")
3794;;	(match_operand:TI 1 "general_operand" ""))]
3795;;  ""
3796;;  "
3797;;{
3798;;  rtx insn;
3799;;
3800;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3801;;    operands[1] = copy_to_reg (operands[1]);
3802;;  if (GET_CODE (operands[0]) == MEM)
3803;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3804;;  else if (GET_CODE (operands[1]) == MEM)
3805;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3806;;  else
3807;;    FAIL;
3808;;
3809;;  emit_insn (insn);
3810;;  DONE;
3811;;}")
3812
3813;; Recognize garbage generated above.
3814
3815;;(define_insn ""
3816;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3817;;	(match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3818;;  ""
3819;;  "*
3820;;  {
3821;;    register mem = (which_alternative < 3);
3822;;    register const char *template;
3823;;
3824;;    operands[mem] = XEXP (operands[mem], 0);
3825;;    switch (which_alternative)
3826;;      {
3827;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3828;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3829;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3830;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3831;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3832;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3833;;      }
3834;;    output_asm_insn (template, operands);
3835;;    return \"\";
3836;;  }")
3837
3838(define_expand "movdi"
3839  [(set (match_operand:DI 0 "general_operand" "")
3840	(match_operand:DI 1 "general_operand" ""))]
3841  "TARGET_EITHER"
3842  "
3843  if (TARGET_THUMB)
3844    {
3845      if (!no_new_pseudos)
3846        {
3847          if (GET_CODE (operands[0]) != REG)
3848	    operands[1] = force_reg (DImode, operands[1]);
3849        }
3850    }
3851  "
3852)
3853
3854(define_insn "*arm_movdi"
3855  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3856	(match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3857  "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
3858  "*
3859  return (output_move_double (operands));
3860  "
3861  [(set_attr "length" "8")
3862   (set_attr "type" "*,load,store2")
3863   (set_attr "pool_range" "*,1020,*")
3864   (set_attr "neg_pool_range" "*,1008,*")]
3865)
3866
3867;;; ??? This should have alternatives for constants.
3868;;; ??? This was originally identical to the movdf_insn pattern.
3869;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3870;;; thumb_reorg with a memory reference.
3871(define_insn "*thumb_movdi_insn"
3872  [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3873	(match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3874  "TARGET_THUMB
3875   && !TARGET_CIRRUS
3876   && (   register_operand (operands[0], DImode)
3877       || register_operand (operands[1], DImode))"
3878  "*
3879  {
3880  switch (which_alternative)
3881    {
3882    default:
3883    case 0:
3884      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3885	return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3886      return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3887    case 1:
3888      return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3889    case 2:
3890      operands[1] = GEN_INT (- INTVAL (operands[1]));
3891      return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3892    case 3:
3893      return \"ldmia\\t%1, {%0, %H0}\";
3894    case 4:
3895      return \"stmia\\t%0, {%1, %H1}\";
3896    case 5:
3897      return thumb_load_double_from_address (operands);
3898    case 6:
3899      operands[2] = gen_rtx (MEM, SImode,
3900			     plus_constant (XEXP (operands[0], 0), 4));
3901      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3902      return \"\";
3903    case 7:
3904      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3905	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3906      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3907    }
3908  }"
3909  [(set_attr "length" "4,4,6,2,2,6,4,4")
3910   (set_attr "type" "*,*,*,load,store2,load,store2,*")
3911   (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3912)
3913
3914(define_expand "movsi"
3915  [(set (match_operand:SI 0 "general_operand" "")
3916        (match_operand:SI 1 "general_operand" ""))]
3917  "TARGET_EITHER"
3918  "
3919  if (TARGET_ARM)
3920    {
3921      /* Everything except mem = const or mem = mem can be done easily.  */
3922      if (GET_CODE (operands[0]) == MEM)
3923        operands[1] = force_reg (SImode, operands[1]);
3924      if (GET_CODE (operands[1]) == CONST_INT
3925          && !(const_ok_for_arm (INTVAL (operands[1]))
3926               || const_ok_for_arm (~INTVAL (operands[1]))))
3927        {
3928           arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3929		    	      NULL_RTX,
3930			      (no_new_pseudos ? 0
3931			       : preserve_subexpressions_p ()));
3932          DONE;
3933        }
3934    }
3935  else /* TARGET_THUMB....  */
3936    {
3937      if (!no_new_pseudos)
3938        {
3939          if (GET_CODE (operands[0]) != REG)
3940	    operands[1] = force_reg (SImode, operands[1]);
3941        }
3942    }
3943    
3944  if (flag_pic
3945      && (CONSTANT_P (operands[1])
3946	 || symbol_mentioned_p (operands[1])
3947	 || label_mentioned_p (operands[1])))
3948    operands[1] = legitimize_pic_address (operands[1], SImode,
3949					  (no_new_pseudos ? operands[0] : 0));
3950  "
3951)
3952
3953(define_insn "*arm_movsi_insn"
3954  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3955	(match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
3956  "TARGET_ARM && ! TARGET_IWMMXT
3957   && (   register_operand (operands[0], SImode)
3958       || register_operand (operands[1], SImode))"
3959  "@
3960   mov%?\\t%0, %1
3961   mvn%?\\t%0, #%B1
3962   ldr%?\\t%0, %1
3963   str%?\\t%1, %0"
3964  [(set_attr "type" "*,*,load,store1")
3965   (set_attr "predicable" "yes")
3966   (set_attr "pool_range" "*,*,4096,*")
3967   (set_attr "neg_pool_range" "*,*,4084,*")]
3968)
3969
3970(define_split
3971  [(set (match_operand:SI 0 "s_register_operand" "")
3972	(match_operand:SI 1 "const_int_operand" ""))]
3973  "TARGET_ARM
3974  && (!(const_ok_for_arm (INTVAL (operands[1]))
3975        || const_ok_for_arm (~INTVAL (operands[1]))))"
3976  [(clobber (const_int 0))]
3977  "
3978  arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3979		      NULL_RTX, 0);
3980  DONE;
3981  "
3982)
3983
3984(define_insn "*thumb_movsi_insn"
3985  [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3986	(match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
3987  "TARGET_THUMB
3988   && (   register_operand (operands[0], SImode) 
3989       || register_operand (operands[1], SImode))"
3990  "@
3991   mov	%0, %1
3992   mov	%0, %1
3993   #
3994   #
3995   ldmia\\t%1, {%0}
3996   stmia\\t%0, {%1}
3997   ldr\\t%0, %1
3998   str\\t%1, %0
3999   mov\\t%0, %1"
4000  [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4001   (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4002   (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4003)
4004
4005(define_split 
4006  [(set (match_operand:SI 0 "register_operand" "")
4007	(match_operand:SI 1 "const_int_operand" ""))]
4008  "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4009  [(set (match_dup 0) (match_dup 1))
4010   (set (match_dup 0) (neg:SI (match_dup 0)))]
4011  "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4012)
4013
4014(define_split 
4015  [(set (match_operand:SI 0 "register_operand" "")
4016	(match_operand:SI 1 "const_int_operand" ""))]
4017  "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4018  [(set (match_dup 0) (match_dup 1))
4019   (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4020  "
4021  {
4022    unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4023    unsigned HOST_WIDE_INT mask = 0xff;
4024    int i;
4025    
4026    for (i = 0; i < 25; i++)
4027      if ((val & (mask << i)) == val)
4028        break;
4029
4030    /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4031    if (i == 0)
4032      FAIL;
4033
4034    operands[1] = GEN_INT (val >> i);
4035    operands[2] = GEN_INT (i);
4036  }"
4037)
4038
4039;; When generating pic, we need to load the symbol offset into a register.
4040;; So that the optimizer does not confuse this with a normal symbol load
4041;; we use an unspec.  The offset will be loaded from a constant pool entry,
4042;; since that is the only type of relocation we can use.
4043
4044;; The rather odd constraints on the following are to force reload to leave
4045;; the insn alone, and to force the minipool generation pass to then move
4046;; the GOT symbol to memory.
4047
4048(define_insn "pic_load_addr_arm"
4049  [(set (match_operand:SI 0 "s_register_operand" "=r")
4050	(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4051  "TARGET_ARM && flag_pic"
4052  "ldr%?\\t%0, %1"
4053  [(set_attr "type" "load")
4054   (set (attr "pool_range")     (const_int 4096))
4055   (set (attr "neg_pool_range") (const_int 4084))]
4056)
4057
4058(define_insn "pic_load_addr_thumb"
4059  [(set (match_operand:SI 0 "s_register_operand" "=l")
4060	(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4061  "TARGET_THUMB && flag_pic"
4062  "ldr\\t%0, %1"
4063  [(set_attr "type" "load")
4064   (set (attr "pool_range") (const_int 1024))]
4065)
4066
4067;; This variant is used for AOF assembly, since it needs to mention the
4068;; pic register in the rtl.
4069(define_expand "pic_load_addr_based"
4070  [(set (match_operand:SI 0 "s_register_operand" "")
4071	(unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4072  "TARGET_ARM && flag_pic"
4073  "operands[2] = pic_offset_table_rtx;"
4074)
4075
4076(define_insn "*pic_load_addr_based_insn"
4077  [(set (match_operand:SI 0 "s_register_operand" "=r")
4078	(unspec:SI [(match_operand 1 "" "")
4079		    (match_operand 2 "s_register_operand" "r")]
4080		   UNSPEC_PIC_SYM))]
4081  "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4082  "*
4083#ifdef AOF_ASSEMBLER
4084  operands[1] = aof_pic_entry (operands[1]);
4085#endif
4086  output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4087  return \"\";
4088  "
4089  [(set_attr "type" "load")
4090   (set (attr "pool_range")
4091	(if_then_else (eq_attr "is_thumb" "yes")
4092		      (const_int 1024)
4093		      (const_int 4096)))
4094   (set (attr "neg_pool_range")
4095	(if_then_else (eq_attr "is_thumb" "yes")
4096		      (const_int 0)
4097		      (const_int 4084)))]
4098)
4099
4100(define_insn "pic_add_dot_plus_four"
4101  [(set (match_operand:SI 0 "register_operand" "+r")
4102	(unspec:SI [(plus:SI (match_dup 0)
4103			     (const (plus:SI (pc) (const_int 4))))]
4104		   UNSPEC_PIC_BASE))
4105   (use (label_ref (match_operand 1 "" "")))]
4106  "TARGET_THUMB && flag_pic"
4107  "*
4108  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4109			     CODE_LABEL_NUMBER (operands[1]));
4110  return \"add\\t%0, %|pc\";
4111  "
4112  [(set_attr "length" "2")]
4113)
4114
4115(define_insn "pic_add_dot_plus_eight"
4116  [(set (match_operand:SI 0 "register_operand" "+r")
4117	(unspec:SI [(plus:SI (match_dup 0)
4118			     (const (plus:SI (pc) (const_int 8))))]
4119		   UNSPEC_PIC_BASE))
4120   (use (label_ref (match_operand 1 "" "")))]
4121  "TARGET_ARM && flag_pic"
4122  "*
4123    (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4124			       CODE_LABEL_NUMBER (operands[1]));
4125    return \"add%?\\t%0, %|pc, %0\";
4126  "
4127  [(set_attr "predicable" "yes")]
4128)
4129
4130(define_expand "builtin_setjmp_receiver"
4131  [(label_ref (match_operand 0 "" ""))]
4132  "flag_pic"
4133  "
4134{
4135  arm_finalize_pic (0);
4136  DONE;
4137}")
4138
4139;; If copying one reg to another we can set the condition codes according to
4140;; its value.  Such a move is common after a return from subroutine and the
4141;; result is being tested against zero.
4142
4143(define_insn "*movsi_compare0"
4144  [(set (reg:CC CC_REGNUM)
4145	(compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4146		    (const_int 0)))
4147   (set (match_operand:SI 0 "s_register_operand" "=r,r")
4148	(match_dup 1))]
4149  "TARGET_ARM"
4150  "@
4151   cmp%?\\t%0, #0
4152   sub%?s\\t%0, %1, #0"
4153  [(set_attr "conds" "set")]
4154)
4155
4156;; Subroutine to store a half word from a register into memory.
4157;; Operand 0 is the source register (HImode)
4158;; Operand 1 is the destination address in a register (SImode)
4159
4160;; In both this routine and the next, we must be careful not to spill
4161;; a memory address of reg+large_const into a separate PLUS insn, since this
4162;; can generate unrecognizable rtl.
4163
4164(define_expand "storehi"
4165  [;; store the low byte
4166   (set (match_operand 1 "" "") (match_dup 3))
4167   ;; extract the high byte
4168   (set (match_dup 2)
4169	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4170   ;; store the high byte
4171   (set (match_dup 4) (match_dup 5))]
4172  "TARGET_ARM"
4173  "
4174  {
4175    rtx op1 = operands[1];
4176    rtx addr = XEXP (op1, 0);
4177    enum rtx_code code = GET_CODE (addr);
4178
4179    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4180	|| code == MINUS)
4181      op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4182
4183    operands[4] = adjust_address (op1, QImode, 1);
4184    operands[1] = adjust_address (operands[1], QImode, 0);
4185    operands[3] = gen_lowpart (QImode, operands[0]);
4186    operands[0] = gen_lowpart (SImode, operands[0]);
4187    operands[2] = gen_reg_rtx (SImode);
4188    operands[5] = gen_lowpart (QImode, operands[2]);
4189  }"
4190)
4191
4192(define_expand "storehi_bigend"
4193  [(set (match_dup 4) (match_dup 3))
4194   (set (match_dup 2)
4195	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4196   (set (match_operand 1 "" "")	(match_dup 5))]
4197  "TARGET_ARM"
4198  "
4199  {
4200    rtx op1 = operands[1];
4201    rtx addr = XEXP (op1, 0);
4202    enum rtx_code code = GET_CODE (addr);
4203
4204    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4205	|| code == MINUS)
4206      op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4207
4208    operands[4] = adjust_address (op1, QImode, 1);
4209    operands[1] = adjust_address (operands[1], QImode, 0);
4210    operands[3] = gen_lowpart (QImode, operands[0]);
4211    operands[0] = gen_lowpart (SImode, operands[0]);
4212    operands[2] = gen_reg_rtx (SImode);
4213    operands[5] = gen_lowpart (QImode, operands[2]);
4214  }"
4215)
4216
4217;; Subroutine to store a half word integer constant into memory.
4218(define_expand "storeinthi"
4219  [(set (match_operand 0 "" "")
4220	(match_operand 1 "" ""))
4221   (set (match_dup 3) (match_dup 2))]
4222  "TARGET_ARM"
4223  "
4224  {
4225    HOST_WIDE_INT value = INTVAL (operands[1]);
4226    rtx addr = XEXP (operands[0], 0);
4227    rtx op0 = operands[0];
4228    enum rtx_code code = GET_CODE (addr);
4229
4230    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4231	|| code == MINUS)
4232      op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4233
4234    operands[1] = gen_reg_rtx (SImode);
4235    if (BYTES_BIG_ENDIAN)
4236      {
4237	emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4238	if ((value & 255) == ((value >> 8) & 255))
4239	  operands[2] = operands[1];
4240	else
4241	  {
4242	    operands[2] = gen_reg_rtx (SImode);
4243	    emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4244	  }
4245      }
4246    else
4247      {
4248	emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4249	if ((value & 255) == ((value >> 8) & 255))
4250	  operands[2] = operands[1];
4251	else
4252	  {
4253	    operands[2] = gen_reg_rtx (SImode);
4254	    emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4255	  }
4256      }
4257
4258    operands[3] = adjust_address (op0, QImode, 1);
4259    operands[0] = adjust_address (operands[0], QImode, 0);
4260    operands[2] = gen_lowpart (QImode, operands[2]);
4261    operands[1] = gen_lowpart (QImode, operands[1]);
4262  }"
4263)
4264
4265(define_expand "storehi_single_op"
4266  [(set (match_operand:HI 0 "memory_operand" "")
4267	(match_operand:HI 1 "general_operand" ""))]
4268  "TARGET_ARM && arm_arch4"
4269  "
4270  if (!s_register_operand (operands[1], HImode))
4271    operands[1] = copy_to_mode_reg (HImode, operands[1]);
4272  "
4273)
4274
4275(define_expand "movhi"
4276  [(set (match_operand:HI 0 "general_operand" "")
4277	(match_operand:HI 1 "general_operand" ""))]
4278  "TARGET_EITHER"
4279  "
4280  if (TARGET_ARM)
4281    {
4282      if (!no_new_pseudos)
4283        {
4284          if (GET_CODE (operands[0]) == MEM)
4285	    {
4286	      if (arm_arch4)
4287	        {
4288	          emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4289	          DONE;
4290	        }
4291	      if (GET_CODE (operands[1]) == CONST_INT)
4292	        emit_insn (gen_storeinthi (operands[0], operands[1]));
4293	      else
4294	        {
4295	          if (GET_CODE (operands[1]) == MEM)
4296		    operands[1] = force_reg (HImode, operands[1]);
4297	          if (BYTES_BIG_ENDIAN)
4298		    emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4299	          else
4300		   emit_insn (gen_storehi (operands[1], operands[0]));
4301	        }
4302	      DONE;
4303	    }
4304          /* Sign extend a constant, and keep it in an SImode reg.  */
4305          else if (GET_CODE (operands[1]) == CONST_INT)
4306	    {
4307	      rtx reg = gen_reg_rtx (SImode);
4308	      HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4309
4310	      /* If the constant is already valid, leave it alone.  */
4311	      if (!const_ok_for_arm (val))
4312	        {
4313	          /* If setting all the top bits will make the constant 
4314		     loadable in a single instruction, then set them.  
4315		     Otherwise, sign extend the number.  */
4316
4317	          if (const_ok_for_arm (~(val | ~0xffff)))
4318		    val |= ~0xffff;
4319	          else if (val & 0x8000)
4320		    val |= ~0xffff;
4321	        }
4322
4323	      emit_insn (gen_movsi (reg, GEN_INT (val)));
4324	      operands[1] = gen_lowpart (HImode, reg);
4325	    }
4326	  else if (arm_arch4 && !no_new_pseudos && optimize > 0
4327		   && GET_CODE (operands[1]) == MEM)
4328	    {
4329	      rtx reg = gen_reg_rtx (SImode);
4330
4331	      emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4332	      operands[1] = gen_lowpart (HImode, reg);
4333	    }
4334          else if (!arm_arch4)
4335	    {
4336	     /* Note: We do not have to worry about TARGET_MMU_TRAPS
4337	        for v4 and up architectures because LDRH instructions will
4338	        be used to access the HI values, and these cannot generate
4339	        unaligned word access faults in the MMU.  */
4340	      if (GET_CODE (operands[1]) == MEM)
4341	        {
4342	          if (TARGET_MMU_TRAPS)
4343		    {
4344		      rtx base;
4345		      rtx offset = const0_rtx;
4346		      rtx reg = gen_reg_rtx (SImode);
4347
4348		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4349		           || (GET_CODE (base) == PLUS
4350			       && (GET_CODE (offset = XEXP (base, 1))
4351				   == CONST_INT)
4352                               && ((INTVAL(offset) & 1) != 1)
4353			       && GET_CODE (base = XEXP (base, 0)) == REG))
4354		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4355		        {
4356		          HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4357		          rtx new;
4358
4359		          new = gen_rtx_MEM (SImode,
4360				   	     plus_constant (base, new_offset));
4361	                  MEM_COPY_ATTRIBUTES (new, operands[1]);
4362		          emit_insn (gen_movsi (reg, new));
4363		          if (((INTVAL (offset) & 2) != 0)
4364			      ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4365			    {
4366			      rtx reg2 = gen_reg_rtx (SImode);
4367
4368			      emit_insn (gen_lshrsi3 (reg2, reg,
4369					 GEN_INT (16)));
4370			      reg = reg2;
4371			    }
4372		        }
4373		      else
4374		        emit_insn (gen_movhi_bytes (reg, operands[1]));
4375
4376		      operands[1] = gen_lowpart (HImode, reg);
4377		    }
4378	          else if (BYTES_BIG_ENDIAN)
4379		    {
4380		      rtx base;
4381		      rtx offset = const0_rtx;
4382
4383		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4384		           || (GET_CODE (base) == PLUS
4385			      && (GET_CODE (offset = XEXP (base, 1))
4386				  == CONST_INT)
4387			      && GET_CODE (base = XEXP (base, 0)) == REG))
4388		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4389		        {
4390		          rtx reg = gen_reg_rtx (SImode);
4391		          rtx new;
4392
4393		          if ((INTVAL (offset) & 2) == 2)
4394			    {
4395			      HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4396			      new = gen_rtx_MEM (SImode,
4397				  	         plus_constant (base,
4398								new_offset));
4399                              MEM_COPY_ATTRIBUTES (new, operands[1]);
4400			      emit_insn (gen_movsi (reg, new));
4401			    }
4402		          else
4403			    {
4404			      new = gen_rtx_MEM (SImode,
4405						 XEXP (operands[1], 0));
4406	                      MEM_COPY_ATTRIBUTES (new, operands[1]);
4407			      emit_insn (gen_rotated_loadsi (reg, new));
4408			    }
4409
4410		          operands[1] = gen_lowpart (HImode, reg);
4411		        }
4412		      else
4413		        {
4414		          emit_insn (gen_movhi_bigend (operands[0],
4415						       operands[1]));
4416		          DONE;
4417		        }
4418		    }
4419	       }
4420	   }
4421        }
4422      /* Handle loading a large integer during reload.  */
4423      else if (GET_CODE (operands[1]) == CONST_INT
4424	       && !const_ok_for_arm (INTVAL (operands[1]))
4425	       && !const_ok_for_arm (~INTVAL (operands[1])))
4426        {
4427          /* Writing a constant to memory needs a scratch, which should
4428	     be handled with SECONDARY_RELOADs.  */
4429          if (GET_CODE (operands[0]) != REG)
4430	    abort ();
4431
4432          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4433          emit_insn (gen_movsi (operands[0], operands[1]));
4434          DONE;
4435       }
4436    }
4437  else /* TARGET_THUMB */
4438    {
4439      if (!no_new_pseudos)
4440        {
4441          if (GET_CODE (operands[0]) != REG)
4442	    operands[1] = force_reg (HImode, operands[1]);
4443
4444          /* ??? We shouldn't really get invalid addresses here, but this can
4445	     happen if we are passed a SP (never OK for HImode/QImode) or 
4446	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4447	     HImode/QImode) relative address.  */
4448          /* ??? This should perhaps be fixed elsewhere, for instance, in
4449	     fixup_stack_1, by checking for other kinds of invalid addresses,
4450	     e.g. a bare reference to a virtual register.  This may confuse the
4451	     alpha though, which must handle this case differently.  */
4452          if (GET_CODE (operands[0]) == MEM
4453	      && !memory_address_p (GET_MODE (operands[0]),
4454				    XEXP (operands[0], 0)))
4455	    operands[0]
4456	      = replace_equiv_address (operands[0],
4457				       copy_to_reg (XEXP (operands[0], 0)));
4458   
4459          if (GET_CODE (operands[1]) == MEM
4460	      && !memory_address_p (GET_MODE (operands[1]),
4461				    XEXP (operands[1], 0)))
4462	    operands[1]
4463	      = replace_equiv_address (operands[1],
4464				       copy_to_reg (XEXP (operands[1], 0)));
4465        }
4466      /* Handle loading a large integer during reload.  */
4467      else if (GET_CODE (operands[1]) == CONST_INT
4468	        && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4469        {
4470          /* Writing a constant to memory needs a scratch, which should
4471	     be handled with SECONDARY_RELOADs.  */
4472          if (GET_CODE (operands[0]) != REG)
4473	    abort ();
4474
4475          operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4476          emit_insn (gen_movsi (operands[0], operands[1]));
4477          DONE;
4478        }
4479    }
4480  "
4481)
4482
4483(define_insn "*thumb_movhi_insn"
4484  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4485	(match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4486  "TARGET_THUMB
4487   && (   register_operand (operands[0], HImode)
4488       || register_operand (operands[1], HImode))"
4489  "*
4490  switch (which_alternative)
4491    {
4492    case 0: return \"add	%0, %1, #0\";
4493    case 2: return \"strh	%1, %0\";
4494    case 3: return \"mov	%0, %1\";
4495    case 4: return \"mov	%0, %1\";
4496    case 5: return \"mov	%0, %1\";
4497    default: abort ();
4498    case 1:
4499      /* The stack pointer can end up being taken as an index register.
4500          Catch this case here and deal with it.  */
4501      if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4502	  && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4503	  && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4504        {
4505	  rtx ops[2];
4506          ops[0] = operands[0];
4507          ops[1] = XEXP (XEXP (operands[1], 0), 0);
4508      
4509          output_asm_insn (\"mov	%0, %1\", ops);
4510
4511          XEXP (XEXP (operands[1], 0), 0) = operands[0];
4512    
4513	}
4514      return \"ldrh	%0, %1\";
4515    }"
4516  [(set_attr "length" "2,4,2,2,2,2")
4517   (set_attr "type" "*,load,store1,*,*,*")]
4518)
4519
4520
4521(define_insn "rotated_loadsi"
4522  [(set (match_operand:SI            0 "s_register_operand"        "=r")
4523	(rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4524		   (const_int 16)))]
4525  "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4526  "*
4527  {
4528    rtx ops[2];
4529
4530    ops[0] = operands[0];
4531    ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4532    output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4533    return \"\";
4534  }"
4535  [(set_attr "type" "load")
4536   (set_attr "predicable" "yes")]
4537)
4538
4539(define_expand "movhi_bytes"
4540  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4541   (set (match_dup 3)
4542	(zero_extend:SI (match_dup 6)))
4543   (set (match_operand:SI 0 "" "")
4544	 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4545  "TARGET_ARM"
4546  "
4547  {
4548    rtx mem1, mem2;
4549    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4550
4551    mem1 = gen_rtx_MEM (QImode, addr);
4552    MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4553    mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4554    MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4555    operands[0] = gen_lowpart (SImode, operands[0]);
4556    operands[1] = mem1;
4557    operands[2] = gen_reg_rtx (SImode);
4558    operands[3] = gen_reg_rtx (SImode);
4559    operands[6] = mem2;
4560
4561    if (BYTES_BIG_ENDIAN)
4562      {
4563	operands[4] = operands[2];
4564	operands[5] = operands[3];
4565      }
4566    else
4567      {
4568	operands[4] = operands[3];
4569	operands[5] = operands[2];
4570      }
4571  }"
4572)
4573
4574(define_expand "movhi_bigend"
4575  [(set (match_dup 2)
4576	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4577		   (const_int 16)))
4578   (set (match_dup 3)
4579	(ashiftrt:SI (match_dup 2) (const_int 16)))
4580   (set (match_operand:HI 0 "s_register_operand" "")
4581	(match_dup 4))]
4582  "TARGET_ARM"
4583  "
4584  operands[2] = gen_reg_rtx (SImode);
4585  operands[3] = gen_reg_rtx (SImode);
4586  operands[4] = gen_lowpart (HImode, operands[3]);
4587  "
4588)
4589
4590;; Pattern to recognize insn generated default case above
4591(define_insn "*movhi_insn_arch4"
4592  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4593	(match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4594  "TARGET_ARM
4595   && arm_arch4
4596   && (GET_CODE (operands[1]) != CONST_INT
4597       || const_ok_for_arm (INTVAL (operands[1]))
4598       || const_ok_for_arm (~INTVAL (operands[1])))"
4599  "@
4600   mov%?\\t%0, %1\\t%@ movhi
4601   mvn%?\\t%0, #%B1\\t%@ movhi
4602   str%?h\\t%1, %0\\t%@ movhi 
4603   ldr%?h\\t%0, %1\\t%@ movhi"
4604  [(set_attr "type" "*,*,store1,load")
4605   (set_attr "predicable" "yes")
4606   (set_attr "pool_range" "*,*,*,256")
4607   (set_attr "neg_pool_range" "*,*,*,244")]
4608)
4609
4610(define_insn "*movhi_insn_littleend"
4611  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4612	(match_operand:HI 1 "general_operand"  "rI,K,m"))]
4613  "TARGET_ARM
4614   && !arm_arch4
4615   && !BYTES_BIG_ENDIAN
4616   && !TARGET_MMU_TRAPS
4617   && (GET_CODE (operands[1]) != CONST_INT
4618       || const_ok_for_arm (INTVAL (operands[1]))
4619       || const_ok_for_arm (~INTVAL (operands[1])))"
4620  "@
4621   mov%?\\t%0, %1\\t%@ movhi
4622   mvn%?\\t%0, #%B1\\t%@ movhi
4623   ldr%?\\t%0, %1\\t%@ movhi"
4624  [(set_attr "type" "*,*,load")
4625   (set_attr "predicable" "yes")
4626   (set_attr "pool_range" "4096")
4627   (set_attr "neg_pool_range" "4084")]
4628)
4629
4630(define_insn "*movhi_insn_bigend"
4631  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4632	(match_operand:HI 1 "general_operand"    "rI,K,m"))]
4633  "TARGET_ARM
4634   && !arm_arch4
4635   && BYTES_BIG_ENDIAN
4636   && !TARGET_MMU_TRAPS
4637   && (GET_CODE (operands[1]) != CONST_INT
4638       || const_ok_for_arm (INTVAL (operands[1]))
4639       || const_ok_for_arm (~INTVAL (operands[1])))"
4640  "@
4641   mov%?\\t%0, %1\\t%@ movhi
4642   mvn%?\\t%0, #%B1\\t%@ movhi
4643   ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4644  [(set_attr "type" "*,*,load")
4645   (set_attr "predicable" "yes")
4646   (set_attr "length" "4,4,8")
4647   (set_attr "pool_range" "*,*,4092")
4648   (set_attr "neg_pool_range" "*,*,4084")]
4649)
4650
4651(define_insn "*loadhi_si_bigend"
4652  [(set (match_operand:SI                       0 "s_register_operand" "=r")
4653	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4654		   (const_int 16)))]
4655  "TARGET_ARM
4656   && BYTES_BIG_ENDIAN
4657   && !TARGET_MMU_TRAPS"
4658  "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4659  [(set_attr "type" "load")
4660   (set_attr "predicable" "yes")
4661   (set_attr "pool_range" "4096")
4662   (set_attr "neg_pool_range" "4084")]
4663)
4664
4665(define_insn "*movhi_bytes"
4666  [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4667	(match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4668  "TARGET_ARM && TARGET_MMU_TRAPS"
4669  "@
4670   mov%?\\t%0, %1\\t%@ movhi
4671   mvn%?\\t%0, #%B1\\t%@ movhi"
4672  [(set_attr "predicable" "yes")]
4673)
4674
4675(define_insn "thumb_movhi_clobber"
4676  [(set (match_operand:HI     0 "memory_operand"   "=m")
4677	(match_operand:HI     1 "register_operand" "l"))
4678   (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4679  "TARGET_THUMB"
4680  "*
4681  abort ();"
4682)
4683	
4684;; We use a DImode scratch because we may occasionally need an additional
4685;; temporary if the address isn't offsettable -- push_reload doesn't seem
4686;; to take any notice of the "o" constraints on reload_memory_operand operand.
4687(define_expand "reload_outhi"
4688  [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4689	      (match_operand:HI 1 "s_register_operand"        "r")
4690	      (match_operand:DI 2 "s_register_operand"        "=&l")])]
4691  "TARGET_EITHER"
4692  "if (TARGET_ARM)
4693     arm_reload_out_hi (operands);
4694   else
4695     thumb_reload_out_hi (operands);
4696  DONE;
4697  "
4698)
4699
4700(define_expand "reload_inhi"
4701  [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4702	      (match_operand:HI 1 "arm_reload_memory_operand" "o")
4703	      (match_operand:DI 2 "s_register_operand" "=&r")])]
4704  "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4705  "
4706  if (TARGET_ARM)
4707    arm_reload_in_hi (operands);
4708  else
4709    thumb_reload_out_hi (operands);
4710  DONE;
4711")
4712
4713(define_expand "movqi"
4714  [(set (match_operand:QI 0 "general_operand" "")
4715        (match_operand:QI 1 "general_operand" ""))]
4716  "TARGET_EITHER"
4717  "
4718  if (TARGET_ARM)
4719    {
4720      /* Everything except mem = const or mem = mem can be done easily */
4721
4722      if (!no_new_pseudos)
4723        {
4724          if (GET_CODE (operands[1]) == CONST_INT)
4725	    {
4726	      rtx reg = gen_reg_rtx (SImode);
4727
4728	      emit_insn (gen_movsi (reg, operands[1]));
4729	      operands[1] = gen_lowpart (QImode, reg);
4730	    }
4731	  if (GET_CODE (operands[1]) == MEM && optimize > 0)
4732	    {
4733	      rtx reg = gen_reg_rtx (SImode);
4734
4735	      emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4736	      operands[1] = gen_lowpart (QImode, reg);
4737	    }
4738          if (GET_CODE (operands[0]) == MEM)
4739	    operands[1] = force_reg (QImode, operands[1]);
4740        }
4741    }
4742  else /* TARGET_THUMB */
4743    {
4744      if (!no_new_pseudos)
4745        {
4746          if (GET_CODE (operands[0]) != REG)
4747	    operands[1] = force_reg (QImode, operands[1]);
4748
4749          /* ??? We shouldn't really get invalid addresses here, but this can
4750	     happen if we are passed a SP (never OK for HImode/QImode) or
4751	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4752	     HImode/QImode) relative address.  */
4753          /* ??? This should perhaps be fixed elsewhere, for instance, in
4754	     fixup_stack_1, by checking for other kinds of invalid addresses,
4755	     e.g. a bare reference to a virtual register.  This may confuse the
4756	     alpha though, which must handle this case differently.  */
4757          if (GET_CODE (operands[0]) == MEM
4758	      && !memory_address_p (GET_MODE (operands[0]),
4759		  		     XEXP (operands[0], 0)))
4760	    operands[0]
4761	      = replace_equiv_address (operands[0],
4762				       copy_to_reg (XEXP (operands[0], 0)));
4763          if (GET_CODE (operands[1]) == MEM
4764	      && !memory_address_p (GET_MODE (operands[1]),
4765				    XEXP (operands[1], 0)))
4766	     operands[1]
4767	       = replace_equiv_address (operands[1],
4768					copy_to_reg (XEXP (operands[1], 0)));
4769        }
4770      /* Handle loading a large integer during reload.  */
4771      else if (GET_CODE (operands[1]) == CONST_INT
4772	       && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4773        {
4774          /* Writing a constant to memory needs a scratch, which should
4775	     be handled with SECONDARY_RELOADs.  */
4776          if (GET_CODE (operands[0]) != REG)
4777	    abort ();
4778
4779          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4780          emit_insn (gen_movsi (operands[0], operands[1]));
4781          DONE;
4782       }
4783    }
4784  "
4785)
4786
4787
4788(define_insn "*arm_movqi_insn"
4789  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4790	(match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4791  "TARGET_ARM
4792   && (   register_operand (operands[0], QImode)
4793       || register_operand (operands[1], QImode))"
4794  "@
4795   mov%?\\t%0, %1
4796   mvn%?\\t%0, #%B1
4797   ldr%?b\\t%0, %1
4798   str%?b\\t%1, %0"
4799  [(set_attr "type" "*,*,load,store1")
4800   (set_attr "predicable" "yes")]
4801)
4802
4803(define_insn "*thumb_movqi_insn"
4804  [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4805	(match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4806  "TARGET_THUMB
4807   && (   register_operand (operands[0], QImode)
4808       || register_operand (operands[1], QImode))"
4809  "@
4810   add\\t%0, %1, #0
4811   ldrb\\t%0, %1
4812   strb\\t%1, %0
4813   mov\\t%0, %1
4814   mov\\t%0, %1
4815   mov\\t%0, %1"
4816  [(set_attr "length" "2")
4817   (set_attr "type" "*,load,store1,*,*,*")
4818   (set_attr "pool_range" "*,32,*,*,*,*")]
4819)
4820
4821(define_expand "movsf"
4822  [(set (match_operand:SF 0 "general_operand" "")
4823	(match_operand:SF 1 "general_operand" ""))]
4824  "TARGET_EITHER"
4825  "
4826  if (TARGET_ARM)
4827    {
4828      if (GET_CODE (operands[0]) == MEM)
4829        operands[1] = force_reg (SFmode, operands[1]);
4830    }
4831  else /* TARGET_THUMB */
4832    {
4833      if (!no_new_pseudos)
4834        {
4835           if (GET_CODE (operands[0]) != REG)
4836	     operands[1] = force_reg (SFmode, operands[1]);
4837        }
4838    }
4839  "
4840)
4841
4842(define_split
4843  [(set (match_operand:SF 0 "nonimmediate_operand" "")
4844	(match_operand:SF 1 "immediate_operand" ""))]
4845  "TARGET_ARM
4846   && !TARGET_HARD_FLOAT
4847   && reload_completed
4848   && GET_CODE (operands[1]) == CONST_DOUBLE"
4849  [(set (match_dup 2) (match_dup 3))]
4850  "
4851  operands[2] = gen_lowpart (SImode, operands[0]);
4852  operands[3] = gen_lowpart (SImode, operands[1]);
4853  if (operands[2] == 0 || operands[3] == 0)
4854    FAIL;
4855  "
4856)
4857
4858(define_insn "*arm_movsf_soft_insn"
4859  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4860	(match_operand:SF 1 "general_operand"  "r,mE,r"))]
4861  "TARGET_ARM
4862   && !TARGET_CIRRUS
4863   && TARGET_SOFT_FLOAT
4864   && (GET_CODE (operands[0]) != MEM
4865       || register_operand (operands[1], SFmode))"
4866  "@
4867   mov%?\\t%0, %1
4868   ldr%?\\t%0, %1\\t%@ float
4869   str%?\\t%1, %0\\t%@ float"
4870  [(set_attr "length" "4,4,4")
4871   (set_attr "predicable" "yes")
4872   (set_attr "type" "*,load,store1")
4873   (set_attr "pool_range" "*,4096,*")
4874   (set_attr "neg_pool_range" "*,4084,*")]
4875)
4876
4877;;; ??? This should have alternatives for constants.
4878(define_insn "*thumb_movsf_insn"
4879  [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4880	(match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4881  "TARGET_THUMB
4882   && (   register_operand (operands[0], SFmode) 
4883       || register_operand (operands[1], SFmode))"
4884  "@
4885   add\\t%0, %1, #0
4886   ldmia\\t%1, {%0}
4887   stmia\\t%0, {%1}
4888   ldr\\t%0, %1
4889   str\\t%1, %0
4890   mov\\t%0, %1
4891   mov\\t%0, %1"
4892  [(set_attr "length" "2")
4893   (set_attr "type" "*,load,store1,load,store1,*,*")
4894   (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4895)
4896
4897(define_expand "movdf"
4898  [(set (match_operand:DF 0 "general_operand" "")
4899	(match_operand:DF 1 "general_operand" ""))]
4900  "TARGET_EITHER"
4901  "
4902  if (TARGET_ARM)
4903    {
4904      if (GET_CODE (operands[0]) == MEM)
4905        operands[1] = force_reg (DFmode, operands[1]);
4906    }
4907  else /* TARGET_THUMB */
4908    {
4909      if (!no_new_pseudos)
4910        {
4911          if (GET_CODE (operands[0]) != REG)
4912	    operands[1] = force_reg (DFmode, operands[1]);
4913        }
4914    }
4915  "
4916)
4917
4918;; Reloading a df mode value stored in integer regs to memory can require a
4919;; scratch reg.
4920(define_expand "reload_outdf"
4921  [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4922   (match_operand:DF 1 "s_register_operand" "r")
4923   (match_operand:SI 2 "s_register_operand" "=&r")]
4924  "TARGET_ARM"
4925  "
4926  {
4927    enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4928
4929    if (code == REG)
4930      operands[2] = XEXP (operands[0], 0);
4931    else if (code == POST_INC || code == PRE_DEC)
4932      {
4933	operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4934	operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4935	emit_insn (gen_movdi (operands[0], operands[1]));
4936	DONE;
4937      }
4938    else if (code == PRE_INC)
4939      {
4940	rtx reg = XEXP (XEXP (operands[0], 0), 0);
4941
4942	emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4943	operands[2] = reg;
4944      }
4945    else if (code == POST_DEC)
4946      operands[2] = XEXP (XEXP (operands[0], 0), 0);
4947    else
4948      emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4949			     XEXP (XEXP (operands[0], 0), 1)));
4950
4951    emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4952			    operands[1]));
4953
4954    if (code == POST_DEC)
4955      emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4956
4957    DONE;
4958  }"
4959)
4960
4961(define_insn "*movdf_soft_insn"
4962  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4963	(match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4964  "TARGET_ARM && TARGET_SOFT_FLOAT
4965   && !TARGET_CIRRUS
4966  "
4967  "* return output_move_double (operands);"
4968  [(set_attr "length" "8,8,8")
4969   (set_attr "type" "*,load,store2")
4970   (set_attr "pool_range" "1020")
4971   (set_attr "neg_pool_range" "1008")]
4972)
4973
4974;;; ??? This should have alternatives for constants.
4975;;; ??? This was originally identical to the movdi_insn pattern.
4976;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4977;;; thumb_reorg with a memory reference.
4978(define_insn "*thumb_movdf_insn"
4979  [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4980	(match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
4981  "TARGET_THUMB
4982   && (   register_operand (operands[0], DFmode)
4983       || register_operand (operands[1], DFmode))"
4984  "*
4985  switch (which_alternative)
4986    {
4987    default:
4988    case 0:
4989      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4990	return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4991      return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4992    case 1:
4993      return \"ldmia\\t%1, {%0, %H0}\";
4994    case 2:
4995      return \"stmia\\t%0, {%1, %H1}\";
4996    case 3:
4997      return thumb_load_double_from_address (operands);
4998    case 4:
4999      operands[2] = gen_rtx (MEM, SImode,
5000			     plus_constant (XEXP (operands[0], 0), 4));
5001      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5002      return \"\";
5003    case 5:
5004      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5005	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5006      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5007    }
5008  "
5009  [(set_attr "length" "4,2,2,6,4,4")
5010   (set_attr "type" "*,load,store2,load,store2,*")
5011   (set_attr "pool_range" "*,*,*,1020,*,*")]
5012)
5013
5014;; Vector Moves
5015(define_expand "movv2si"
5016  [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5017	(match_operand:V2SI 1 "general_operand" ""))]
5018  "TARGET_REALLY_IWMMXT"
5019{
5020})
5021
5022(define_expand "movv4hi"
5023  [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5024	(match_operand:V4HI 1 "general_operand" ""))]
5025  "TARGET_REALLY_IWMMXT"
5026{
5027})
5028
5029(define_expand "movv8qi"
5030  [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5031	(match_operand:V8QI 1 "general_operand" ""))]
5032  "TARGET_REALLY_IWMMXT"
5033{
5034})
5035
5036
5037;; load- and store-multiple insns
5038;; The arm can load/store any set of registers, provided that they are in
5039;; ascending order; but that is beyond GCC so stick with what it knows.
5040
5041(define_expand "load_multiple"
5042  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5043                          (match_operand:SI 1 "" ""))
5044                     (use (match_operand:SI 2 "" ""))])]
5045  "TARGET_ARM"
5046  "
5047  /* Support only fixed point registers.  */
5048  if (GET_CODE (operands[2]) != CONST_INT
5049      || INTVAL (operands[2]) > 14
5050      || INTVAL (operands[2]) < 2
5051      || GET_CODE (operands[1]) != MEM
5052      || GET_CODE (operands[0]) != REG
5053      || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5054      || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5055    FAIL;
5056
5057  operands[3]
5058    = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5059			     force_reg (SImode, XEXP (operands[1], 0)),
5060			     TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5061			     MEM_IN_STRUCT_P(operands[1]),
5062	                     MEM_SCALAR_P (operands[1]));
5063  "
5064)
5065
5066;; Load multiple with write-back
5067
5068(define_insn "*ldmsi_postinc4"
5069  [(match_parallel 0 "load_multiple_operation"
5070    [(set (match_operand:SI 1 "s_register_operand" "=r")
5071	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5072		   (const_int 16)))
5073     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5074	  (mem:SI (match_dup 2)))
5075     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5076	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5077     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5078	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5079     (set (match_operand:SI 6 "arm_hard_register_operand" "")
5080	  (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5081  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5082  "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5083  [(set_attr "type" "load")
5084   (set_attr "predicable" "yes")]
5085)
5086
5087(define_insn "*ldmsi_postinc3"
5088  [(match_parallel 0 "load_multiple_operation"
5089    [(set (match_operand:SI 1 "s_register_operand" "=r")
5090	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5091		   (const_int 12)))
5092     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5093	  (mem:SI (match_dup 2)))
5094     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5095	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5096     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5097	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5098  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5099  "ldm%?ia\\t%1!, {%3, %4, %5}"
5100  [(set_attr "type" "load")
5101   (set_attr "predicable" "yes")]
5102)
5103
5104(define_insn "*ldmsi_postinc2"
5105  [(match_parallel 0 "load_multiple_operation"
5106    [(set (match_operand:SI 1 "s_register_operand" "=r")
5107	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5108		   (const_int 8)))
5109     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5110	  (mem:SI (match_dup 2)))
5111     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5112	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5113  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5114  "ldm%?ia\\t%1!, {%3, %4}"
5115  [(set_attr "type" "load")
5116   (set_attr "predicable" "yes")]
5117)
5118
5119;; Ordinary load multiple
5120
5121(define_insn "*ldmsi4"
5122  [(match_parallel 0 "load_multiple_operation"
5123    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5124	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5125     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5126	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5127     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5128	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5129     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5130	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5131  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5132  "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5133  [(set_attr "type" "load")
5134   (set_attr "predicable" "yes")]
5135)
5136
5137(define_insn "*ldmsi3"
5138  [(match_parallel 0 "load_multiple_operation"
5139    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5140	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5141     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5142	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5143     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5144	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5145  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5146  "ldm%?ia\\t%1, {%2, %3, %4}"
5147  [(set_attr "type" "load")
5148   (set_attr "predicable" "yes")]
5149)
5150
5151(define_insn "*ldmsi2"
5152  [(match_parallel 0 "load_multiple_operation"
5153    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5154	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5155     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5156	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5157  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5158  "ldm%?ia\\t%1, {%2, %3}"
5159  [(set_attr "type" "load")
5160   (set_attr "predicable" "yes")]
5161)
5162
5163(define_expand "store_multiple"
5164  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5165                          (match_operand:SI 1 "" ""))
5166                     (use (match_operand:SI 2 "" ""))])]
5167  "TARGET_ARM"
5168  "
5169  /* Support only fixed point registers.  */
5170  if (GET_CODE (operands[2]) != CONST_INT
5171      || INTVAL (operands[2]) > 14
5172      || INTVAL (operands[2]) < 2
5173      || GET_CODE (operands[1]) != REG
5174      || GET_CODE (operands[0]) != MEM
5175      || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5176      || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5177    FAIL;
5178
5179  operands[3]
5180    = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5181			      force_reg (SImode, XEXP (operands[0], 0)),
5182			      TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5183			      MEM_IN_STRUCT_P(operands[0]), 
5184	                      MEM_SCALAR_P (operands[0]));
5185  "
5186)
5187
5188;; Store multiple with write-back
5189
5190(define_insn "*stmsi_postinc4"
5191  [(match_parallel 0 "store_multiple_operation"
5192    [(set (match_operand:SI 1 "s_register_operand" "=r")
5193	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5194		   (const_int 16)))
5195     (set (mem:SI (match_dup 2))
5196	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5197     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5198	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5199     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5200	  (match_operand:SI 5 "arm_hard_register_operand" ""))
5201     (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5202	  (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5203  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5204  "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5205  [(set_attr "predicable" "yes")
5206   (set_attr "type" "store4")]
5207)
5208
5209(define_insn "*stmsi_postinc3"
5210  [(match_parallel 0 "store_multiple_operation"
5211    [(set (match_operand:SI 1 "s_register_operand" "=r")
5212	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5213		   (const_int 12)))
5214     (set (mem:SI (match_dup 2))
5215	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5216     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5217	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5218     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5219	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5220  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5221  "stm%?ia\\t%1!, {%3, %4, %5}"
5222  [(set_attr "predicable" "yes")
5223   (set_attr "type" "store3")]
5224)
5225
5226(define_insn "*stmsi_postinc2"
5227  [(match_parallel 0 "store_multiple_operation"
5228    [(set (match_operand:SI 1 "s_register_operand" "=r")
5229	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5230		   (const_int 8)))
5231     (set (mem:SI (match_dup 2))
5232	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5233     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5234	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5235  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5236  "stm%?ia\\t%1!, {%3, %4}"
5237  [(set_attr "predicable" "yes")
5238   (set_attr "type" "store2")]
5239)
5240
5241;; Ordinary store multiple
5242
5243(define_insn "*stmsi4"
5244  [(match_parallel 0 "store_multiple_operation"
5245    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5246	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5247     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5248	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5249     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5250	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5251     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5252	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5253  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5254  "stm%?ia\\t%1, {%2, %3, %4, %5}"
5255  [(set_attr "predicable" "yes")
5256   (set_attr "type" "store4")]
5257)
5258
5259(define_insn "*stmsi3"
5260  [(match_parallel 0 "store_multiple_operation"
5261    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5262	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5263     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5264	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5265     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5266	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5267  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5268  "stm%?ia\\t%1, {%2, %3, %4}"
5269  [(set_attr "predicable" "yes")
5270   (set_attr "type" "store3")]
5271)
5272
5273(define_insn "*stmsi2"
5274  [(match_parallel 0 "store_multiple_operation"
5275    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5276	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5277     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5278	  (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5279  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5280  "stm%?ia\\t%1, {%2, %3}"
5281  [(set_attr "predicable" "yes")
5282   (set_attr "type" "store2")]
5283)
5284
5285;; Move a block of memory if it is word aligned and MORE than 2 words long.
5286;; We could let this apply for blocks of less than this, but it clobbers so
5287;; many registers that there is then probably a better way.
5288
5289(define_expand "movstrqi"
5290  [(match_operand:BLK 0 "general_operand" "")
5291   (match_operand:BLK 1 "general_operand" "")
5292   (match_operand:SI 2 "const_int_operand" "")
5293   (match_operand:SI 3 "const_int_operand" "")]
5294  "TARGET_EITHER"
5295  "
5296  if (TARGET_ARM)
5297    {
5298      if (arm_gen_movstrqi (operands))
5299        DONE;
5300      FAIL;
5301    }
5302  else /* TARGET_THUMB */
5303    {
5304      if (   INTVAL (operands[3]) != 4
5305          || INTVAL (operands[2]) > 48)
5306        FAIL;
5307
5308      thumb_expand_movstrqi (operands);
5309      DONE;
5310    }
5311  "
5312)
5313
5314;; Thumb block-move insns
5315
5316(define_insn "movmem12b"
5317  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5318	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5319   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5320	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5321   (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5322	(mem:SI (plus:SI (match_dup 3) (const_int 8))))
5323   (set (match_operand:SI 0 "register_operand" "=l")
5324	(plus:SI (match_dup 2) (const_int 12)))
5325   (set (match_operand:SI 1 "register_operand" "=l")
5326	(plus:SI (match_dup 3) (const_int 12)))
5327   (clobber (match_scratch:SI 4 "=&l"))
5328   (clobber (match_scratch:SI 5 "=&l"))
5329   (clobber (match_scratch:SI 6 "=&l"))]
5330  "TARGET_THUMB"
5331  "* return thumb_output_move_mem_multiple (3, operands);"
5332  [(set_attr "length" "4")
5333   ; This isn't entirely accurate...  It loads as well, but in terms of
5334   ; scheduling the following insn it is better to consider it as a store
5335   (set_attr "type" "store3")]
5336)
5337
5338(define_insn "movmem8b"
5339  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5340	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5341   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5342	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5343   (set (match_operand:SI 0 "register_operand" "=l")
5344	(plus:SI (match_dup 2) (const_int 8)))
5345   (set (match_operand:SI 1 "register_operand" "=l")
5346	(plus:SI (match_dup 3) (const_int 8)))
5347   (clobber (match_scratch:SI 4 "=&l"))
5348   (clobber (match_scratch:SI 5 "=&l"))]
5349  "TARGET_THUMB"
5350  "* return thumb_output_move_mem_multiple (2, operands);"
5351  [(set_attr "length" "4")
5352   ; This isn't entirely accurate...  It loads as well, but in terms of
5353   ; scheduling the following insn it is better to consider it as a store
5354   (set_attr "type" "store2")]
5355)
5356
5357
5358
5359;; Compare & branch insns
5360;; The range calculations are based as follows:
5361;; For forward branches, the address calculation returns the address of
5362;; the next instruction.  This is 2 beyond the branch instruction.
5363;; For backward branches, the address calculation returns the address of
5364;; the first instruction in this pattern (cmp).  This is 2 before the branch
5365;; instruction for the shortest sequence, and 4 before the branch instruction
5366;; if we have to jump around an unconditional branch.
5367;; To the basic branch range the PC offset must be added (this is +4).
5368;; So for forward branches we have 
5369;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5370;; And for backward branches we have 
5371;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5372;;
5373;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5374;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5375
5376(define_expand "cbranchsi4"
5377  [(set (pc) (if_then_else
5378	      (match_operator 0 "arm_comparison_operator"
5379	       [(match_operand:SI 1 "s_register_operand" "")
5380	        (match_operand:SI 2 "nonmemory_operand" "")])
5381	      (label_ref (match_operand 3 "" ""))
5382	      (pc)))]
5383  "TARGET_THUMB"
5384  "
5385  if (thumb_cmpneg_operand (operands[2], SImode))
5386    {
5387      emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5388					      operands[3], operands[0]));
5389      DONE;
5390    }
5391  if (!thumb_cmp_operand (operands[2], SImode))
5392    operands[2] = force_reg (SImode, operands[2]);
5393  ")
5394
5395(define_insn "*cbranchsi4_insn"
5396  [(set (pc) (if_then_else
5397	      (match_operator 0 "arm_comparison_operator"
5398	       [(match_operand:SI 1 "s_register_operand" "l,*h")
5399	        (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5400	      (label_ref (match_operand 3 "" ""))
5401	      (pc)))]
5402  "TARGET_THUMB"
5403  "*
5404  output_asm_insn (\"cmp\\t%1, %2\", operands);
5405
5406  switch (get_attr_length (insn))
5407    {
5408    case 4:  return \"b%d0\\t%l3\";
5409    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5410    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5411    }
5412  "
5413  [(set (attr "far_jump")
5414        (if_then_else
5415	    (eq_attr "length" "8")
5416	    (const_string "yes")
5417            (const_string "no")))
5418   (set (attr "length") 
5419        (if_then_else
5420	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5421	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5422	    (const_int 4)
5423	    (if_then_else
5424	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5425		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5426		(const_int 6)
5427		(const_int 8))))]
5428)
5429
5430(define_insn "cbranchsi4_scratch"
5431  [(set (pc) (if_then_else
5432	      (match_operator 4 "arm_comparison_operator"
5433	       [(match_operand:SI 1 "s_register_operand" "l,0")
5434	        (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5435	      (label_ref (match_operand 3 "" ""))
5436	      (pc)))
5437   (clobber (match_scratch:SI 0 "=l,l"))]
5438  "TARGET_THUMB"
5439  "*
5440  output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5441
5442  switch (get_attr_length (insn))
5443    {
5444    case 4:  return \"b%d4\\t%l3\";
5445    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5446    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5447    }
5448  "
5449  [(set (attr "far_jump")
5450        (if_then_else
5451	    (eq_attr "length" "8")
5452	    (const_string "yes")
5453            (const_string "no")))
5454   (set (attr "length") 
5455        (if_then_else
5456	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5457	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5458	    (const_int 4)
5459	    (if_then_else
5460	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5461		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5462		(const_int 6)
5463		(const_int 8))))]
5464)
5465(define_insn "*movsi_cbranchsi4"
5466  [(set (pc)
5467	(if_then_else
5468	 (match_operator 3 "arm_comparison_operator"
5469	  [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5470	   (const_int 0)])
5471	 (label_ref (match_operand 2 "" ""))
5472	 (pc)))
5473   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5474	(match_dup 1))]
5475  "TARGET_THUMB"
5476  "*{
5477  if (which_alternative == 0)
5478    output_asm_insn (\"cmp\t%0, #0\", operands);
5479  else if (which_alternative == 1)
5480    output_asm_insn (\"sub\t%0, %1, #0\", operands);
5481  else
5482    {
5483      output_asm_insn (\"cmp\t%1, #0\", operands);
5484      if (which_alternative == 2)
5485	output_asm_insn (\"mov\t%0, %1\", operands);
5486      else
5487	output_asm_insn (\"str\t%1, %0\", operands);
5488    }
5489  switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5490    {
5491    case 4:  return \"b%d3\\t%l2\";
5492    case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5493    default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5494    }
5495  }"
5496  [(set (attr "far_jump")
5497        (if_then_else
5498	    (ior (and (gt (symbol_ref ("which_alternative"))
5499	                  (const_int 1))
5500		      (eq_attr "length" "8"))
5501		 (eq_attr "length" "10"))
5502	    (const_string "yes")
5503            (const_string "no")))
5504   (set (attr "length")
5505     (if_then_else
5506       (le (symbol_ref ("which_alternative"))
5507		       (const_int 1))
5508       (if_then_else
5509	 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5510	      (le (minus (match_dup 2) (pc)) (const_int 256)))
5511	 (const_int 4)
5512	 (if_then_else
5513	   (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5514		(le (minus (match_dup 2) (pc)) (const_int 2048)))
5515	   (const_int 6)
5516	   (const_int 8)))
5517       (if_then_else
5518	 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5519	      (le (minus (match_dup 2) (pc)) (const_int 256)))
5520	 (const_int 6)
5521	 (if_then_else
5522	   (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5523		(le (minus (match_dup 2) (pc)) (const_int 2048)))
5524	   (const_int 8)
5525	   (const_int 10)))))]
5526)
5527
5528(define_insn "*negated_cbranchsi4"
5529  [(set (pc)
5530	(if_then_else
5531	 (match_operator 0 "arm_comparison_operator"
5532	  [(match_operand:SI 1 "s_register_operand" "l")
5533	   (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5534	 (label_ref (match_operand 3 "" ""))
5535	 (pc)))]
5536  "TARGET_THUMB"
5537  "*
5538  output_asm_insn (\"cmn\\t%1, %2\", operands);
5539  switch (get_attr_length (insn))
5540    {
5541    case 4:  return \"b%d0\\t%l3\";
5542    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5543    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5544    }
5545  "
5546  [(set (attr "far_jump")
5547        (if_then_else
5548	    (eq_attr "length" "8")
5549	    (const_string "yes")
5550            (const_string "no")))
5551   (set (attr "length") 
5552        (if_then_else
5553	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5554	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5555	    (const_int 4)
5556	    (if_then_else
5557	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5558		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5559		(const_int 6)
5560		(const_int 8))))]
5561)
5562
5563(define_insn "*tbit_cbranch"
5564  [(set (pc)
5565	(if_then_else
5566	 (match_operator 0 "equality_operator"
5567	  [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5568			    (const_int 1)
5569			    (match_operand:SI 2 "const_int_operand" "i"))
5570	   (const_int 0)])
5571	 (label_ref (match_operand 3 "" ""))
5572	 (pc)))
5573   (clobber (match_scratch:SI 4 "=l"))]
5574  "TARGET_THUMB"
5575  "*
5576  {
5577  rtx op[3];
5578  op[0] = operands[4];
5579  op[1] = operands[1];
5580  op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5581
5582  output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5583  switch (get_attr_length (insn))
5584    {
5585    case 4:  return \"b%d0\\t%l3\";
5586    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5587    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5588    }
5589  }"
5590  [(set (attr "far_jump")
5591        (if_then_else
5592	    (eq_attr "length" "8")
5593	    (const_string "yes")
5594            (const_string "no")))
5595   (set (attr "length") 
5596        (if_then_else
5597	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5598	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5599	    (const_int 4)
5600	    (if_then_else
5601	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5602		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5603		(const_int 6)
5604		(const_int 8))))]
5605)
5606  
5607(define_insn "*tstsi3_cbranch"
5608  [(set (pc)
5609	(if_then_else
5610	 (match_operator 3 "equality_operator"
5611	  [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5612		   (match_operand:SI 1 "s_register_operand" "l"))
5613	   (const_int 0)])
5614	 (label_ref (match_operand 2 "" ""))
5615	 (pc)))]
5616  "TARGET_THUMB"
5617  "*
5618  {
5619  output_asm_insn (\"tst\\t%0, %1\", operands);
5620  switch (get_attr_length (insn))
5621    {
5622    case 4:  return \"b%d3\\t%l2\";
5623    case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5624    default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5625    }
5626  }"
5627  [(set (attr "far_jump")
5628        (if_then_else
5629	    (eq_attr "length" "8")
5630	    (const_string "yes")
5631            (const_string "no")))
5632   (set (attr "length") 
5633        (if_then_else
5634	    (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5635	         (le (minus (match_dup 2) (pc)) (const_int 256)))
5636	    (const_int 4)
5637	    (if_then_else
5638	        (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5639		     (le (minus (match_dup 2) (pc)) (const_int 2048)))
5640		(const_int 6)
5641		(const_int 8))))]
5642)
5643  
5644(define_insn "*andsi3_cbranch"
5645  [(set (pc)
5646	(if_then_else
5647	 (match_operator 5 "equality_operator"
5648	  [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5649		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5650	   (const_int 0)])
5651	 (label_ref (match_operand 4 "" ""))
5652	 (pc)))
5653   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5654	(and:SI (match_dup 2) (match_dup 3)))
5655   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5656  "TARGET_THUMB"
5657  "*
5658  {
5659  if (which_alternative == 0)
5660    output_asm_insn (\"and\\t%0, %3\", operands);
5661  else if (which_alternative == 1)
5662    {
5663      output_asm_insn (\"and\\t%1, %3\", operands);
5664      output_asm_insn (\"mov\\t%0, %1\", operands);
5665    }
5666  else
5667    {
5668      output_asm_insn (\"and\\t%1, %3\", operands);
5669      output_asm_insn (\"str\\t%1, %0\", operands);
5670    }
5671
5672  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5673    {
5674    case 4:  return \"b%d5\\t%l4\";
5675    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5676    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5677    }
5678  }"
5679  [(set (attr "far_jump")
5680        (if_then_else
5681	    (ior (and (eq (symbol_ref ("which_alternative"))
5682	                  (const_int 0))
5683		      (eq_attr "length" "8"))
5684		 (eq_attr "length" "10"))
5685	    (const_string "yes")
5686            (const_string "no")))
5687   (set (attr "length")
5688     (if_then_else
5689       (eq (symbol_ref ("which_alternative"))
5690		       (const_int 0))
5691       (if_then_else
5692	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5693	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5694	 (const_int 4)
5695	 (if_then_else
5696	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5697		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5698	   (const_int 6)
5699	   (const_int 8)))
5700       (if_then_else
5701	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5702	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5703	 (const_int 6)
5704	 (if_then_else
5705	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5706		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5707	   (const_int 8)
5708	   (const_int 10)))))]
5709)
5710
5711(define_insn "*orrsi3_cbranch_scratch"
5712  [(set (pc)
5713	(if_then_else
5714	 (match_operator 4 "equality_operator"
5715	  [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5716		   (match_operand:SI 2 "s_register_operand" "l"))
5717	   (const_int 0)])
5718	 (label_ref (match_operand 3 "" ""))
5719	 (pc)))
5720   (clobber (match_scratch:SI 0 "=l"))]
5721  "TARGET_THUMB"
5722  "*
5723  {
5724  output_asm_insn (\"orr\\t%0, %2\", operands);
5725  switch (get_attr_length (insn))
5726    {
5727    case 4:  return \"b%d4\\t%l3\";
5728    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5729    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5730    }
5731  }"
5732  [(set (attr "far_jump")
5733        (if_then_else
5734	    (eq_attr "length" "8")
5735	    (const_string "yes")
5736            (const_string "no")))
5737   (set (attr "length") 
5738        (if_then_else
5739	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5740	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5741	    (const_int 4)
5742	    (if_then_else
5743	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5744		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5745		(const_int 6)
5746		(const_int 8))))]
5747)
5748  
5749(define_insn "*orrsi3_cbranch"
5750  [(set (pc)
5751	(if_then_else
5752	 (match_operator 5 "equality_operator"
5753	  [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5754		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5755	   (const_int 0)])
5756	 (label_ref (match_operand 4 "" ""))
5757	 (pc)))
5758   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5759	(ior:SI (match_dup 2) (match_dup 3)))
5760   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5761  "TARGET_THUMB"
5762  "*
5763  {
5764  if (which_alternative == 0)
5765    output_asm_insn (\"orr\\t%0, %3\", operands);
5766  else if (which_alternative == 1)
5767    {
5768      output_asm_insn (\"orr\\t%1, %3\", operands);
5769      output_asm_insn (\"mov\\t%0, %1\", operands);
5770    }
5771  else
5772    {
5773      output_asm_insn (\"orr\\t%1, %3\", operands);
5774      output_asm_insn (\"str\\t%1, %0\", operands);
5775    }
5776
5777  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5778    {
5779    case 4:  return \"b%d5\\t%l4\";
5780    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5781    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5782    }
5783  }"
5784  [(set (attr "far_jump")
5785        (if_then_else
5786	    (ior (and (eq (symbol_ref ("which_alternative"))
5787	                  (const_int 0))
5788		      (eq_attr "length" "8"))
5789		 (eq_attr "length" "10"))
5790	    (const_string "yes")
5791            (const_string "no")))
5792   (set (attr "length")
5793     (if_then_else
5794       (eq (symbol_ref ("which_alternative"))
5795		       (const_int 0))
5796       (if_then_else
5797	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5798	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5799	 (const_int 4)
5800	 (if_then_else
5801	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5802		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5803	   (const_int 6)
5804	   (const_int 8)))
5805       (if_then_else
5806	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5807	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5808	 (const_int 6)
5809	 (if_then_else
5810	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5811		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5812	   (const_int 8)
5813	   (const_int 10)))))]
5814)
5815
5816(define_insn "*xorsi3_cbranch_scratch"
5817  [(set (pc)
5818	(if_then_else
5819	 (match_operator 4 "equality_operator"
5820	  [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
5821		   (match_operand:SI 2 "s_register_operand" "l"))
5822	   (const_int 0)])
5823	 (label_ref (match_operand 3 "" ""))
5824	 (pc)))
5825   (clobber (match_scratch:SI 0 "=l"))]
5826  "TARGET_THUMB"
5827  "*
5828  {
5829  output_asm_insn (\"eor\\t%0, %2\", operands);
5830  switch (get_attr_length (insn))
5831    {
5832    case 4:  return \"b%d4\\t%l3\";
5833    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5834    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5835    }
5836  }"
5837  [(set (attr "far_jump")
5838        (if_then_else
5839	    (eq_attr "length" "8")
5840	    (const_string "yes")
5841            (const_string "no")))
5842   (set (attr "length") 
5843        (if_then_else
5844	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5845	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5846	    (const_int 4)
5847	    (if_then_else
5848	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5849		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5850		(const_int 6)
5851		(const_int 8))))]
5852)
5853  
5854(define_insn "*xorsi3_cbranch"
5855  [(set (pc)
5856	(if_then_else
5857	 (match_operator 5 "equality_operator"
5858	  [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5859		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5860	   (const_int 0)])
5861	 (label_ref (match_operand 4 "" ""))
5862	 (pc)))
5863   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5864	(xor:SI (match_dup 2) (match_dup 3)))
5865   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5866  "TARGET_THUMB"
5867  "*
5868  {
5869  if (which_alternative == 0)
5870    output_asm_insn (\"eor\\t%0, %3\", operands);
5871  else if (which_alternative == 1)
5872    {
5873      output_asm_insn (\"eor\\t%1, %3\", operands);
5874      output_asm_insn (\"mov\\t%0, %1\", operands);
5875    }
5876  else
5877    {
5878      output_asm_insn (\"eor\\t%1, %3\", operands);
5879      output_asm_insn (\"str\\t%1, %0\", operands);
5880    }
5881
5882  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5883    {
5884    case 4:  return \"b%d5\\t%l4\";
5885    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5886    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5887    }
5888  }"
5889  [(set (attr "far_jump")
5890        (if_then_else
5891	    (ior (and (eq (symbol_ref ("which_alternative"))
5892	                  (const_int 0))
5893		      (eq_attr "length" "8"))
5894		 (eq_attr "length" "10"))
5895	    (const_string "yes")
5896            (const_string "no")))
5897   (set (attr "length")
5898     (if_then_else
5899       (eq (symbol_ref ("which_alternative"))
5900		       (const_int 0))
5901       (if_then_else
5902	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5903	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5904	 (const_int 4)
5905	 (if_then_else
5906	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5907		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5908	   (const_int 6)
5909	   (const_int 8)))
5910       (if_then_else
5911	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5912	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5913	 (const_int 6)
5914	 (if_then_else
5915	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5916		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5917	   (const_int 8)
5918	   (const_int 10)))))]
5919)
5920
5921(define_insn "*bicsi3_cbranch_scratch"
5922  [(set (pc)
5923	(if_then_else
5924	 (match_operator 4 "equality_operator"
5925	  [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
5926		   (match_operand:SI 1 "s_register_operand" "0"))
5927	   (const_int 0)])
5928	 (label_ref (match_operand 3 "" ""))
5929	 (pc)))
5930   (clobber (match_scratch:SI 0 "=l"))]
5931  "TARGET_THUMB"
5932  "*
5933  {
5934  output_asm_insn (\"bic\\t%0, %2\", operands);
5935  switch (get_attr_length (insn))
5936    {
5937    case 4:  return \"b%d4\\t%l3\";
5938    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5939    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5940    }
5941  }"
5942  [(set (attr "far_jump")
5943        (if_then_else
5944	    (eq_attr "length" "8")
5945	    (const_string "yes")
5946            (const_string "no")))
5947   (set (attr "length") 
5948        (if_then_else
5949	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5950	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5951	    (const_int 4)
5952	    (if_then_else
5953	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5954		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5955		(const_int 6)
5956		(const_int 8))))]
5957)
5958  
5959(define_insn "*bicsi3_cbranch"
5960  [(set (pc)
5961	(if_then_else
5962	 (match_operator 5 "equality_operator"
5963	  [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5964		   (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
5965	   (const_int 0)])
5966	 (label_ref (match_operand 4 "" ""))
5967	 (pc)))
5968   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5969	(and:SI (not:SI (match_dup 3)) (match_dup 2)))
5970   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5971  "TARGET_THUMB"
5972  "*
5973  {
5974  if (which_alternative == 0)
5975    output_asm_insn (\"bic\\t%0, %3\", operands);
5976  else if (which_alternative == 1)
5977    {
5978      output_asm_insn (\"bic\\t%1, %3\", operands);
5979      output_asm_insn (\"mov\\t%0, %1\", operands);
5980    }
5981  else
5982    {
5983      output_asm_insn (\"bic\\t%1, %3\", operands);
5984      output_asm_insn (\"str\\t%1, %0\", operands);
5985    }
5986
5987  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5988    {
5989    case 4:  return \"b%d5\\t%l4\";
5990    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5991    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5992    }
5993  }"
5994  [(set (attr "far_jump")
5995        (if_then_else
5996	    (ior (and (eq (symbol_ref ("which_alternative"))
5997	                  (const_int 0))
5998		      (eq_attr "length" "8"))
5999		 (eq_attr "length" "10"))
6000	    (const_string "yes")
6001            (const_string "no")))
6002   (set (attr "length")
6003     (if_then_else
6004       (eq (symbol_ref ("which_alternative"))
6005		       (const_int 0))
6006       (if_then_else
6007	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6008	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6009	 (const_int 4)
6010	 (if_then_else
6011	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6012		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6013	   (const_int 6)
6014	   (const_int 8)))
6015       (if_then_else
6016	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6017	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6018	 (const_int 6)
6019	 (if_then_else
6020	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6021		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6022	   (const_int 8)
6023	   (const_int 10)))))]
6024)
6025
6026(define_insn "*cbranchne_decr1"
6027  [(set (pc)
6028	(if_then_else (match_operator 3 "equality_operator"
6029		       [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6030		        (const_int 0)])
6031		      (label_ref (match_operand 4 "" ""))
6032		      (pc)))
6033   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6034	(plus:SI (match_dup 2) (const_int -1)))
6035   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6036  "TARGET_THUMB"
6037  "*
6038   {
6039     rtx cond[2];
6040     cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6041				? GEU : LTU),
6042			       VOIDmode, operands[2], const1_rtx);
6043     cond[1] = operands[4];
6044
6045     if (which_alternative == 0)
6046       output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6047     else if (which_alternative == 1)
6048       {
6049	 /* We must provide an alternative for a hi reg because reload 
6050	    cannot handle output reloads on a jump instruction, but we
6051	    can't subtract into that.  Fortunately a mov from lo to hi
6052	    does not clobber the condition codes.  */
6053	 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6054	 output_asm_insn (\"mov\\t%0, %1\", operands);
6055       }
6056     else
6057       {
6058	 /* Similarly, but the target is memory.  */
6059	 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6060	 output_asm_insn (\"str\\t%1, %0\", operands);
6061       }
6062
6063     switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6064       {
6065	 case 4:
6066	   output_asm_insn (\"b%d0\\t%l1\", cond);
6067	   return \"\";
6068	 case 6:
6069	   output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6070	   return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6071	 default:
6072	   output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6073	   return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6074       }
6075   }
6076  "
6077  [(set (attr "far_jump")
6078        (if_then_else
6079	    (ior (and (eq (symbol_ref ("which_alternative"))
6080	                  (const_int 0))
6081		      (eq_attr "length" "8"))
6082		 (eq_attr "length" "10"))
6083	    (const_string "yes")
6084            (const_string "no")))
6085   (set_attr_alternative "length"
6086      [
6087       ;; Alternative 0
6088       (if_then_else
6089	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6090	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6091	 (const_int 4)
6092	 (if_then_else
6093	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6094		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6095	   (const_int 6)
6096	   (const_int 8)))
6097       ;; Alternative 1
6098       (if_then_else
6099	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6100	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6101	 (const_int 6)
6102	 (if_then_else
6103	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6104		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6105	   (const_int 8)
6106	   (const_int 10)))
6107       ;; Alternative 2
6108       (if_then_else
6109	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6110	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6111	 (const_int 6)
6112	 (if_then_else
6113	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6114		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6115	   (const_int 8)
6116	   (const_int 10)))
6117       ;; Alternative 3
6118       (if_then_else
6119	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6120	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6121	 (const_int 6)
6122	 (if_then_else
6123	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6124		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6125	   (const_int 8)
6126	   (const_int 10)))])]
6127)
6128
6129(define_insn "*addsi3_cbranch"
6130  [(set (pc)
6131	(if_then_else
6132	 (match_operator 4 "comparison_operator"
6133	  [(plus:SI
6134	    (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6135	    (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6136	   (const_int 0)])
6137	 (label_ref (match_operand 5 "" ""))
6138	 (pc)))
6139   (set
6140    (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6141    (plus:SI (match_dup 2) (match_dup 3)))
6142   (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6143  "TARGET_THUMB
6144   && (GET_CODE (operands[4]) == EQ
6145       || GET_CODE (operands[4]) == NE
6146       || GET_CODE (operands[4]) == GE
6147       || GET_CODE (operands[4]) == LT)"
6148  "*
6149   {
6150     rtx cond[3];
6151
6152     
6153     cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6154     cond[1] = operands[2];
6155     cond[2] = operands[3];
6156
6157     if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6158       output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6159     else
6160       output_asm_insn (\"add\\t%0, %1, %2\", cond);
6161
6162     if (which_alternative >= 3
6163	 && which_alternative < 4)
6164       output_asm_insn (\"mov\\t%0, %1\", operands);
6165     else if (which_alternative >= 4)
6166       output_asm_insn (\"str\\t%1, %0\", operands);
6167
6168     switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6169       {
6170	 case 4:
6171	   return \"b%d4\\t%l5\";
6172	 case 6:
6173	   return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6174	 default:
6175	   return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6176       }
6177   }
6178  "
6179  [(set (attr "far_jump")
6180        (if_then_else
6181	    (ior (and (lt (symbol_ref ("which_alternative"))
6182	                  (const_int 3))
6183		      (eq_attr "length" "8"))
6184		 (eq_attr "length" "10"))
6185	    (const_string "yes")
6186            (const_string "no")))
6187   (set (attr "length")
6188     (if_then_else
6189       (lt (symbol_ref ("which_alternative"))
6190		       (const_int 3))
6191       (if_then_else
6192	 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6193	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6194	 (const_int 4)
6195	 (if_then_else
6196	   (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6197		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6198	   (const_int 6)
6199	   (const_int 8)))
6200       (if_then_else
6201	 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6202	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6203	 (const_int 6)
6204	 (if_then_else
6205	   (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6206		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6207	   (const_int 8)
6208	   (const_int 10)))))]
6209)
6210
6211(define_insn "*addsi3_cbranch_scratch"
6212  [(set (pc)
6213	(if_then_else
6214	 (match_operator 3 "comparison_operator"
6215	  [(plus:SI
6216	    (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6217	    (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6218	   (const_int 0)])
6219	 (label_ref (match_operand 4 "" ""))
6220	 (pc)))
6221   (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6222  "TARGET_THUMB
6223   && (GET_CODE (operands[3]) == EQ
6224       || GET_CODE (operands[3]) == NE
6225       || GET_CODE (operands[3]) == GE
6226       || GET_CODE (operands[3]) == LT)"
6227  "*
6228   {
6229     switch (which_alternative)
6230       {
6231       case 0:
6232	 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6233	 break;
6234       case 1:
6235	 output_asm_insn (\"cmn\t%1, %2\", operands);
6236	 break;
6237       case 3:
6238	 output_asm_insn (\"add\t%0, %1, %2\", operands);
6239	 break;
6240       case 4:
6241	 output_asm_insn (\"add\t%0, %0, %2\", operands);
6242	 break;
6243       }
6244
6245     switch (get_attr_length (insn))
6246       {
6247	 case 4:
6248	   return \"b%d3\\t%l4\";
6249	 case 6:
6250	   return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6251	 default:
6252	   return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6253       }
6254   }
6255  "
6256  [(set (attr "far_jump")
6257        (if_then_else
6258	    (eq_attr "length" "8")
6259	    (const_string "yes")
6260            (const_string "no")))
6261   (set (attr "length")
6262       (if_then_else
6263	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6264	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6265	 (const_int 4)
6266	 (if_then_else
6267	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6268		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6269	   (const_int 6)
6270	   (const_int 8))))]
6271)
6272
6273(define_insn "*subsi3_cbranch"
6274  [(set (pc)
6275	(if_then_else
6276	 (match_operator 4 "comparison_operator"
6277	  [(minus:SI
6278	    (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6279	    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6280	   (const_int 0)])
6281	 (label_ref (match_operand 5 "" ""))
6282	 (pc)))
6283   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6284	(minus:SI (match_dup 2) (match_dup 3)))
6285   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6286  "TARGET_THUMB
6287   && (GET_CODE (operands[4]) == EQ
6288       || GET_CODE (operands[4]) == NE
6289       || GET_CODE (operands[4]) == GE
6290       || GET_CODE (operands[4]) == LT)"
6291  "*
6292   {
6293     if (which_alternative == 0)
6294       output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6295     else if (which_alternative == 1)
6296       {
6297	 /* We must provide an alternative for a hi reg because reload 
6298	    cannot handle output reloads on a jump instruction, but we
6299	    can't subtract into that.  Fortunately a mov from lo to hi
6300	    does not clobber the condition codes.  */
6301	 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6302	 output_asm_insn (\"mov\\t%0, %1\", operands);
6303       }
6304     else
6305       {
6306	 /* Similarly, but the target is memory.  */
6307	 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6308	 output_asm_insn (\"str\\t%1, %0\", operands);
6309       }
6310
6311     switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6312       {
6313	 case 4:
6314	   return \"b%d4\\t%l5\";
6315	 case 6:
6316	   return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6317	 default:
6318	   return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6319       }
6320   }
6321  "
6322  [(set (attr "far_jump")
6323        (if_then_else
6324	    (ior (and (eq (symbol_ref ("which_alternative"))
6325	                  (const_int 0))
6326		      (eq_attr "length" "8"))
6327		 (eq_attr "length" "10"))
6328	    (const_string "yes")
6329            (const_string "no")))
6330   (set (attr "length")
6331     (if_then_else
6332       (eq (symbol_ref ("which_alternative"))
6333		       (const_int 0))
6334       (if_then_else
6335	 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6336	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6337	 (const_int 4)
6338	 (if_then_else
6339	   (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6340		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6341	   (const_int 6)
6342	   (const_int 8)))
6343       (if_then_else
6344	 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6345	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6346	 (const_int 6)
6347	 (if_then_else
6348	   (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6349		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6350	   (const_int 8)
6351	   (const_int 10)))))]
6352)
6353
6354(define_insn "*subsi3_cbranch_scratch"
6355  [(set (pc)
6356	(if_then_else
6357	 (match_operator 0 "arm_comparison_operator"
6358	  [(minus:SI (match_operand:SI 1 "register_operand" "l")
6359		     (match_operand:SI 2 "nonmemory_operand" "l"))
6360	   (const_int 0)])
6361	 (label_ref (match_operand 3 "" ""))
6362	 (pc)))]
6363  "TARGET_THUMB
6364   && (GET_CODE (operands[0]) == EQ
6365       || GET_CODE (operands[0]) == NE
6366       || GET_CODE (operands[0]) == GE
6367       || GET_CODE (operands[0]) == LT)"
6368  "*
6369  output_asm_insn (\"cmp\\t%1, %2\", operands);
6370  switch (get_attr_length (insn))
6371    {
6372    case 4:  return \"b%d0\\t%l3\";
6373    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6374    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6375    }
6376  "
6377  [(set (attr "far_jump")
6378        (if_then_else
6379	    (eq_attr "length" "8")
6380	    (const_string "yes")
6381            (const_string "no")))
6382   (set (attr "length") 
6383        (if_then_else
6384	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6385	         (le (minus (match_dup 3) (pc)) (const_int 256)))
6386	    (const_int 4)
6387	    (if_then_else
6388	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6389		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
6390		(const_int 6)
6391		(const_int 8))))]
6392)
6393
6394;; Comparison and test insns
6395
6396(define_expand "cmpsi"
6397  [(match_operand:SI 0 "s_register_operand" "")
6398   (match_operand:SI 1 "arm_add_operand" "")]
6399  "TARGET_ARM"
6400  "{
6401    arm_compare_op0 = operands[0];
6402    arm_compare_op1 = operands[1];
6403    DONE;
6404  }"
6405)
6406
6407(define_expand "cmpsf"
6408  [(match_operand:SF 0 "s_register_operand" "")
6409   (match_operand:SF 1 "fpa_rhs_operand" "")]
6410  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6411  "
6412  if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
6413    operands[1] = force_reg (SFmode, operands[1]);
6414
6415  arm_compare_op0 = operands[0];
6416  arm_compare_op1 = operands[1];
6417  DONE;
6418  "
6419)
6420
6421(define_expand "cmpdf"
6422  [(match_operand:DF 0 "s_register_operand" "")
6423   (match_operand:DF 1 "fpa_rhs_operand" "")]
6424  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6425  "
6426  if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
6427    operands[1] = force_reg (DFmode, operands[1]);
6428
6429  arm_compare_op0 = operands[0];
6430  arm_compare_op1 = operands[1];
6431  DONE;
6432  "
6433)
6434
6435(define_insn "*arm_cmpsi_insn"
6436  [(set (reg:CC CC_REGNUM)
6437	(compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6438		    (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6439  "TARGET_ARM"
6440  "@
6441   cmp%?\\t%0, %1
6442   cmn%?\\t%0, #%n1"
6443  [(set_attr "conds" "set")]
6444)
6445
6446(define_insn "*cmpsi_shiftsi"
6447  [(set (reg:CC CC_REGNUM)
6448	(compare:CC (match_operand:SI   0 "s_register_operand" "r")
6449		    (match_operator:SI  3 "shift_operator"
6450		     [(match_operand:SI 1 "s_register_operand" "r")
6451		      (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6452  "TARGET_ARM"
6453  "cmp%?\\t%0, %1%S3"
6454  [(set_attr "conds" "set")
6455   (set_attr "shift" "1")
6456   ]
6457)
6458
6459(define_insn "*cmpsi_shiftsi_swp"
6460  [(set (reg:CC_SWP CC_REGNUM)
6461	(compare:CC_SWP (match_operator:SI 3 "shift_operator"
6462			 [(match_operand:SI 1 "s_register_operand" "r")
6463			  (match_operand:SI 2 "reg_or_int_operand" "rM")])
6464			(match_operand:SI 0 "s_register_operand" "r")))]
6465  "TARGET_ARM"
6466  "cmp%?\\t%0, %1%S3"
6467  [(set_attr "conds" "set")
6468   (set_attr "shift" "1")
6469   ]
6470)
6471
6472(define_insn "*cmpsi_neg_shiftsi"
6473  [(set (reg:CC CC_REGNUM)
6474	(compare:CC (match_operand:SI 0 "s_register_operand" "r")
6475		    (neg:SI (match_operator:SI 3 "shift_operator"
6476			     [(match_operand:SI 1 "s_register_operand" "r")
6477			      (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6478  "TARGET_ARM"
6479  "cmn%?\\t%0, %1%S3"
6480  [(set_attr "conds" "set")
6481   (set_attr "shift" "1")
6482   ]
6483)
6484
6485;; Cirrus SF compare instruction
6486(define_insn "*cirrus_cmpsf"
6487  [(set (reg:CCFP CC_REGNUM)
6488	(compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6489		      (match_operand:SF 1 "cirrus_fp_register" "v")))]
6490  "TARGET_ARM && TARGET_CIRRUS"
6491  "cfcmps%?\\tr15, %V0, %V1"
6492  [(set_attr "type"   "mav_farith")
6493   (set_attr "cirrus" "compare")]
6494)
6495
6496;; Cirrus DF compare instruction
6497(define_insn "*cirrus_cmpdf"
6498  [(set (reg:CCFP CC_REGNUM)
6499	(compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6500		      (match_operand:DF 1 "cirrus_fp_register" "v")))]
6501  "TARGET_ARM && TARGET_CIRRUS"
6502  "cfcmpd%?\\tr15, %V0, %V1"
6503  [(set_attr "type"   "mav_farith")
6504   (set_attr "cirrus" "compare")]
6505)
6506
6507;; Cirrus DI compare instruction
6508(define_expand "cmpdi"
6509  [(match_operand:DI 0 "cirrus_fp_register" "")
6510   (match_operand:DI 1 "cirrus_fp_register" "")]
6511  "TARGET_ARM && TARGET_CIRRUS"
6512  "{
6513     arm_compare_op0 = operands[0];
6514     arm_compare_op1 = operands[1];
6515     DONE;
6516   }")
6517
6518(define_insn "*cirrus_cmpdi"
6519  [(set (reg:CC CC_REGNUM)
6520	(compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6521		    (match_operand:DI 1 "cirrus_fp_register" "v")))]
6522  "TARGET_ARM && TARGET_CIRRUS"
6523  "cfcmp64%?\\tr15, %V0, %V1"
6524  [(set_attr "type"   "mav_farith")
6525   (set_attr "cirrus" "compare")]
6526)
6527
6528; This insn allows redundant compares to be removed by cse, nothing should
6529; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6530; is deleted later on. The match_dup will match the mode here, so that
6531; mode changes of the condition codes aren't lost by this even though we don't
6532; specify what they are.
6533
6534(define_insn "*deleted_compare"
6535  [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6536  "TARGET_ARM"
6537  "\\t%@ deleted compare"
6538  [(set_attr "conds" "set")
6539   (set_attr "length" "0")]
6540)
6541
6542
6543;; Conditional branch insns
6544
6545(define_expand "beq"
6546  [(set (pc)
6547	(if_then_else (eq (match_dup 1) (const_int 0))
6548		      (label_ref (match_operand 0 "" ""))
6549		      (pc)))]
6550  "TARGET_ARM"
6551  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6552)
6553
6554(define_expand "bne"
6555  [(set (pc)
6556	(if_then_else (ne (match_dup 1) (const_int 0))
6557		      (label_ref (match_operand 0 "" ""))
6558		      (pc)))]
6559  "TARGET_ARM"
6560  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6561)
6562
6563(define_expand "bgt"
6564  [(set (pc)
6565	(if_then_else (gt (match_dup 1) (const_int 0))
6566		      (label_ref (match_operand 0 "" ""))
6567		      (pc)))]
6568  "TARGET_ARM"
6569  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6570)
6571
6572(define_expand "ble"
6573  [(set (pc)
6574	(if_then_else (le (match_dup 1) (const_int 0))
6575		      (label_ref (match_operand 0 "" ""))
6576		      (pc)))]
6577  "TARGET_ARM"
6578  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6579)
6580
6581(define_expand "bge"
6582  [(set (pc)
6583	(if_then_else (ge (match_dup 1) (const_int 0))
6584		      (label_ref (match_operand 0 "" ""))
6585		      (pc)))]
6586  "TARGET_ARM"
6587  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6588)
6589
6590(define_expand "blt"
6591  [(set (pc)
6592	(if_then_else (lt (match_dup 1) (const_int 0))
6593		      (label_ref (match_operand 0 "" ""))
6594		      (pc)))]
6595  "TARGET_ARM"
6596  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6597)
6598
6599(define_expand "bgtu"
6600  [(set (pc)
6601	(if_then_else (gtu (match_dup 1) (const_int 0))
6602		      (label_ref (match_operand 0 "" ""))
6603		      (pc)))]
6604  "TARGET_ARM"
6605  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6606)
6607
6608(define_expand "bleu"
6609  [(set (pc)
6610	(if_then_else (leu (match_dup 1) (const_int 0))
6611		      (label_ref (match_operand 0 "" ""))
6612		      (pc)))]
6613  "TARGET_ARM"
6614  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6615)
6616
6617(define_expand "bgeu"
6618  [(set (pc)
6619	(if_then_else (geu (match_dup 1) (const_int 0))
6620		      (label_ref (match_operand 0 "" ""))
6621		      (pc)))]
6622  "TARGET_ARM"
6623  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6624)
6625
6626(define_expand "bltu"
6627  [(set (pc)
6628	(if_then_else (ltu (match_dup 1) (const_int 0))
6629		      (label_ref (match_operand 0 "" ""))
6630		      (pc)))]
6631  "TARGET_ARM"
6632  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6633)
6634
6635(define_expand "bunordered"
6636  [(set (pc)
6637	(if_then_else (unordered (match_dup 1) (const_int 0))
6638		      (label_ref (match_operand 0 "" ""))
6639		      (pc)))]
6640  "TARGET_ARM && TARGET_HARD_FLOAT"
6641  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6642				      arm_compare_op1);"
6643)
6644
6645(define_expand "bordered"
6646  [(set (pc)
6647	(if_then_else (ordered (match_dup 1) (const_int 0))
6648		      (label_ref (match_operand 0 "" ""))
6649		      (pc)))]
6650  "TARGET_ARM && TARGET_HARD_FLOAT"
6651  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6652				      arm_compare_op1);"
6653)
6654
6655(define_expand "bungt"
6656  [(set (pc)
6657	(if_then_else (ungt (match_dup 1) (const_int 0))
6658		      (label_ref (match_operand 0 "" ""))
6659		      (pc)))]
6660  "TARGET_ARM && TARGET_HARD_FLOAT"
6661  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6662)
6663
6664(define_expand "bunlt"
6665  [(set (pc)
6666	(if_then_else (unlt (match_dup 1) (const_int 0))
6667		      (label_ref (match_operand 0 "" ""))
6668		      (pc)))]
6669  "TARGET_ARM && TARGET_HARD_FLOAT"
6670  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6671)
6672
6673(define_expand "bunge"
6674  [(set (pc)
6675	(if_then_else (unge (match_dup 1) (const_int 0))
6676		      (label_ref (match_operand 0 "" ""))
6677		      (pc)))]
6678  "TARGET_ARM && TARGET_HARD_FLOAT"
6679  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6680)
6681
6682(define_expand "bunle"
6683  [(set (pc)
6684	(if_then_else (unle (match_dup 1) (const_int 0))
6685		      (label_ref (match_operand 0 "" ""))
6686		      (pc)))]
6687  "TARGET_ARM && TARGET_HARD_FLOAT"
6688  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6689)
6690
6691;; The following two patterns need two branch instructions, since there is
6692;; no single instruction that will handle all cases.
6693(define_expand "buneq"
6694  [(set (pc)
6695	(if_then_else (uneq (match_dup 1) (const_int 0))
6696		      (label_ref (match_operand 0 "" ""))
6697		      (pc)))]
6698  "TARGET_ARM && TARGET_HARD_FLOAT"
6699  "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6700)
6701
6702(define_expand "bltgt"
6703  [(set (pc)
6704	(if_then_else (ltgt (match_dup 1) (const_int 0))
6705		      (label_ref (match_operand 0 "" ""))
6706		      (pc)))]
6707  "TARGET_ARM && TARGET_HARD_FLOAT"
6708  "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6709)
6710
6711;;
6712;; Patterns to match conditional branch insns.
6713;;
6714
6715; Special pattern to match UNEQ.
6716(define_insn "*arm_buneq"
6717  [(set (pc)
6718	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6719		      (label_ref (match_operand 0 "" ""))
6720		      (pc)))]
6721  "TARGET_ARM && TARGET_HARD_FLOAT"
6722  "*
6723  if (arm_ccfsm_state != 0)
6724    abort ();
6725
6726  return \"bvs\\t%l0\;beq\\t%l0\";
6727  "
6728  [(set_attr "conds" "jump_clob")
6729   (set_attr "length" "8")]
6730)
6731
6732; Special pattern to match LTGT.
6733(define_insn "*arm_bltgt"
6734  [(set (pc)
6735	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6736		      (label_ref (match_operand 0 "" ""))
6737		      (pc)))]
6738  "TARGET_ARM && TARGET_HARD_FLOAT"
6739  "*
6740  if (arm_ccfsm_state != 0)
6741    abort ();
6742
6743  return \"bmi\\t%l0\;bgt\\t%l0\";
6744  "
6745  [(set_attr "conds" "jump_clob")
6746   (set_attr "length" "8")]
6747)
6748
6749(define_insn "*arm_cond_branch"
6750  [(set (pc)
6751	(if_then_else (match_operator 1 "arm_comparison_operator"
6752		       [(match_operand 2 "cc_register" "") (const_int 0)])
6753		      (label_ref (match_operand 0 "" ""))
6754		      (pc)))]
6755  "TARGET_ARM"
6756  "*
6757  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6758    {
6759      arm_ccfsm_state += 2;
6760      return \"\";
6761    }
6762  return \"b%d1\\t%l0\";
6763  "
6764  [(set_attr "conds" "use")]
6765)
6766
6767; Special pattern to match reversed UNEQ.
6768(define_insn "*arm_buneq_reversed"
6769  [(set (pc)
6770	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6771		      (pc)
6772		      (label_ref (match_operand 0 "" ""))))]
6773  "TARGET_ARM && TARGET_HARD_FLOAT"
6774  "*
6775  if (arm_ccfsm_state != 0)
6776    abort ();
6777
6778  return \"bmi\\t%l0\;bgt\\t%l0\";
6779  "
6780  [(set_attr "conds" "jump_clob")
6781   (set_attr "length" "8")]
6782)
6783
6784; Special pattern to match reversed LTGT.
6785(define_insn "*arm_bltgt_reversed"
6786  [(set (pc)
6787	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6788		      (pc)
6789		      (label_ref (match_operand 0 "" ""))))]
6790  "TARGET_ARM && TARGET_HARD_FLOAT"
6791  "*
6792  if (arm_ccfsm_state != 0)
6793    abort ();
6794
6795  return \"bvs\\t%l0\;beq\\t%l0\";
6796  "
6797  [(set_attr "conds" "jump_clob")
6798   (set_attr "length" "8")]
6799)
6800
6801(define_insn "*arm_cond_branch_reversed"
6802  [(set (pc)
6803	(if_then_else (match_operator 1 "arm_comparison_operator"
6804		       [(match_operand 2 "cc_register" "") (const_int 0)])
6805		      (pc)
6806		      (label_ref (match_operand 0 "" ""))))]
6807  "TARGET_ARM"
6808  "*
6809  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6810    {
6811      arm_ccfsm_state += 2;
6812      return \"\";
6813    }
6814  return \"b%D1\\t%l0\";
6815  "
6816  [(set_attr "conds" "use")]
6817)
6818
6819
6820
6821; scc insns
6822
6823(define_expand "seq"
6824  [(set (match_operand:SI 0 "s_register_operand" "")
6825	(eq:SI (match_dup 1) (const_int 0)))]
6826  "TARGET_ARM"
6827  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6828)
6829
6830(define_expand "sne"
6831  [(set (match_operand:SI 0 "s_register_operand" "")
6832	(ne:SI (match_dup 1) (const_int 0)))]
6833  "TARGET_ARM"
6834  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6835)
6836
6837(define_expand "sgt"
6838  [(set (match_operand:SI 0 "s_register_operand" "")
6839	(gt:SI (match_dup 1) (const_int 0)))]
6840  "TARGET_ARM"
6841  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6842)
6843
6844(define_expand "sle"
6845  [(set (match_operand:SI 0 "s_register_operand" "")
6846	(le:SI (match_dup 1) (const_int 0)))]
6847  "TARGET_ARM"
6848  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6849)
6850
6851(define_expand "sge"
6852  [(set (match_operand:SI 0 "s_register_operand" "")
6853	(ge:SI (match_dup 1) (const_int 0)))]
6854  "TARGET_ARM"
6855  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6856)
6857
6858(define_expand "slt"
6859  [(set (match_operand:SI 0 "s_register_operand" "")
6860	(lt:SI (match_dup 1) (const_int 0)))]
6861  "TARGET_ARM"
6862  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6863)
6864
6865(define_expand "sgtu"
6866  [(set (match_operand:SI 0 "s_register_operand" "")
6867	(gtu:SI (match_dup 1) (const_int 0)))]
6868  "TARGET_ARM"
6869  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6870)
6871
6872(define_expand "sleu"
6873  [(set (match_operand:SI 0 "s_register_operand" "")
6874	(leu:SI (match_dup 1) (const_int 0)))]
6875  "TARGET_ARM"
6876  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6877)
6878
6879(define_expand "sgeu"
6880  [(set (match_operand:SI 0 "s_register_operand" "")
6881	(geu:SI (match_dup 1) (const_int 0)))]
6882  "TARGET_ARM"
6883  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6884)
6885
6886(define_expand "sltu"
6887  [(set (match_operand:SI 0 "s_register_operand" "")
6888	(ltu:SI (match_dup 1) (const_int 0)))]
6889  "TARGET_ARM"
6890  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6891)
6892
6893(define_expand "sunordered"
6894  [(set (match_operand:SI 0 "s_register_operand" "")
6895	(unordered:SI (match_dup 1) (const_int 0)))]
6896  "TARGET_ARM && TARGET_HARD_FLOAT"
6897  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6898				      arm_compare_op1);"
6899)
6900
6901(define_expand "sordered"
6902  [(set (match_operand:SI 0 "s_register_operand" "")
6903	(ordered:SI (match_dup 1) (const_int 0)))]
6904  "TARGET_ARM && TARGET_HARD_FLOAT"
6905  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6906				      arm_compare_op1);"
6907)
6908
6909(define_expand "sungt"
6910  [(set (match_operand:SI 0 "s_register_operand" "")
6911	(ungt:SI (match_dup 1) (const_int 0)))]
6912  "TARGET_ARM && TARGET_HARD_FLOAT"
6913  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6914				      arm_compare_op1);"
6915)
6916
6917(define_expand "sunge"
6918  [(set (match_operand:SI 0 "s_register_operand" "")
6919	(unge:SI (match_dup 1) (const_int 0)))]
6920  "TARGET_ARM && TARGET_HARD_FLOAT"
6921  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6922				      arm_compare_op1);"
6923)
6924
6925(define_expand "sunlt"
6926  [(set (match_operand:SI 0 "s_register_operand" "")
6927	(unlt:SI (match_dup 1) (const_int 0)))]
6928  "TARGET_ARM && TARGET_HARD_FLOAT"
6929  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6930				      arm_compare_op1);"
6931)
6932
6933(define_expand "sunle"
6934  [(set (match_operand:SI 0 "s_register_operand" "")
6935	(unle:SI (match_dup 1) (const_int 0)))]
6936  "TARGET_ARM && TARGET_HARD_FLOAT"
6937  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6938				      arm_compare_op1);"
6939)
6940
6941;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6942;;; simple ARM instructions. 
6943;
6944; (define_expand "suneq"
6945;   [(set (match_operand:SI 0 "s_register_operand" "")
6946; 	(uneq:SI (match_dup 1) (const_int 0)))]
6947;   "TARGET_ARM && TARGET_HARD_FLOAT"
6948;   "abort ();"
6949; )
6950;
6951; (define_expand "sltgt"
6952;   [(set (match_operand:SI 0 "s_register_operand" "")
6953; 	(ltgt:SI (match_dup 1) (const_int 0)))]
6954;   "TARGET_ARM && TARGET_HARD_FLOAT"
6955;   "abort ();"
6956; )
6957
6958(define_insn "*mov_scc"
6959  [(set (match_operand:SI 0 "s_register_operand" "=r")
6960	(match_operator:SI 1 "arm_comparison_operator"
6961	 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6962  "TARGET_ARM"
6963  "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6964  [(set_attr "conds" "use")
6965   (set_attr "length" "8")]
6966)
6967
6968(define_insn "*mov_negscc"
6969  [(set (match_operand:SI 0 "s_register_operand" "=r")
6970	(neg:SI (match_operator:SI 1 "arm_comparison_operator"
6971		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6972  "TARGET_ARM"
6973  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6974  [(set_attr "conds" "use")
6975   (set_attr "length" "8")]
6976)
6977
6978(define_insn "*mov_notscc"
6979  [(set (match_operand:SI 0 "s_register_operand" "=r")
6980	(not:SI (match_operator:SI 1 "arm_comparison_operator"
6981		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6982  "TARGET_ARM"
6983  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6984  [(set_attr "conds" "use")
6985   (set_attr "length" "8")]
6986)
6987
6988
6989;; Conditional move insns
6990
6991(define_expand "movsicc"
6992  [(set (match_operand:SI 0 "s_register_operand" "")
6993	(if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6994			 (match_operand:SI 2 "arm_not_operand" "")
6995			 (match_operand:SI 3 "arm_not_operand" "")))]
6996  "TARGET_ARM"
6997  "
6998  {
6999    enum rtx_code code = GET_CODE (operands[1]);
7000    rtx ccreg;
7001
7002    if (code == UNEQ || code == LTGT)
7003      FAIL;
7004
7005    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7006    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7007  }"
7008)
7009
7010(define_expand "movsfcc"
7011  [(set (match_operand:SF 0 "s_register_operand" "")
7012	(if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7013			 (match_operand:SF 2 "s_register_operand" "")
7014			 (match_operand:SF 3 "nonmemory_operand" "")))]
7015  "TARGET_ARM"
7016  "
7017  {
7018    enum rtx_code code = GET_CODE (operands[1]);
7019    rtx ccreg;
7020
7021    if (code == UNEQ || code == LTGT)
7022      FAIL;
7023
7024    /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7025       Otherwise, ensure it is a valid FP add operand.  */
7026    if ((!TARGET_HARD_FLOAT)
7027        || (!fpa_add_operand (operands[3], SFmode)))
7028      operands[3] = force_reg (SFmode, operands[3]);
7029
7030    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7031    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7032  }"
7033)
7034
7035(define_expand "movdfcc"
7036  [(set (match_operand:DF 0 "s_register_operand" "")
7037	(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7038			 (match_operand:DF 2 "s_register_operand" "")
7039			 (match_operand:DF 3 "fpa_add_operand" "")))]
7040  "TARGET_ARM && TARGET_HARD_FLOAT"
7041  "
7042  {
7043    enum rtx_code code = GET_CODE (operands[1]);
7044    rtx ccreg;
7045
7046    if (code == UNEQ || code == LTGT)
7047      FAIL;
7048
7049    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7050    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7051  }"
7052)
7053
7054(define_insn "*movsicc_insn"
7055  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7056	(if_then_else:SI
7057	 (match_operator 3 "arm_comparison_operator"
7058	  [(match_operand 4 "cc_register" "") (const_int 0)])
7059	 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7060	 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7061  "TARGET_ARM"
7062  "@
7063   mov%D3\\t%0, %2
7064   mvn%D3\\t%0, #%B2
7065   mov%d3\\t%0, %1
7066   mvn%d3\\t%0, #%B1
7067   mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7068   mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7069   mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7070   mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7071  [(set_attr "length" "4,4,4,4,8,8,8,8")
7072   (set_attr "conds" "use")]
7073)
7074
7075(define_insn "*movsfcc_soft_insn"
7076  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7077	(if_then_else:SF (match_operator 3 "arm_comparison_operator"
7078			  [(match_operand 4 "cc_register" "") (const_int 0)])
7079			 (match_operand:SF 1 "s_register_operand" "0,r")
7080			 (match_operand:SF 2 "s_register_operand" "r,0")))]
7081  "TARGET_ARM && TARGET_SOFT_FLOAT"
7082  "@
7083   mov%D3\\t%0, %2
7084   mov%d3\\t%0, %1"
7085  [(set_attr "conds" "use")]
7086)
7087
7088
7089;; Jump and linkage insns
7090
7091(define_expand "jump"
7092  [(set (pc)
7093	(label_ref (match_operand 0 "" "")))]
7094  "TARGET_EITHER"
7095  ""
7096)
7097
7098(define_insn "*arm_jump"
7099  [(set (pc)
7100	(label_ref (match_operand 0 "" "")))]
7101  "TARGET_ARM"
7102  "*
7103  {
7104    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7105      {
7106        arm_ccfsm_state += 2;
7107        return \"\";
7108      }
7109    return \"b%?\\t%l0\";
7110  }
7111  "
7112  [(set_attr "predicable" "yes")]
7113)
7114
7115(define_insn "*thumb_jump"
7116  [(set (pc)
7117	(label_ref (match_operand 0 "" "")))]
7118  "TARGET_THUMB"
7119  "*
7120  if (get_attr_length (insn) == 2)
7121    return \"b\\t%l0\";
7122  return \"bl\\t%l0\\t%@ far jump\";
7123  "
7124  [(set (attr "far_jump")
7125        (if_then_else
7126	    (eq_attr "length" "4")
7127	    (const_string "yes")
7128	    (const_string "no")))
7129   (set (attr "length") 
7130        (if_then_else
7131	    (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
7132		 (le (minus (match_dup 0) (pc)) (const_int 2044)))
7133  	    (const_int 2)
7134	    (const_int 4)))]
7135)
7136
7137(define_expand "call"
7138  [(parallel [(call (match_operand 0 "memory_operand" "")
7139	            (match_operand 1 "general_operand" ""))
7140	      (use (match_operand 2 "" ""))
7141	      (clobber (reg:SI LR_REGNUM))])]
7142  "TARGET_EITHER"
7143  "
7144  {
7145    rtx callee;
7146    
7147    /* In an untyped call, we can get NULL for operand 2.  */
7148    if (operands[2] == NULL_RTX)
7149      operands[2] = const0_rtx;
7150      
7151    /* This is to decide if we should generate indirect calls by loading the
7152       32 bit address of the callee into a register before performing the
7153       branch and link.  operand[2] encodes the long_call/short_call
7154       attribute of the function being called.  This attribute is set whenever
7155       __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7156       is used, and the short_call attribute can also be set if function is
7157       declared as static or if it has already been defined in the current
7158       compilation unit.  See arm.c and arm.h for info about this.  The third
7159       parameter to arm_is_longcall_p is used to tell it which pattern
7160       invoked it.  */
7161    callee  = XEXP (operands[0], 0);
7162    
7163    if (GET_CODE (callee) != REG
7164       && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7165      XEXP (operands[0], 0) = force_reg (Pmode, callee);
7166  }"
7167)
7168
7169(define_insn "*call_reg"
7170  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7171         (match_operand 1 "" ""))
7172   (use (match_operand 2 "" ""))
7173   (clobber (reg:SI LR_REGNUM))]
7174  "TARGET_ARM"
7175  "*
7176  return output_call (operands);
7177  "
7178  ;; length is worst case, normally it is only two
7179  [(set_attr "length" "12")
7180   (set_attr "type" "call")]
7181)
7182
7183(define_insn "*call_mem"
7184  [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7185	 (match_operand 1 "" ""))
7186   (use (match_operand 2 "" ""))
7187   (clobber (reg:SI LR_REGNUM))]
7188  "TARGET_ARM"
7189  "*
7190  return output_call_mem (operands);
7191  "
7192  [(set_attr "length" "12")
7193   (set_attr "type" "call")]
7194)
7195
7196(define_insn "*call_indirect"
7197  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7198	 (match_operand 1 "" ""))
7199   (use (match_operand 2 "" ""))
7200   (clobber (reg:SI LR_REGNUM))]
7201  "TARGET_THUMB"
7202  "*
7203  {
7204    if (TARGET_CALLER_INTERWORKING)
7205      return \"bl\\t%__interwork_call_via_%0\";
7206    else
7207      return \"bl\\t%__call_via_%0\";
7208  }"
7209  [(set_attr "type" "call")]
7210)
7211
7212(define_insn "*call_value_indirect"
7213  [(set (match_operand 0 "" "")
7214	(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7215	      (match_operand 2 "" "")))
7216   (use (match_operand 3 "" ""))
7217   (clobber (reg:SI LR_REGNUM))]
7218  "TARGET_THUMB"
7219  "*
7220  {
7221    if (TARGET_CALLER_INTERWORKING)
7222      return \"bl\\t%__interwork_call_via_%1\";
7223    else
7224      return \"bl\\t%__call_via_%1\";
7225  }"
7226  [(set_attr "type" "call")]
7227)
7228
7229(define_expand "call_value"
7230  [(parallel [(set (match_operand       0 "" "")
7231	           (call (match_operand 1 "memory_operand" "")
7232		         (match_operand 2 "general_operand" "")))
7233	      (use (match_operand 3 "" ""))
7234	      (clobber (reg:SI LR_REGNUM))])]
7235  "TARGET_EITHER"
7236  "
7237  {
7238    rtx callee = XEXP (operands[1], 0);
7239    
7240    /* In an untyped call, we can get NULL for operand 2.  */
7241    if (operands[3] == 0)
7242      operands[3] = const0_rtx;
7243      
7244    /* See the comment in define_expand \"call\".  */
7245    if (GET_CODE (callee) != REG
7246	&& arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7247      XEXP (operands[1], 0) = force_reg (Pmode, callee);
7248  }"
7249)
7250
7251(define_insn "*call_value_reg"
7252  [(set (match_operand 0 "" "")
7253        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7254	      (match_operand 2 "" "")))
7255   (use (match_operand 3 "" ""))
7256   (clobber (reg:SI LR_REGNUM))]
7257  "TARGET_ARM"
7258  "*
7259  return output_call (&operands[1]);
7260  "
7261  [(set_attr "length" "12")
7262   (set_attr "type" "call")]
7263)
7264
7265(define_insn "*call_value_mem"
7266  [(set (match_operand 0 "" "")
7267	(call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7268	      (match_operand 2 "" "")))
7269   (use (match_operand 3 "" ""))
7270   (clobber (reg:SI LR_REGNUM))]
7271  "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7272  "*
7273  return output_call_mem (&operands[1]);
7274  "
7275  [(set_attr "length" "12")
7276   (set_attr "type" "call")]
7277)
7278
7279;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7280;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7281
7282(define_insn "*call_symbol"
7283  [(call (mem:SI (match_operand:SI 0 "" ""))
7284	 (match_operand 1 "" ""))
7285   (use (match_operand 2 "" ""))
7286   (clobber (reg:SI LR_REGNUM))]
7287  "TARGET_ARM
7288   && (GET_CODE (operands[0]) == SYMBOL_REF)
7289   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7290  "*
7291  {
7292    return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7293  }"
7294  [(set_attr "type" "call")]
7295)
7296
7297(define_insn "*call_value_symbol"
7298  [(set (match_operand 0 "s_register_operand" "")
7299	(call (mem:SI (match_operand:SI 1 "" ""))
7300	(match_operand:SI 2 "" "")))
7301   (use (match_operand 3 "" ""))
7302   (clobber (reg:SI LR_REGNUM))]
7303  "TARGET_ARM
7304   && (GET_CODE (operands[1]) == SYMBOL_REF)
7305   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7306  "*
7307  {
7308    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7309  }"
7310  [(set_attr "type" "call")]
7311)
7312
7313(define_insn "*call_insn"
7314  [(call (mem:SI (match_operand:SI 0 "" ""))
7315	 (match_operand:SI 1 "" ""))
7316   (use (match_operand 2 "" ""))
7317   (clobber (reg:SI LR_REGNUM))]
7318  "TARGET_THUMB
7319   && GET_CODE (operands[0]) == SYMBOL_REF
7320   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7321  "bl\\t%a0"
7322  [(set_attr "length" "4")
7323   (set_attr "type" "call")]
7324)
7325
7326(define_insn "*call_value_insn"
7327  [(set (match_operand 0 "register_operand" "")
7328	(call (mem:SI (match_operand 1 "" ""))
7329	      (match_operand 2 "" "")))
7330   (use (match_operand 3 "" ""))
7331   (clobber (reg:SI LR_REGNUM))]
7332  "TARGET_THUMB
7333   && GET_CODE (operands[1]) == SYMBOL_REF
7334   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7335  "bl\\t%a1"
7336  [(set_attr "length" "4")
7337   (set_attr "type" "call")]
7338)
7339
7340;; We may also be able to do sibcalls for Thumb, but it's much harder...
7341(define_expand "sibcall"
7342  [(parallel [(call (match_operand 0 "memory_operand" "")
7343		    (match_operand 1 "general_operand" ""))
7344	      (return)
7345	      (use (match_operand 2 "" ""))])]
7346  "TARGET_ARM"
7347  "
7348  {
7349    if (operands[2] == NULL_RTX)
7350      operands[2] = const0_rtx;
7351  }"
7352)
7353
7354(define_expand "sibcall_value"
7355  [(parallel [(set (match_operand 0 "register_operand" "")
7356		   (call (match_operand 1 "memory_operand" "")
7357			 (match_operand 2 "general_operand" "")))
7358	      (return)
7359	      (use (match_operand 3 "" ""))])]
7360  "TARGET_ARM"
7361  "
7362  {
7363    if (operands[3] == NULL_RTX)
7364      operands[3] = const0_rtx;
7365  }"
7366)
7367
7368(define_insn "*sibcall_insn"
7369 [(call (mem:SI (match_operand:SI 0 "" "X"))
7370	(match_operand 1 "" ""))
7371  (return)
7372  (use (match_operand 2 "" ""))]
7373  "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7374  "*
7375  return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7376  "
7377  [(set_attr "type" "call")]
7378)
7379
7380(define_insn "*sibcall_value_insn"
7381 [(set (match_operand 0 "s_register_operand" "")
7382       (call (mem:SI (match_operand:SI 1 "" "X"))
7383	     (match_operand 2 "" "")))
7384  (return)
7385  (use (match_operand 3 "" ""))]
7386  "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7387  "*
7388  return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7389  "
7390  [(set_attr "type" "call")]
7391)
7392
7393;; Often the return insn will be the same as loading from memory, so set attr
7394(define_insn "return"
7395  [(return)]
7396  "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7397  "*
7398  {
7399    if (arm_ccfsm_state == 2)
7400      {
7401        arm_ccfsm_state += 2;
7402        return \"\";
7403      }
7404    return output_return_instruction (const_true_rtx, TRUE, FALSE);
7405  }"
7406  [(set_attr "type" "load")
7407   (set_attr "length" "12")
7408   (set_attr "predicable" "yes")]
7409)
7410
7411(define_insn "*cond_return"
7412  [(set (pc)
7413        (if_then_else (match_operator 0 "arm_comparison_operator"
7414		       [(match_operand 1 "cc_register" "") (const_int 0)])
7415                      (return)
7416                      (pc)))]
7417  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7418  "*
7419  {
7420    if (arm_ccfsm_state == 2)
7421      {
7422        arm_ccfsm_state += 2;
7423        return \"\";
7424      }
7425    return output_return_instruction (operands[0], TRUE, FALSE);
7426  }"
7427  [(set_attr "conds" "use")
7428   (set_attr "length" "12")
7429   (set_attr "type" "load")]
7430)
7431
7432(define_insn "*cond_return_inverted"
7433  [(set (pc)
7434        (if_then_else (match_operator 0 "arm_comparison_operator"
7435		       [(match_operand 1 "cc_register" "") (const_int 0)])
7436                      (pc)
7437		      (return)))]
7438  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7439  "*
7440  {
7441    if (arm_ccfsm_state == 2)
7442      {
7443        arm_ccfsm_state += 2;
7444        return \"\";
7445      }
7446    return output_return_instruction (operands[0], TRUE, TRUE);
7447  }"
7448  [(set_attr "conds" "use")
7449   (set_attr "type" "load")]
7450)
7451
7452;; Generate a sequence of instructions to determine if the processor is
7453;; in 26-bit or 32-bit mode, and return the appropriate return address
7454;; mask.
7455
7456(define_expand "return_addr_mask"
7457  [(set (match_dup 1)
7458      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7459		       (const_int 0)))
7460   (set (match_operand:SI 0 "s_register_operand" "")
7461      (if_then_else:SI (eq (match_dup 1) (const_int 0))
7462		       (const_int -1)
7463		       (const_int 67108860)))] ; 0x03fffffc
7464  "TARGET_ARM"
7465  "
7466  operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7467  ")
7468
7469(define_insn "*check_arch2"
7470  [(set (match_operand:CC_NOOV 0 "cc_register" "")
7471      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7472		       (const_int 0)))]
7473  "TARGET_ARM"
7474  "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7475  [(set_attr "length" "8")
7476   (set_attr "conds" "set")]
7477)
7478
7479;; Call subroutine returning any type.
7480
7481(define_expand "untyped_call"
7482  [(parallel [(call (match_operand 0 "" "")
7483		    (const_int 0))
7484	      (match_operand 1 "" "")
7485	      (match_operand 2 "" "")])]
7486  "TARGET_ARM"
7487  "
7488  {
7489    int i;
7490
7491    emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7492
7493    for (i = 0; i < XVECLEN (operands[2], 0); i++)
7494      {
7495	rtx set = XVECEXP (operands[2], 0, i);
7496
7497	emit_move_insn (SET_DEST (set), SET_SRC (set));
7498      }
7499
7500    /* The optimizer does not know that the call sets the function value
7501       registers we stored in the result block.  We avoid problems by
7502       claiming that all hard registers are used and clobbered at this
7503       point.  */
7504    emit_insn (gen_blockage ());
7505
7506    DONE;
7507  }"
7508)
7509
7510;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7511;; all of memory.  This blocks insns from being moved across this point.
7512
7513(define_insn "blockage"
7514  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7515  "TARGET_EITHER"
7516  ""
7517  [(set_attr "length" "0")
7518   (set_attr "type" "block")]
7519)
7520
7521(define_expand "casesi"
7522  [(match_operand:SI 0 "s_register_operand" "")	; index to jump on
7523   (match_operand:SI 1 "const_int_operand" "")	; lower bound
7524   (match_operand:SI 2 "const_int_operand" "")	; total range
7525   (match_operand:SI 3 "" "")			; table label
7526   (match_operand:SI 4 "" "")]			; Out of range label
7527  "TARGET_ARM"
7528  "
7529  {
7530    rtx reg;
7531    if (operands[1] != const0_rtx)
7532      {
7533	reg = gen_reg_rtx (SImode);
7534
7535	emit_insn (gen_addsi3 (reg, operands[0],
7536			       GEN_INT (-INTVAL (operands[1]))));
7537	operands[0] = reg;
7538      }
7539
7540    if (!const_ok_for_arm (INTVAL (operands[2])))
7541      operands[2] = force_reg (SImode, operands[2]);
7542
7543    emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7544					 operands[4]));
7545    DONE;
7546  }"
7547)
7548
7549;; The USE in this pattern is needed to tell flow analysis that this is
7550;; a CASESI insn.  It has no other purpose.
7551(define_insn "casesi_internal"
7552  [(parallel [(set (pc)
7553	       (if_then_else
7554		(leu (match_operand:SI 0 "s_register_operand" "r")
7555		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
7556		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7557				 (label_ref (match_operand 2 "" ""))))
7558		(label_ref (match_operand 3 "" ""))))
7559	      (clobber (reg:CC CC_REGNUM))
7560	      (use (label_ref (match_dup 2)))])]
7561  "TARGET_ARM"
7562  "*
7563    if (flag_pic)
7564      return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7565    return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7566  "
7567  [(set_attr "conds" "clob")
7568   (set_attr "length" "12")]
7569)
7570
7571(define_expand "indirect_jump"
7572  [(set (pc)
7573	(match_operand:SI 0 "s_register_operand" ""))]
7574  "TARGET_EITHER"
7575  ""
7576)
7577
7578(define_insn "*arm_indirect_jump"
7579  [(set (pc)
7580	(match_operand:SI 0 "s_register_operand" "r"))]
7581  "TARGET_ARM"
7582  "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7583  [(set_attr "predicable" "yes")]
7584)
7585
7586;; Although not supported by the define_expand above,
7587;; cse/combine may generate this form.
7588(define_insn "*load_indirect_jump"
7589  [(set (pc)
7590	(match_operand:SI 0 "memory_operand" "m"))]
7591  "TARGET_ARM"
7592  "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7593  [(set_attr "type" "load")
7594   (set_attr "pool_range" "4096")
7595   (set_attr "neg_pool_range" "4084")
7596   (set_attr "predicable" "yes")]
7597)
7598
7599(define_insn "*thumb_indirect_jump"
7600  [(set (pc)
7601	(match_operand:SI 0 "register_operand" "l*r"))]
7602  "TARGET_THUMB"
7603  "mov\\tpc, %0"
7604  [(set_attr "conds" "clob")
7605   (set_attr "length" "2")]
7606)
7607
7608
7609;; Misc insns
7610
7611(define_insn "nop"
7612  [(const_int 0)]
7613  "TARGET_EITHER"
7614  "*
7615  if (TARGET_ARM)
7616    return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7617  return  \"mov\\tr8, r8\";
7618  "
7619  [(set (attr "length")
7620	(if_then_else (eq_attr "is_thumb" "yes")
7621		      (const_int 2)
7622		      (const_int 4)))]
7623)
7624
7625
7626;; Patterns to allow combination of arithmetic, cond code and shifts
7627
7628(define_insn "*arith_shiftsi"
7629  [(set (match_operand:SI 0 "s_register_operand" "=r")
7630        (match_operator:SI 1 "shiftable_operator"
7631          [(match_operator:SI 3 "shift_operator"
7632             [(match_operand:SI 4 "s_register_operand" "r")
7633              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7634           (match_operand:SI 2 "s_register_operand" "r")]))]
7635  "TARGET_ARM"
7636  "%i1%?\\t%0, %2, %4%S3"
7637  [(set_attr "predicable" "yes")
7638   (set_attr "shift" "4")
7639   ]
7640)
7641
7642(define_split
7643  [(set (match_operand:SI 0 "s_register_operand" "")
7644	(match_operator:SI 1 "shiftable_operator"
7645	 [(match_operator:SI 2 "shiftable_operator"
7646	   [(match_operator:SI 3 "shift_operator"
7647	     [(match_operand:SI 4 "s_register_operand" "")
7648	      (match_operand:SI 5 "reg_or_int_operand" "")])
7649	    (match_operand:SI 6 "s_register_operand" "")])
7650	  (match_operand:SI 7 "arm_rhs_operand" "")]))
7651   (clobber (match_operand:SI 8 "s_register_operand" ""))]
7652  "TARGET_ARM"
7653  [(set (match_dup 8)
7654	(match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7655			 (match_dup 6)]))
7656   (set (match_dup 0)
7657	(match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7658  "")
7659
7660(define_insn "*arith_shiftsi_compare0"
7661  [(set (reg:CC_NOOV CC_REGNUM)
7662        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7663		          [(match_operator:SI 3 "shift_operator"
7664		            [(match_operand:SI 4 "s_register_operand" "r")
7665		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
7666		           (match_operand:SI 2 "s_register_operand" "r")])
7667			 (const_int 0)))
7668   (set (match_operand:SI 0 "s_register_operand" "=r")
7669	(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7670			 (match_dup 2)]))]
7671  "TARGET_ARM"
7672  "%i1%?s\\t%0, %2, %4%S3"
7673  [(set_attr "conds" "set")
7674   (set_attr "shift" "4")
7675   ]
7676)
7677
7678(define_insn "*arith_shiftsi_compare0_scratch"
7679  [(set (reg:CC_NOOV CC_REGNUM)
7680        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7681		          [(match_operator:SI 3 "shift_operator"
7682		            [(match_operand:SI 4 "s_register_operand" "r")
7683		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
7684		           (match_operand:SI 2 "s_register_operand" "r")])
7685			 (const_int 0)))
7686   (clobber (match_scratch:SI 0 "=r"))]
7687  "TARGET_ARM"
7688  "%i1%?s\\t%0, %2, %4%S3"
7689  [(set_attr "conds" "set")
7690   (set_attr "shift" "4")
7691   ]
7692)
7693
7694(define_insn "*sub_shiftsi"
7695  [(set (match_operand:SI 0 "s_register_operand" "=r")
7696	(minus:SI (match_operand:SI 1 "s_register_operand" "r")
7697		  (match_operator:SI 2 "shift_operator"
7698		   [(match_operand:SI 3 "s_register_operand" "r")
7699		    (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7700  "TARGET_ARM"
7701  "sub%?\\t%0, %1, %3%S2"
7702  [(set_attr "predicable" "yes")
7703   (set_attr "shift" "3")
7704   ]
7705)
7706
7707(define_insn "*sub_shiftsi_compare0"
7708  [(set (reg:CC_NOOV CC_REGNUM)
7709	(compare:CC_NOOV
7710	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7711		   (match_operator:SI 2 "shift_operator"
7712		    [(match_operand:SI 3 "s_register_operand" "r")
7713		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7714	 (const_int 0)))
7715   (set (match_operand:SI 0 "s_register_operand" "=r")
7716	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7717						 (match_dup 4)])))]
7718  "TARGET_ARM"
7719  "sub%?s\\t%0, %1, %3%S2"
7720  [(set_attr "conds" "set")
7721   (set_attr "shift" "3") 
7722   ]
7723)
7724
7725(define_insn "*sub_shiftsi_compare0_scratch"
7726  [(set (reg:CC_NOOV CC_REGNUM)
7727	(compare:CC_NOOV
7728	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7729		   (match_operator:SI 2 "shift_operator"
7730		    [(match_operand:SI 3 "s_register_operand" "r")
7731		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7732	 (const_int 0)))
7733   (clobber (match_scratch:SI 0 "=r"))]
7734  "TARGET_ARM"
7735  "sub%?s\\t%0, %1, %3%S2"
7736  [(set_attr "conds" "set")
7737   (set_attr "shift" "3") 
7738   ]
7739)
7740
7741
7742
7743(define_insn "*and_scc"
7744  [(set (match_operand:SI 0 "s_register_operand" "=r")
7745	(and:SI (match_operator:SI 1 "arm_comparison_operator"
7746		 [(match_operand 3 "cc_register" "") (const_int 0)])
7747		(match_operand:SI 2 "s_register_operand" "r")))]
7748  "TARGET_ARM"
7749  "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7750  [(set_attr "conds" "use")
7751   (set_attr "length" "8")]
7752)
7753
7754(define_insn "*ior_scc"
7755  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7756	(ior:SI (match_operator:SI 2 "arm_comparison_operator"
7757		 [(match_operand 3 "cc_register" "") (const_int 0)])
7758		(match_operand:SI 1 "s_register_operand" "0,?r")))]
7759  "TARGET_ARM"
7760  "@
7761   orr%d2\\t%0, %1, #1
7762   mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7763  [(set_attr "conds" "use")
7764   (set_attr "length" "4,8")]
7765)
7766
7767(define_insn "*compare_scc"
7768  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7769	(match_operator:SI 1 "arm_comparison_operator"
7770	 [(match_operand:SI 2 "s_register_operand" "r,r")
7771	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7772   (clobber (reg:CC CC_REGNUM))]
7773  "TARGET_ARM"
7774  "*
7775    if (operands[3] == const0_rtx)
7776      {
7777	if (GET_CODE (operands[1]) == LT)
7778	  return \"mov\\t%0, %2, lsr #31\";
7779
7780	if (GET_CODE (operands[1]) == GE)
7781	  return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7782
7783	if (GET_CODE (operands[1]) == EQ)
7784	  return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
7785      }
7786
7787    if (GET_CODE (operands[1]) == NE)
7788      {
7789        if (which_alternative == 1)
7790	  return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7791        return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7792      }
7793    if (which_alternative == 1)
7794      output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7795    else
7796      output_asm_insn (\"cmp\\t%2, %3\", operands);
7797    return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7798  "
7799  [(set_attr "conds" "clob")
7800   (set_attr "length" "12")]
7801)
7802
7803(define_insn "*cond_move"
7804  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7805	(if_then_else:SI (match_operator 3 "equality_operator"
7806			  [(match_operator 4 "arm_comparison_operator"
7807			    [(match_operand 5 "cc_register" "") (const_int 0)])
7808			   (const_int 0)])
7809			 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7810			 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7811  "TARGET_ARM"
7812  "*
7813    if (GET_CODE (operands[3]) == NE)
7814      {
7815        if (which_alternative != 1)
7816	  output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7817        if (which_alternative != 0)
7818	  output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7819        return \"\";
7820      }
7821    if (which_alternative != 0)
7822      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7823    if (which_alternative != 1)
7824      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7825    return \"\";
7826  "
7827  [(set_attr "conds" "use")
7828   (set_attr "length" "4,4,8")]
7829)
7830
7831(define_insn "*cond_arith"
7832  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7833        (match_operator:SI 5 "shiftable_operator" 
7834	 [(match_operator:SI 4 "arm_comparison_operator"
7835           [(match_operand:SI 2 "s_register_operand" "r,r")
7836	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7837          (match_operand:SI 1 "s_register_operand" "0,?r")]))
7838   (clobber (reg:CC CC_REGNUM))]
7839  "TARGET_ARM"
7840  "*
7841    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7842      return \"%i5\\t%0, %1, %2, lsr #31\";
7843
7844    output_asm_insn (\"cmp\\t%2, %3\", operands);
7845    if (GET_CODE (operands[5]) == AND)
7846      output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7847    else if (GET_CODE (operands[5]) == MINUS)
7848      output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7849    else if (which_alternative != 0)
7850      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7851    return \"%i5%d4\\t%0, %1, #1\";
7852  "
7853  [(set_attr "conds" "clob")
7854   (set_attr "length" "12")]
7855)
7856
7857(define_insn "*cond_sub"
7858  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7859        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7860		  (match_operator:SI 4 "arm_comparison_operator"
7861                   [(match_operand:SI 2 "s_register_operand" "r,r")
7862		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7863   (clobber (reg:CC CC_REGNUM))]
7864  "TARGET_ARM"
7865  "*
7866    output_asm_insn (\"cmp\\t%2, %3\", operands);
7867    if (which_alternative != 0)
7868      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7869    return \"sub%d4\\t%0, %1, #1\";
7870  "
7871  [(set_attr "conds" "clob")
7872   (set_attr "length" "8,12")]
7873)
7874
7875(define_insn "*cmp_ite0"
7876  [(set (match_operand 6 "dominant_cc_register" "")
7877	(compare
7878	 (if_then_else:SI
7879	  (match_operator 4 "arm_comparison_operator"
7880	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7881	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7882	  (match_operator:SI 5 "arm_comparison_operator"
7883	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7884	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7885	  (const_int 0))
7886	 (const_int 0)))]
7887  "TARGET_ARM"
7888  "*
7889  {
7890    static const char * const opcodes[4][2] =
7891    {
7892      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7893       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7894      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7895       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7896      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7897       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7898      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7899       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7900    };
7901    int swap =
7902      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7903
7904    return opcodes[which_alternative][swap];
7905  }"
7906  [(set_attr "conds" "set")
7907   (set_attr "length" "8")]
7908)
7909
7910(define_insn "*cmp_ite1"
7911  [(set (match_operand 6 "dominant_cc_register" "")
7912	(compare
7913	 (if_then_else:SI
7914	  (match_operator 4 "arm_comparison_operator"
7915	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7916	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7917	  (match_operator:SI 5 "arm_comparison_operator"
7918	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7919	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7920	  (const_int 1))
7921	 (const_int 0)))]
7922  "TARGET_ARM"
7923  "*
7924  {
7925    static const char * const opcodes[4][2] =
7926    {
7927      {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7928       \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7929      {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7930       \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7931      {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7932       \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7933      {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7934       \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7935    };
7936    int swap =
7937      comparison_dominates_p (GET_CODE (operands[5]),
7938			      reverse_condition (GET_CODE (operands[4])));
7939
7940    return opcodes[which_alternative][swap];
7941  }"
7942  [(set_attr "conds" "set")
7943   (set_attr "length" "8")]
7944)
7945
7946(define_insn "*cmp_and"
7947  [(set (match_operand 6 "dominant_cc_register" "")
7948	(compare
7949	 (and:SI
7950	  (match_operator 4 "arm_comparison_operator"
7951	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7952	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7953	  (match_operator:SI 5 "arm_comparison_operator"
7954	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7955	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7956	 (const_int 0)))]
7957  "TARGET_ARM"
7958  "*
7959  {
7960    static const char *const opcodes[4][2] =
7961    {
7962      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7963       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7964      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7965       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7966      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7967       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7968      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7969       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7970    };
7971    int swap =
7972      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7973
7974    return opcodes[which_alternative][swap];
7975  }"
7976  [(set_attr "conds" "set")
7977   (set_attr "predicable" "no")
7978   (set_attr "length" "8")]
7979)
7980
7981(define_insn "*cmp_ior"
7982  [(set (match_operand 6 "dominant_cc_register" "")
7983	(compare
7984	 (ior:SI
7985	  (match_operator 4 "arm_comparison_operator"
7986	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7987	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7988	  (match_operator:SI 5 "arm_comparison_operator"
7989	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7990	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7991	 (const_int 0)))]
7992  "TARGET_ARM"
7993  "*
7994{
7995  static const char *const opcodes[4][2] =
7996  {
7997    {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7998     \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7999    {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8000     \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8001    {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8002     \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8003    {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8004     \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8005  };
8006  int swap =
8007    comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8008
8009  return opcodes[which_alternative][swap];
8010}
8011"
8012  [(set_attr "conds" "set")
8013   (set_attr "length" "8")]
8014)
8015
8016(define_insn_and_split "*ior_scc_scc"
8017  [(set (match_operand:SI 0 "s_register_operand" "=r")
8018	(ior:SI (match_operator:SI 3 "arm_comparison_operator"
8019		 [(match_operand:SI 1 "s_register_operand" "r")
8020		  (match_operand:SI 2 "arm_add_operand" "rIL")])
8021		(match_operator:SI 6 "arm_comparison_operator"
8022		 [(match_operand:SI 4 "s_register_operand" "r")
8023		  (match_operand:SI 5 "arm_add_operand" "rIL")])))
8024   (clobber (reg:CC CC_REGNUM))]
8025  "TARGET_ARM
8026   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8027       != CCmode)"
8028  "#"
8029  "TARGET_ARM && reload_completed"
8030  [(set (match_dup 7)
8031	(compare
8032	 (ior:SI
8033	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8034	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8035	 (const_int 0)))
8036   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8037  "operands[7]
8038     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8039						  DOM_CC_X_OR_Y),
8040		    CC_REGNUM);"
8041  [(set_attr "conds" "clob")
8042   (set_attr "length" "16")])
8043
8044; If the above pattern is followed by a CMP insn, then the compare is 
8045; redundant, since we can rework the conditional instruction that follows.
8046(define_insn_and_split "*ior_scc_scc_cmp"
8047  [(set (match_operand 0 "dominant_cc_register" "")
8048	(compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8049			  [(match_operand:SI 1 "s_register_operand" "r")
8050			   (match_operand:SI 2 "arm_add_operand" "rIL")])
8051			 (match_operator:SI 6 "arm_comparison_operator"
8052			  [(match_operand:SI 4 "s_register_operand" "r")
8053			   (match_operand:SI 5 "arm_add_operand" "rIL")]))
8054		 (const_int 0)))
8055   (set (match_operand:SI 7 "s_register_operand" "=r")
8056	(ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8057		(match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8058  "TARGET_ARM"
8059  "#"
8060  "TARGET_ARM && reload_completed"
8061  [(set (match_dup 0)
8062	(compare
8063	 (ior:SI
8064	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8065	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8066	 (const_int 0)))
8067   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8068  ""
8069  [(set_attr "conds" "set")
8070   (set_attr "length" "16")])
8071
8072(define_insn_and_split "*and_scc_scc"
8073  [(set (match_operand:SI 0 "s_register_operand" "=r")
8074	(and:SI (match_operator:SI 3 "arm_comparison_operator"
8075		 [(match_operand:SI 1 "s_register_operand" "r")
8076		  (match_operand:SI 2 "arm_add_operand" "rIL")])
8077		(match_operator:SI 6 "arm_comparison_operator"
8078		 [(match_operand:SI 4 "s_register_operand" "r")
8079		  (match_operand:SI 5 "arm_add_operand" "rIL")])))
8080   (clobber (reg:CC CC_REGNUM))]
8081  "TARGET_ARM
8082   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8083       != CCmode)"
8084  "#"
8085  "TARGET_ARM && reload_completed
8086   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8087       != CCmode)"
8088  [(set (match_dup 7)
8089	(compare
8090	 (and:SI
8091	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8092	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8093	 (const_int 0)))
8094   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8095  "operands[7]
8096     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8097						  DOM_CC_X_AND_Y),
8098		    CC_REGNUM);"
8099  [(set_attr "conds" "clob")
8100   (set_attr "length" "16")])
8101
8102; If the above pattern is followed by a CMP insn, then the compare is 
8103; redundant, since we can rework the conditional instruction that follows.
8104(define_insn_and_split "*and_scc_scc_cmp"
8105  [(set (match_operand 0 "dominant_cc_register" "")
8106	(compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8107			  [(match_operand:SI 1 "s_register_operand" "r")
8108			   (match_operand:SI 2 "arm_add_operand" "rIL")])
8109			 (match_operator:SI 6 "arm_comparison_operator"
8110			  [(match_operand:SI 4 "s_register_operand" "r")
8111			   (match_operand:SI 5 "arm_add_operand" "rIL")]))
8112		 (const_int 0)))
8113   (set (match_operand:SI 7 "s_register_operand" "=r")
8114	(and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8115		(match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8116  "TARGET_ARM"
8117  "#"
8118  "TARGET_ARM && reload_completed"
8119  [(set (match_dup 0)
8120	(compare
8121	 (and:SI
8122	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8123	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8124	 (const_int 0)))
8125   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8126  ""
8127  [(set_attr "conds" "set")
8128   (set_attr "length" "16")])
8129
8130;; If there is no dominance in the comparison, then we can still save an
8131;; instruction in the AND case, since we can know that the second compare
8132;; need only zero the value if false (if true, then the value is already
8133;; correct).
8134(define_insn_and_split "*and_scc_scc_nodom"
8135  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8136	(and:SI (match_operator:SI 3 "arm_comparison_operator"
8137		 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8138		  (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8139		(match_operator:SI 6 "arm_comparison_operator"
8140		 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8141		  (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8142   (clobber (reg:CC CC_REGNUM))]
8143  "TARGET_ARM
8144   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8145       == CCmode)"
8146  "#"
8147  "TARGET_ARM && reload_completed"
8148  [(parallel [(set (match_dup 0)
8149		   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8150	      (clobber (reg:CC CC_REGNUM))])
8151   (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8152   (set (match_dup 0)
8153	(if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8154			 (match_dup 0)
8155			 (const_int 0)))]
8156  "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8157					      operands[4], operands[5]),
8158			      CC_REGNUM);
8159   operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8160				  operands[5]);"
8161  [(set_attr "conds" "clob")
8162   (set_attr "length" "20")])
8163
8164(define_split
8165  [(set (reg:CC_NOOV CC_REGNUM)
8166	(compare:CC_NOOV (ior:SI
8167			  (and:SI (match_operand:SI 0 "s_register_operand" "")
8168				  (const_int 1))
8169			  (match_operator:SI 1 "comparison_operator"
8170			   [(match_operand:SI 2 "s_register_operand" "")
8171			    (match_operand:SI 3 "arm_add_operand" "")]))
8172			 (const_int 0)))
8173   (clobber (match_operand:SI 4 "s_register_operand" ""))]
8174  "TARGET_ARM"
8175  [(set (match_dup 4)
8176	(ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8177		(match_dup 0)))
8178   (set (reg:CC_NOOV CC_REGNUM)
8179	(compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8180			 (const_int 0)))]
8181  "")
8182
8183(define_split
8184  [(set (reg:CC_NOOV CC_REGNUM)
8185	(compare:CC_NOOV (ior:SI
8186			  (match_operator:SI 1 "comparison_operator"
8187			   [(match_operand:SI 2 "s_register_operand" "")
8188			    (match_operand:SI 3 "arm_add_operand" "")])
8189			  (and:SI (match_operand:SI 0 "s_register_operand" "")
8190				  (const_int 1)))
8191			 (const_int 0)))
8192   (clobber (match_operand:SI 4 "s_register_operand" ""))]
8193  "TARGET_ARM"
8194  [(set (match_dup 4)
8195	(ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8196		(match_dup 0)))
8197   (set (reg:CC_NOOV CC_REGNUM)
8198	(compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8199			 (const_int 0)))]
8200  "")
8201
8202(define_insn "*negscc"
8203  [(set (match_operand:SI 0 "s_register_operand" "=r")
8204	(neg:SI (match_operator 3 "arm_comparison_operator"
8205		 [(match_operand:SI 1 "s_register_operand" "r")
8206		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8207   (clobber (reg:CC CC_REGNUM))]
8208  "TARGET_ARM"
8209  "*
8210  if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8211    return \"mov\\t%0, %1, asr #31\";
8212
8213  if (GET_CODE (operands[3]) == NE)
8214    return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8215
8216  if (GET_CODE (operands[3]) == GT)
8217    return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8218
8219  output_asm_insn (\"cmp\\t%1, %2\", operands);
8220  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8221  return \"mvn%d3\\t%0, #0\";
8222  "
8223  [(set_attr "conds" "clob")
8224   (set_attr "length" "12")]
8225)
8226
8227(define_insn "movcond"
8228  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8229	(if_then_else:SI
8230	 (match_operator 5 "arm_comparison_operator"
8231	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
8232	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8233	 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8234	 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8235   (clobber (reg:CC CC_REGNUM))]
8236  "TARGET_ARM"
8237  "*
8238  if (GET_CODE (operands[5]) == LT
8239      && (operands[4] == const0_rtx))
8240    {
8241      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8242	{
8243	  if (operands[2] == const0_rtx)
8244	    return \"and\\t%0, %1, %3, asr #31\";
8245	  return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8246	}
8247      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8248	{
8249	  if (operands[1] == const0_rtx)
8250	    return \"bic\\t%0, %2, %3, asr #31\";
8251	  return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8252	}
8253      /* The only case that falls through to here is when both ops 1 & 2
8254	 are constants.  */
8255    }
8256
8257  if (GET_CODE (operands[5]) == GE
8258      && (operands[4] == const0_rtx))
8259    {
8260      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8261	{
8262	  if (operands[2] == const0_rtx)
8263	    return \"bic\\t%0, %1, %3, asr #31\";
8264	  return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8265	}
8266      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8267	{
8268	  if (operands[1] == const0_rtx)
8269	    return \"and\\t%0, %2, %3, asr #31\";
8270	  return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8271	}
8272      /* The only case that falls through to here is when both ops 1 & 2
8273	 are constants.  */
8274    }
8275  if (GET_CODE (operands[4]) == CONST_INT
8276      && !const_ok_for_arm (INTVAL (operands[4])))
8277    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8278  else
8279    output_asm_insn (\"cmp\\t%3, %4\", operands);
8280  if (which_alternative != 0)
8281    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8282  if (which_alternative != 1)
8283    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8284  return \"\";
8285  "
8286  [(set_attr "conds" "clob")
8287   (set_attr "length" "8,8,12")]
8288)
8289
8290(define_insn "*ifcompare_plus_move"
8291  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8292	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8293			  [(match_operand:SI 4 "s_register_operand" "r,r")
8294			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8295			 (plus:SI
8296			  (match_operand:SI 2 "s_register_operand" "r,r")
8297			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8298			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8299   (clobber (reg:CC CC_REGNUM))]
8300  "TARGET_ARM"
8301  "#"
8302  [(set_attr "conds" "clob")
8303   (set_attr "length" "8,12")]
8304)
8305
8306(define_insn "*if_plus_move"
8307  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8308	(if_then_else:SI
8309	 (match_operator 4 "arm_comparison_operator"
8310	  [(match_operand 5 "cc_register" "") (const_int 0)])
8311	 (plus:SI
8312	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8313	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8314	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8315  "TARGET_ARM"
8316  "@
8317   add%d4\\t%0, %2, %3
8318   sub%d4\\t%0, %2, #%n3
8319   add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8320   sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8321  [(set_attr "conds" "use")
8322   (set_attr "length" "4,4,8,8")
8323   (set_attr "type" "*,*,*,*")]
8324)
8325
8326(define_insn "*ifcompare_move_plus"
8327  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8328	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8329			  [(match_operand:SI 4 "s_register_operand" "r,r")
8330			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8331			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8332			 (plus:SI
8333			  (match_operand:SI 2 "s_register_operand" "r,r")
8334			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8335   (clobber (reg:CC CC_REGNUM))]
8336  "TARGET_ARM"
8337  "#"
8338  [(set_attr "conds" "clob")
8339   (set_attr "length" "8,12")]
8340)
8341
8342(define_insn "*if_move_plus"
8343  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8344	(if_then_else:SI
8345	 (match_operator 4 "arm_comparison_operator"
8346	  [(match_operand 5 "cc_register" "") (const_int 0)])
8347	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8348	 (plus:SI
8349	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8350	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8351  "TARGET_ARM"
8352  "@
8353   add%D4\\t%0, %2, %3
8354   sub%D4\\t%0, %2, #%n3
8355   add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8356   sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8357  [(set_attr "conds" "use")
8358   (set_attr "length" "4,4,8,8")
8359   (set_attr "type" "*,*,*,*")]
8360)
8361
8362(define_insn "*ifcompare_arith_arith"
8363  [(set (match_operand:SI 0 "s_register_operand" "=r")
8364	(if_then_else:SI (match_operator 9 "arm_comparison_operator"
8365			  [(match_operand:SI 5 "s_register_operand" "r")
8366			   (match_operand:SI 6 "arm_add_operand" "rIL")])
8367			 (match_operator:SI 8 "shiftable_operator"
8368			  [(match_operand:SI 1 "s_register_operand" "r")
8369			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
8370			 (match_operator:SI 7 "shiftable_operator"
8371			  [(match_operand:SI 3 "s_register_operand" "r")
8372			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8373   (clobber (reg:CC CC_REGNUM))]
8374  "TARGET_ARM"
8375  "#"
8376  [(set_attr "conds" "clob")
8377   (set_attr "length" "12")]
8378)
8379
8380(define_insn "*if_arith_arith"
8381  [(set (match_operand:SI 0 "s_register_operand" "=r")
8382	(if_then_else:SI (match_operator 5 "arm_comparison_operator"
8383			  [(match_operand 8 "cc_register" "") (const_int 0)])
8384			 (match_operator:SI 6 "shiftable_operator"
8385			  [(match_operand:SI 1 "s_register_operand" "r")
8386			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
8387			 (match_operator:SI 7 "shiftable_operator"
8388			  [(match_operand:SI 3 "s_register_operand" "r")
8389			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8390  "TARGET_ARM"
8391  "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8392  [(set_attr "conds" "use")
8393   (set_attr "length" "8")]
8394)
8395
8396(define_insn "*ifcompare_arith_move"
8397  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8398	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8399			  [(match_operand:SI 2 "s_register_operand" "r,r")
8400			   (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8401			 (match_operator:SI 7 "shiftable_operator"
8402			  [(match_operand:SI 4 "s_register_operand" "r,r")
8403			   (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8404			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8405   (clobber (reg:CC CC_REGNUM))]
8406  "TARGET_ARM"
8407  "*
8408  /* If we have an operation where (op x 0) is the identity operation and
8409     the conditional operator is LT or GE and we are comparing against zero and
8410     everything is in registers then we can do this in two instructions.  */
8411  if (operands[3] == const0_rtx
8412      && GET_CODE (operands[7]) != AND
8413      && GET_CODE (operands[5]) == REG
8414      && GET_CODE (operands[1]) == REG 
8415      && REGNO (operands[1]) == REGNO (operands[4])
8416      && REGNO (operands[4]) != REGNO (operands[0]))
8417    {
8418      if (GET_CODE (operands[6]) == LT)
8419	return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8420      else if (GET_CODE (operands[6]) == GE)
8421	return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8422    }
8423  if (GET_CODE (operands[3]) == CONST_INT
8424      && !const_ok_for_arm (INTVAL (operands[3])))
8425    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8426  else
8427    output_asm_insn (\"cmp\\t%2, %3\", operands);
8428  output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8429  if (which_alternative != 0)
8430    return \"mov%D6\\t%0, %1\";
8431  return \"\";
8432  "
8433  [(set_attr "conds" "clob")
8434   (set_attr "length" "8,12")]
8435)
8436
8437(define_insn "*if_arith_move"
8438  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8439	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
8440			  [(match_operand 6 "cc_register" "") (const_int 0)])
8441			 (match_operator:SI 5 "shiftable_operator"
8442			  [(match_operand:SI 2 "s_register_operand" "r,r")
8443			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8444			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8445  "TARGET_ARM"
8446  "@
8447   %I5%d4\\t%0, %2, %3
8448   %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8449  [(set_attr "conds" "use")
8450   (set_attr "length" "4,8")
8451   (set_attr "type" "*,*")]
8452)
8453
8454(define_insn "*ifcompare_move_arith"
8455  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8456	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8457			  [(match_operand:SI 4 "s_register_operand" "r,r")
8458			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8459			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8460			 (match_operator:SI 7 "shiftable_operator"
8461			  [(match_operand:SI 2 "s_register_operand" "r,r")
8462			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8463   (clobber (reg:CC CC_REGNUM))]
8464  "TARGET_ARM"
8465  "*
8466  /* If we have an operation where (op x 0) is the identity operation and
8467     the conditional operator is LT or GE and we are comparing against zero and
8468     everything is in registers then we can do this in two instructions */
8469  if (operands[5] == const0_rtx
8470      && GET_CODE (operands[7]) != AND
8471      && GET_CODE (operands[3]) == REG
8472      && GET_CODE (operands[1]) == REG 
8473      && REGNO (operands[1]) == REGNO (operands[2])
8474      && REGNO (operands[2]) != REGNO (operands[0]))
8475    {
8476      if (GET_CODE (operands[6]) == GE)
8477	return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8478      else if (GET_CODE (operands[6]) == LT)
8479	return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8480    }
8481
8482  if (GET_CODE (operands[5]) == CONST_INT
8483      && !const_ok_for_arm (INTVAL (operands[5])))
8484    output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8485  else
8486    output_asm_insn (\"cmp\\t%4, %5\", operands);
8487
8488  if (which_alternative != 0)
8489    output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8490  return \"%I7%D6\\t%0, %2, %3\";
8491  "
8492  [(set_attr "conds" "clob")
8493   (set_attr "length" "8,12")]
8494)
8495
8496(define_insn "*if_move_arith"
8497  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8498	(if_then_else:SI
8499	 (match_operator 4 "arm_comparison_operator"
8500	  [(match_operand 6 "cc_register" "") (const_int 0)])
8501	 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8502	 (match_operator:SI 5 "shiftable_operator"
8503	  [(match_operand:SI 2 "s_register_operand" "r,r")
8504	   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8505  "TARGET_ARM"
8506  "@
8507   %I5%D4\\t%0, %2, %3
8508   %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8509  [(set_attr "conds" "use")
8510   (set_attr "length" "4,8")
8511   (set_attr "type" "*,*")]
8512)
8513
8514(define_insn "*ifcompare_move_not"
8515  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8516	(if_then_else:SI
8517	 (match_operator 5 "arm_comparison_operator"
8518	  [(match_operand:SI 3 "s_register_operand" "r,r")
8519	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8520	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8521	 (not:SI
8522	  (match_operand:SI 2 "s_register_operand" "r,r"))))
8523   (clobber (reg:CC CC_REGNUM))]
8524  "TARGET_ARM"
8525  "#"
8526  [(set_attr "conds" "clob")
8527   (set_attr "length" "8,12")]
8528)
8529
8530(define_insn "*if_move_not"
8531  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8532	(if_then_else:SI
8533	 (match_operator 4 "arm_comparison_operator"
8534	  [(match_operand 3 "cc_register" "") (const_int 0)])
8535	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8536	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8537  "TARGET_ARM"
8538  "@
8539   mvn%D4\\t%0, %2
8540   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8541   mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8542  [(set_attr "conds" "use")
8543   (set_attr "length" "4,8,8")]
8544)
8545
8546(define_insn "*ifcompare_not_move"
8547  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8548	(if_then_else:SI 
8549	 (match_operator 5 "arm_comparison_operator"
8550	  [(match_operand:SI 3 "s_register_operand" "r,r")
8551	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8552	 (not:SI
8553	  (match_operand:SI 2 "s_register_operand" "r,r"))
8554	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8555   (clobber (reg:CC CC_REGNUM))]
8556  "TARGET_ARM"
8557  "#"
8558  [(set_attr "conds" "clob")
8559   (set_attr "length" "8,12")]
8560)
8561
8562(define_insn "*if_not_move"
8563  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8564	(if_then_else:SI
8565	 (match_operator 4 "arm_comparison_operator"
8566	  [(match_operand 3 "cc_register" "") (const_int 0)])
8567	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8568	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8569  "TARGET_ARM"
8570  "@
8571   mvn%d4\\t%0, %2
8572   mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8573   mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8574  [(set_attr "conds" "use")
8575   (set_attr "length" "4,8,8")]
8576)
8577
8578(define_insn "*ifcompare_shift_move"
8579  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8580	(if_then_else:SI
8581	 (match_operator 6 "arm_comparison_operator"
8582	  [(match_operand:SI 4 "s_register_operand" "r,r")
8583	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8584	 (match_operator:SI 7 "shift_operator"
8585	  [(match_operand:SI 2 "s_register_operand" "r,r")
8586	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8587	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8588   (clobber (reg:CC CC_REGNUM))]
8589  "TARGET_ARM"
8590  "#"
8591  [(set_attr "conds" "clob")
8592   (set_attr "length" "8,12")]
8593)
8594
8595(define_insn "*if_shift_move"
8596  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8597	(if_then_else:SI
8598	 (match_operator 5 "arm_comparison_operator"
8599	  [(match_operand 6 "cc_register" "") (const_int 0)])
8600	 (match_operator:SI 4 "shift_operator"
8601	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
8602	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8603	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8604  "TARGET_ARM"
8605  "@
8606   mov%d5\\t%0, %2%S4
8607   mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8608   mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8609  [(set_attr "conds" "use")
8610   (set_attr "shift" "2")
8611   (set_attr "length" "4,8,8")]
8612)
8613
8614(define_insn "*ifcompare_move_shift"
8615  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8616	(if_then_else:SI
8617	 (match_operator 6 "arm_comparison_operator"
8618	  [(match_operand:SI 4 "s_register_operand" "r,r")
8619	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8620	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8621	 (match_operator:SI 7 "shift_operator"
8622	  [(match_operand:SI 2 "s_register_operand" "r,r")
8623	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8624   (clobber (reg:CC CC_REGNUM))]
8625  "TARGET_ARM"
8626  "#"
8627  [(set_attr "conds" "clob")
8628   (set_attr "length" "8,12")]
8629)
8630
8631(define_insn "*if_move_shift"
8632  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8633	(if_then_else:SI
8634	 (match_operator 5 "arm_comparison_operator"
8635	  [(match_operand 6 "cc_register" "") (const_int 0)])
8636	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8637	 (match_operator:SI 4 "shift_operator"
8638	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
8639	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8640  "TARGET_ARM"
8641  "@
8642   mov%D5\\t%0, %2%S4
8643   mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8644   mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8645  [(set_attr "conds" "use")
8646   (set_attr "shift" "2")
8647   (set_attr "length" "4,8,8")]
8648)
8649
8650(define_insn "*ifcompare_shift_shift"
8651  [(set (match_operand:SI 0 "s_register_operand" "=r")
8652	(if_then_else:SI
8653	 (match_operator 7 "arm_comparison_operator"
8654	  [(match_operand:SI 5 "s_register_operand" "r")
8655	   (match_operand:SI 6 "arm_add_operand" "rIL")])
8656	 (match_operator:SI 8 "shift_operator"
8657	  [(match_operand:SI 1 "s_register_operand" "r")
8658	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
8659	 (match_operator:SI 9 "shift_operator"
8660	  [(match_operand:SI 3 "s_register_operand" "r")
8661	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8662   (clobber (reg:CC CC_REGNUM))]
8663  "TARGET_ARM"
8664  "#"
8665  [(set_attr "conds" "clob")
8666   (set_attr "length" "12")]
8667)
8668
8669(define_insn "*if_shift_shift"
8670  [(set (match_operand:SI 0 "s_register_operand" "=r")
8671	(if_then_else:SI
8672	 (match_operator 5 "arm_comparison_operator"
8673	  [(match_operand 8 "cc_register" "") (const_int 0)])
8674	 (match_operator:SI 6 "shift_operator"
8675	  [(match_operand:SI 1 "s_register_operand" "r")
8676	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
8677	 (match_operator:SI 7 "shift_operator"
8678	  [(match_operand:SI 3 "s_register_operand" "r")
8679	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8680  "TARGET_ARM"
8681  "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8682  [(set_attr "conds" "use")
8683   (set_attr "shift" "1")
8684   (set_attr "length" "8")]
8685)
8686
8687(define_insn "*ifcompare_not_arith"
8688  [(set (match_operand:SI 0 "s_register_operand" "=r")
8689	(if_then_else:SI
8690	 (match_operator 6 "arm_comparison_operator"
8691	  [(match_operand:SI 4 "s_register_operand" "r")
8692	   (match_operand:SI 5 "arm_add_operand" "rIL")])
8693	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8694	 (match_operator:SI 7 "shiftable_operator"
8695	  [(match_operand:SI 2 "s_register_operand" "r")
8696	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8697   (clobber (reg:CC CC_REGNUM))]
8698  "TARGET_ARM"
8699  "#"
8700  [(set_attr "conds" "clob")
8701   (set_attr "length" "12")]
8702)
8703
8704(define_insn "*if_not_arith"
8705  [(set (match_operand:SI 0 "s_register_operand" "=r")
8706	(if_then_else:SI
8707	 (match_operator 5 "arm_comparison_operator"
8708	  [(match_operand 4 "cc_register" "") (const_int 0)])
8709	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8710	 (match_operator:SI 6 "shiftable_operator"
8711	  [(match_operand:SI 2 "s_register_operand" "r")
8712	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8713  "TARGET_ARM"
8714  "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8715  [(set_attr "conds" "use")
8716   (set_attr "length" "8")]
8717)
8718
8719(define_insn "*ifcompare_arith_not"
8720  [(set (match_operand:SI 0 "s_register_operand" "=r")
8721	(if_then_else:SI
8722	 (match_operator 6 "arm_comparison_operator"
8723	  [(match_operand:SI 4 "s_register_operand" "r")
8724	   (match_operand:SI 5 "arm_add_operand" "rIL")])
8725	 (match_operator:SI 7 "shiftable_operator"
8726	  [(match_operand:SI 2 "s_register_operand" "r")
8727	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
8728	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8729   (clobber (reg:CC CC_REGNUM))]
8730  "TARGET_ARM"
8731  "#"
8732  [(set_attr "conds" "clob")
8733   (set_attr "length" "12")]
8734)
8735
8736(define_insn "*if_arith_not"
8737  [(set (match_operand:SI 0 "s_register_operand" "=r")
8738	(if_then_else:SI
8739	 (match_operator 5 "arm_comparison_operator"
8740	  [(match_operand 4 "cc_register" "") (const_int 0)])
8741	 (match_operator:SI 6 "shiftable_operator"
8742	  [(match_operand:SI 2 "s_register_operand" "r")
8743	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
8744	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8745  "TARGET_ARM"
8746  "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8747  [(set_attr "conds" "use")
8748   (set_attr "length" "8")]
8749)
8750
8751(define_insn "*ifcompare_neg_move"
8752  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8753	(if_then_else:SI
8754	 (match_operator 5 "arm_comparison_operator"
8755	  [(match_operand:SI 3 "s_register_operand" "r,r")
8756	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8757	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8758	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8759   (clobber (reg:CC CC_REGNUM))]
8760  "TARGET_ARM"
8761  "#"
8762  [(set_attr "conds" "clob")
8763   (set_attr "length" "8,12")]
8764)
8765
8766(define_insn "*if_neg_move"
8767  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8768	(if_then_else:SI
8769	 (match_operator 4 "arm_comparison_operator"
8770	  [(match_operand 3 "cc_register" "") (const_int 0)])
8771	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8772	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8773  "TARGET_ARM"
8774  "@
8775   rsb%d4\\t%0, %2, #0
8776   mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8777   mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8778  [(set_attr "conds" "use")
8779   (set_attr "length" "4,8,8")]
8780)
8781
8782(define_insn "*ifcompare_move_neg"
8783  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8784	(if_then_else:SI
8785	 (match_operator 5 "arm_comparison_operator"
8786	  [(match_operand:SI 3 "s_register_operand" "r,r")
8787	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8788	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8789	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8790   (clobber (reg:CC CC_REGNUM))]
8791  "TARGET_ARM"
8792  "#"
8793  [(set_attr "conds" "clob")
8794   (set_attr "length" "8,12")]
8795)
8796
8797(define_insn "*if_move_neg"
8798  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8799	(if_then_else:SI
8800	 (match_operator 4 "arm_comparison_operator"
8801	  [(match_operand 3 "cc_register" "") (const_int 0)])
8802	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8803	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8804  "TARGET_ARM"
8805  "@
8806   rsb%D4\\t%0, %2, #0
8807   mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8808   mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8809  [(set_attr "conds" "use")
8810   (set_attr "length" "4,8,8")]
8811)
8812
8813(define_insn "*arith_adjacentmem"
8814  [(set (match_operand:SI 0 "s_register_operand" "=r")
8815	(match_operator:SI 1 "shiftable_operator"
8816	 [(match_operand:SI 2 "memory_operand" "m")
8817	  (match_operand:SI 3 "memory_operand" "m")]))
8818   (clobber (match_scratch:SI 4 "=r"))]
8819  "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8820  "*
8821  {
8822    rtx ldm[3];
8823    rtx arith[4];
8824    int val1 = 0, val2 = 0;
8825
8826    if (REGNO (operands[0]) > REGNO (operands[4]))
8827      {
8828	ldm[1] = operands[4];
8829	ldm[2] = operands[0];
8830      }
8831    else
8832      {
8833	ldm[1] = operands[0];
8834	ldm[2] = operands[4];
8835      }
8836    if (GET_CODE (XEXP (operands[2], 0)) != REG)
8837      val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8838    if (GET_CODE (XEXP (operands[3], 0)) != REG)
8839      val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8840    arith[0] = operands[0];
8841    arith[3] = operands[1];
8842    if (val1 < val2)
8843      {
8844	arith[1] = ldm[1];
8845	arith[2] = ldm[2];
8846      }
8847    else
8848      {
8849	arith[1] = ldm[2];
8850	arith[2] = ldm[1];
8851      }
8852   if (val1 && val2)
8853      {
8854	rtx ops[3];
8855	ldm[0] = ops[0] = operands[4];
8856	ops[1] = XEXP (XEXP (operands[2], 0), 0);
8857	ops[2] = XEXP (XEXP (operands[2], 0), 1);
8858	output_add_immediate (ops);
8859	if (val1 < val2)
8860	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8861	else
8862	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8863      }
8864    else if (val1)
8865      {
8866	ldm[0] = XEXP (operands[3], 0);
8867	if (val1 < val2)
8868	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8869	else
8870	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8871      }
8872    else
8873      {
8874	ldm[0] = XEXP (operands[2], 0);
8875	if (val1 < val2)
8876	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8877	else
8878	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8879      }
8880    output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8881    return \"\";
8882  }"
8883  [(set_attr "length" "12")
8884   (set_attr "predicable" "yes")
8885   (set_attr "type" "load")]
8886)
8887
8888;; the arm can support extended pre-inc instructions
8889
8890;; In all these cases, we use operands 0 and 1 for the register being
8891;; incremented because those are the operands that local-alloc will
8892;; tie and these are the pair most likely to be tieable (and the ones
8893;; that will benefit the most).
8894
8895;; We reject the frame pointer if it occurs anywhere in these patterns since
8896;; elimination will cause too many headaches.
8897
8898(define_insn "*strqi_preinc"
8899  [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8900			 (match_operand:SI 2 "index_operand" "rJ")))
8901	(match_operand:QI 3 "s_register_operand" "r"))
8902   (set (match_operand:SI 0 "s_register_operand" "=r")
8903	(plus:SI (match_dup 1) (match_dup 2)))]
8904  "TARGET_ARM
8905   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8906   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8907   && (GET_CODE (operands[2]) != REG
8908       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8909  "str%?b\\t%3, [%0, %2]!"
8910  [(set_attr "type" "store1")
8911   (set_attr "predicable" "yes")]
8912)
8913
8914(define_insn "*strqi_predec"
8915  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8916			  (match_operand:SI 2 "s_register_operand" "r")))
8917	(match_operand:QI 3 "s_register_operand" "r"))
8918   (set (match_operand:SI 0 "s_register_operand" "=r")
8919	(minus:SI (match_dup 1) (match_dup 2)))]
8920  "TARGET_ARM
8921   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8922   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8923   && (GET_CODE (operands[2]) != REG
8924       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8925  "str%?b\\t%3, [%0, -%2]!"
8926  [(set_attr "type" "store1")
8927   (set_attr "predicable" "yes")]
8928)
8929
8930(define_insn "*loadqi_preinc"
8931  [(set (match_operand:QI 3 "s_register_operand" "=r")
8932	(mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8933			 (match_operand:SI 2 "index_operand" "rJ"))))
8934   (set (match_operand:SI 0 "s_register_operand" "=r")
8935	(plus:SI (match_dup 1) (match_dup 2)))]
8936  "TARGET_ARM
8937   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8938   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8939   && (GET_CODE (operands[2]) != REG
8940       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8941  "ldr%?b\\t%3, [%0, %2]!"
8942  [(set_attr "type" "load")
8943   (set_attr "predicable" "yes")]
8944)
8945
8946(define_insn "*loadqi_predec"
8947  [(set (match_operand:QI 3 "s_register_operand" "=r")
8948	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8949			  (match_operand:SI 2 "s_register_operand" "r"))))
8950   (set (match_operand:SI 0 "s_register_operand" "=r")
8951	(minus:SI (match_dup 1) (match_dup 2)))]
8952  "TARGET_ARM
8953   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8954   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8955   && (GET_CODE (operands[2]) != REG
8956       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8957  "ldr%?b\\t%3, [%0, -%2]!"
8958  [(set_attr "type" "load")
8959   (set_attr "predicable" "yes")]
8960)
8961
8962(define_insn "*loadqisi_preinc"
8963  [(set (match_operand:SI 3 "s_register_operand" "=r")
8964	(zero_extend:SI
8965	 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8966			  (match_operand:SI 2 "index_operand" "rJ")))))
8967   (set (match_operand:SI 0 "s_register_operand" "=r")
8968	(plus:SI (match_dup 1) (match_dup 2)))]
8969  "TARGET_ARM
8970   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8971   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8972   && (GET_CODE (operands[2]) != REG
8973       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8974  "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8975  [(set_attr "type" "load")
8976   (set_attr "predicable" "yes")]
8977)
8978
8979(define_insn "*loadqisi_predec"
8980  [(set (match_operand:SI 3 "s_register_operand" "=r")
8981	(zero_extend:SI
8982	 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8983			   (match_operand:SI 2 "s_register_operand" "r")))))
8984   (set (match_operand:SI 0 "s_register_operand" "=r")
8985	(minus:SI (match_dup 1) (match_dup 2)))]
8986  "TARGET_ARM
8987   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8988   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8989   && (GET_CODE (operands[2]) != REG
8990       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8991  "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8992  [(set_attr "type" "load")
8993   (set_attr "predicable" "yes")]
8994)
8995
8996(define_insn "*strsi_preinc"
8997  [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8998			 (match_operand:SI 2 "index_operand" "rJ")))
8999	(match_operand:SI 3 "s_register_operand" "r"))
9000   (set (match_operand:SI 0 "s_register_operand" "=r")
9001	(plus:SI (match_dup 1) (match_dup 2)))]
9002  "TARGET_ARM
9003   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9004   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9005   && (GET_CODE (operands[2]) != REG
9006       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9007  "str%?\\t%3, [%0, %2]!"
9008  [(set_attr "type" "store1")
9009   (set_attr "predicable" "yes")]
9010)
9011
9012(define_insn "*strsi_predec"
9013  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9014			  (match_operand:SI 2 "s_register_operand" "r")))
9015	(match_operand:SI 3 "s_register_operand" "r"))
9016   (set (match_operand:SI 0 "s_register_operand" "=r")
9017	(minus:SI (match_dup 1) (match_dup 2)))]
9018  "TARGET_ARM
9019   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9020   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9021   && (GET_CODE (operands[2]) != REG
9022       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9023  "str%?\\t%3, [%0, -%2]!"
9024  [(set_attr "type" "store1")
9025   (set_attr "predicable" "yes")]
9026)
9027
9028(define_insn "*loadsi_preinc"
9029  [(set (match_operand:SI 3 "s_register_operand" "=r")
9030	(mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9031			 (match_operand:SI 2 "index_operand" "rJ"))))
9032   (set (match_operand:SI 0 "s_register_operand" "=r")
9033	(plus:SI (match_dup 1) (match_dup 2)))]
9034  "TARGET_ARM
9035   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9036   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9037   && (GET_CODE (operands[2]) != REG
9038       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9039  "ldr%?\\t%3, [%0, %2]!"
9040  [(set_attr "type" "load")
9041   (set_attr "predicable" "yes")]
9042)
9043
9044(define_insn "*loadsi_predec"
9045  [(set (match_operand:SI 3 "s_register_operand" "=r")
9046	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9047			  (match_operand:SI 2 "s_register_operand" "r"))))
9048   (set (match_operand:SI 0 "s_register_operand" "=r")
9049	(minus:SI (match_dup 1) (match_dup 2)))]
9050  "TARGET_ARM
9051   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9052   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9053   && (GET_CODE (operands[2]) != REG
9054       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9055  "ldr%?\\t%3, [%0, -%2]!"
9056  [(set_attr "type" "load")
9057   (set_attr "predicable" "yes")]
9058)
9059
9060(define_insn "*loadhi_preinc"
9061  [(set (match_operand:HI 3 "s_register_operand" "=r")
9062	(mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9063			 (match_operand:SI 2 "index_operand" "rJ"))))
9064   (set (match_operand:SI 0 "s_register_operand" "=r")
9065	(plus:SI (match_dup 1) (match_dup 2)))]
9066  "TARGET_ARM
9067   && !BYTES_BIG_ENDIAN
9068   && !TARGET_MMU_TRAPS
9069   && !arm_arch4
9070   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9071   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9072   && (GET_CODE (operands[2]) != REG
9073       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9074  "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
9075  [(set_attr "type" "load")
9076   (set_attr "predicable" "yes")]
9077)
9078
9079(define_insn "*loadhi_predec"
9080  [(set (match_operand:HI 3 "s_register_operand" "=r")
9081	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9082			  (match_operand:SI 2 "s_register_operand" "r"))))
9083   (set (match_operand:SI 0 "s_register_operand" "=r")
9084	(minus:SI (match_dup 1) (match_dup 2)))]
9085  "TARGET_ARM
9086   && !BYTES_BIG_ENDIAN
9087   && !TARGET_MMU_TRAPS
9088   && !arm_arch4
9089   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9090   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9091   && (GET_CODE (operands[2]) != REG
9092       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9093  "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
9094  [(set_attr "type" "load")
9095   (set_attr "predicable" "yes")]
9096)
9097
9098(define_insn "*strqi_shiftpreinc"
9099  [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9100			  [(match_operand:SI 3 "s_register_operand" "r")
9101			   (match_operand:SI 4 "const_shift_operand" "n")])
9102			 (match_operand:SI 1 "s_register_operand" "0")))
9103	(match_operand:QI 5 "s_register_operand" "r"))
9104   (set (match_operand:SI 0 "s_register_operand" "=r")
9105	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9106		 (match_dup 1)))]
9107  "TARGET_ARM
9108   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9109   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9110   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9111  "str%?b\\t%5, [%0, %3%S2]!"
9112  [(set_attr "type" "store1")
9113   (set_attr "predicable" "yes")]
9114)
9115
9116(define_insn "*strqi_shiftpredec"
9117  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9118			  (match_operator:SI 2 "shift_operator"
9119			   [(match_operand:SI 3 "s_register_operand" "r")
9120			    (match_operand:SI 4 "const_shift_operand" "n")])))
9121	(match_operand:QI 5 "s_register_operand" "r"))
9122   (set (match_operand:SI 0 "s_register_operand" "=r")
9123	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9124						 (match_dup 4)])))]
9125  "TARGET_ARM
9126   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9127   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9128   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9129  "str%?b\\t%5, [%0, -%3%S2]!"
9130  [(set_attr "type" "store1")
9131   (set_attr "predicable" "yes")]
9132)
9133
9134(define_insn "*loadqi_shiftpreinc"
9135  [(set (match_operand:QI 5 "s_register_operand" "=r")
9136	(mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9137			  [(match_operand:SI 3 "s_register_operand" "r")
9138			   (match_operand:SI 4 "const_shift_operand" "n")])
9139			 (match_operand:SI 1 "s_register_operand" "0"))))
9140   (set (match_operand:SI 0 "s_register_operand" "=r")
9141	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9142		 (match_dup 1)))]
9143  "TARGET_ARM
9144   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9145   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9146   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9147  "ldr%?b\\t%5, [%0, %3%S2]!"
9148  [(set_attr "type" "load")
9149   (set_attr "predicable" "yes")]
9150)
9151
9152(define_insn "*loadqi_shiftpredec"
9153  [(set (match_operand:QI 5 "s_register_operand" "=r")
9154	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9155			  (match_operator:SI 2 "shift_operator"
9156			   [(match_operand:SI 3 "s_register_operand" "r")
9157			    (match_operand:SI 4 "const_shift_operand" "n")]))))
9158   (set (match_operand:SI 0 "s_register_operand" "=r")
9159	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9160						 (match_dup 4)])))]
9161  "TARGET_ARM
9162   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9163   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9164   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9165  "ldr%?b\\t%5, [%0, -%3%S2]!"
9166  [(set_attr "type" "load")
9167   (set_attr "predicable" "yes")]
9168)
9169
9170(define_insn "*strsi_shiftpreinc"
9171  [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9172			  [(match_operand:SI 3 "s_register_operand" "r")
9173			   (match_operand:SI 4 "const_shift_operand" "n")])
9174			 (match_operand:SI 1 "s_register_operand" "0")))
9175	(match_operand:SI 5 "s_register_operand" "r"))
9176   (set (match_operand:SI 0 "s_register_operand" "=r")
9177	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9178		 (match_dup 1)))]
9179  "TARGET_ARM
9180   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9181   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9182   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9183  "str%?\\t%5, [%0, %3%S2]!"
9184  [(set_attr "type" "store1")
9185   (set_attr "predicable" "yes")]
9186)
9187
9188(define_insn "*strsi_shiftpredec"
9189  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9190			  (match_operator:SI 2 "shift_operator"
9191			   [(match_operand:SI 3 "s_register_operand" "r")
9192			    (match_operand:SI 4 "const_shift_operand" "n")])))
9193	(match_operand:SI 5 "s_register_operand" "r"))
9194   (set (match_operand:SI 0 "s_register_operand" "=r")
9195	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9196						 (match_dup 4)])))]
9197  "TARGET_ARM
9198   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9199   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9200   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9201  "str%?\\t%5, [%0, -%3%S2]!"
9202  [(set_attr "type" "store1")
9203   (set_attr "predicable" "yes")]
9204)
9205
9206(define_insn "*loadsi_shiftpreinc"
9207  [(set (match_operand:SI 5 "s_register_operand" "=r")
9208	(mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9209			  [(match_operand:SI 3 "s_register_operand" "r")
9210			   (match_operand:SI 4 "const_shift_operand" "n")])
9211			 (match_operand:SI 1 "s_register_operand" "0"))))
9212   (set (match_operand:SI 0 "s_register_operand" "=r")
9213	(plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9214		 (match_dup 1)))]
9215  "TARGET_ARM
9216   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9217   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9218   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9219  "ldr%?\\t%5, [%0, %3%S2]!"
9220  [(set_attr "type" "load")
9221   (set_attr "predicable" "yes")]
9222)
9223
9224(define_insn "*loadsi_shiftpredec"
9225  [(set (match_operand:SI 5 "s_register_operand" "=r")
9226	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9227			  (match_operator:SI 2 "shift_operator"
9228			   [(match_operand:SI 3 "s_register_operand" "r")
9229			    (match_operand:SI 4 "const_shift_operand" "n")]))))
9230   (set (match_operand:SI 0 "s_register_operand" "=r")
9231	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9232						 (match_dup 4)])))]
9233  "TARGET_ARM
9234   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9235   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9236   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9237  "ldr%?\\t%5, [%0, -%3%S2]!"
9238  [(set_attr "type" "load")
9239   (set_attr "predicable" "yes")])
9240
9241(define_insn "*loadhi_shiftpreinc"
9242  [(set (match_operand:HI 5 "s_register_operand" "=r")
9243	(mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9244			  [(match_operand:SI 3 "s_register_operand" "r")
9245			   (match_operand:SI 4 "const_shift_operand" "n")])
9246			 (match_operand:SI 1 "s_register_operand" "0"))))
9247   (set (match_operand:SI 0 "s_register_operand" "=r")
9248	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9249		 (match_dup 1)))]
9250  "TARGET_ARM
9251   && !BYTES_BIG_ENDIAN
9252   && !TARGET_MMU_TRAPS
9253   && !arm_arch4
9254   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9255   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9256   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9257  "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9258  [(set_attr "type" "load")
9259   (set_attr "predicable" "yes")]
9260)
9261
9262(define_insn "*loadhi_shiftpredec"
9263  [(set (match_operand:HI 5 "s_register_operand" "=r")
9264	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9265			  (match_operator:SI 2 "shift_operator"
9266			   [(match_operand:SI 3 "s_register_operand" "r")
9267			    (match_operand:SI 4 "const_shift_operand" "n")]))))
9268   (set (match_operand:SI 0 "s_register_operand" "=r")
9269	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9270						 (match_dup 4)])))]
9271  "TARGET_ARM
9272   && !BYTES_BIG_ENDIAN
9273   && !TARGET_MMU_TRAPS
9274   && !arm_arch4
9275   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9276   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9277   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9278  "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9279  [(set_attr "type" "load")
9280   (set_attr "predicable" "yes")]
9281)
9282
9283; It can also support extended post-inc expressions, but combine doesn't
9284; try these....
9285; It doesn't seem worth adding peepholes for anything but the most common
9286; cases since, unlike combine, the increment must immediately follow the load
9287; for this pattern to match.
9288; We must watch to see that the source/destination register isn't also the
9289; same as the base address register, and that if the index is a register,
9290; that it is not the same as the base address register.  In such cases the
9291; instruction that we would generate would have UNPREDICTABLE behavior so 
9292; we cannot use it.
9293
9294(define_peephole
9295  [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9296	(match_operand:QI 2 "s_register_operand" "r"))
9297   (set (match_dup 0)
9298	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9299  "TARGET_ARM
9300   && (REGNO (operands[2]) != REGNO (operands[0]))
9301   && (GET_CODE (operands[1]) != REG
9302       || (REGNO (operands[1]) != REGNO (operands[0])))"
9303  "str%?b\\t%2, [%0], %1"
9304)
9305
9306(define_peephole
9307  [(set (match_operand:QI 0 "s_register_operand" "=r")
9308	(mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9309   (set (match_dup 1)
9310	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9311  "TARGET_ARM
9312   && REGNO (operands[0]) != REGNO(operands[1])
9313   && (GET_CODE (operands[2]) != REG
9314       || REGNO(operands[0]) != REGNO (operands[2]))"
9315  "ldr%?b\\t%0, [%1], %2"
9316)
9317
9318(define_peephole
9319  [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9320	(match_operand:SI 2 "s_register_operand" "r"))
9321   (set (match_dup 0)
9322	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9323  "TARGET_ARM
9324   && (REGNO (operands[2]) != REGNO (operands[0]))
9325   && (GET_CODE (operands[1]) != REG
9326       || (REGNO (operands[1]) != REGNO (operands[0])))"
9327  "str%?\\t%2, [%0], %1"
9328)
9329
9330(define_peephole
9331  [(set (match_operand:HI 0 "s_register_operand" "=r")
9332	(mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9333   (set (match_dup 1)
9334	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9335  "TARGET_ARM
9336   && !BYTES_BIG_ENDIAN
9337   && !TARGET_MMU_TRAPS
9338   && !arm_arch4
9339   && REGNO (operands[0]) != REGNO(operands[1])
9340   && (GET_CODE (operands[2]) != REG
9341       || REGNO(operands[0]) != REGNO (operands[2]))"
9342  "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9343)
9344
9345(define_peephole
9346  [(set (match_operand:SI 0 "s_register_operand" "=r")
9347	(mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9348   (set (match_dup 1)
9349	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9350  "TARGET_ARM
9351   && REGNO (operands[0]) != REGNO(operands[1])
9352   && (GET_CODE (operands[2]) != REG
9353       || REGNO(operands[0]) != REGNO (operands[2]))"
9354  "ldr%?\\t%0, [%1], %2"
9355)
9356
9357(define_peephole
9358  [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9359			 (match_operand:SI 1 "index_operand" "rJ")))
9360	(match_operand:QI 2 "s_register_operand" "r"))
9361   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9362  "TARGET_ARM
9363   && (REGNO (operands[2]) != REGNO (operands[0]))
9364   && (GET_CODE (operands[1]) != REG
9365       || (REGNO (operands[1]) != REGNO (operands[0])))"
9366  "str%?b\\t%2, [%0, %1]!"
9367)
9368
9369(define_peephole
9370  [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9371			  [(match_operand:SI 0 "s_register_operand" "r")
9372			   (match_operand:SI 1 "const_int_operand" "n")])
9373			 (match_operand:SI 2 "s_register_operand" "+r")))
9374	(match_operand:QI 3 "s_register_operand" "r"))
9375   (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9376			       (match_dup 2)))]
9377  "TARGET_ARM
9378   && (REGNO (operands[3]) != REGNO (operands[2]))
9379   && (REGNO (operands[0]) != REGNO (operands[2]))"
9380  "str%?b\\t%3, [%2, %0%S4]!"
9381)
9382
9383; This pattern is never tried by combine, so do it as a peephole
9384
9385(define_peephole2
9386  [(set (match_operand:SI 0 "s_register_operand" "")
9387	(match_operand:SI 1 "s_register_operand" ""))
9388   (set (reg:CC CC_REGNUM)
9389	(compare:CC (match_dup 1) (const_int 0)))]
9390  "TARGET_ARM
9391   && (!TARGET_CIRRUS
9392       || (!cirrus_fp_register (operands[0], SImode)
9393           && !cirrus_fp_register (operands[1], SImode)))
9394  "
9395  [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9396	      (set (match_dup 0) (match_dup 1))])]
9397  ""
9398)
9399
9400; Peepholes to spot possible load- and store-multiples, if the ordering is
9401; reversed, check that the memory references aren't volatile.
9402
9403(define_peephole
9404  [(set (match_operand:SI 0 "s_register_operand" "=r")
9405        (match_operand:SI 4 "memory_operand" "m"))
9406   (set (match_operand:SI 1 "s_register_operand" "=r")
9407        (match_operand:SI 5 "memory_operand" "m"))
9408   (set (match_operand:SI 2 "s_register_operand" "=r")
9409        (match_operand:SI 6 "memory_operand" "m"))
9410   (set (match_operand:SI 3 "s_register_operand" "=r")
9411        (match_operand:SI 7 "memory_operand" "m"))]
9412  "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9413  "*
9414  return emit_ldm_seq (operands, 4);
9415  "
9416)
9417
9418(define_peephole
9419  [(set (match_operand:SI 0 "s_register_operand" "=r")
9420        (match_operand:SI 3 "memory_operand" "m"))
9421   (set (match_operand:SI 1 "s_register_operand" "=r")
9422        (match_operand:SI 4 "memory_operand" "m"))
9423   (set (match_operand:SI 2 "s_register_operand" "=r")
9424        (match_operand:SI 5 "memory_operand" "m"))]
9425  "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9426  "*
9427  return emit_ldm_seq (operands, 3);
9428  "
9429)
9430
9431(define_peephole
9432  [(set (match_operand:SI 0 "s_register_operand" "=r")
9433        (match_operand:SI 2 "memory_operand" "m"))
9434   (set (match_operand:SI 1 "s_register_operand" "=r")
9435        (match_operand:SI 3 "memory_operand" "m"))]
9436  "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9437  "*
9438  return emit_ldm_seq (operands, 2);
9439  "
9440)
9441
9442(define_peephole
9443  [(set (match_operand:SI 4 "memory_operand" "=m")
9444        (match_operand:SI 0 "s_register_operand" "r"))
9445   (set (match_operand:SI 5 "memory_operand" "=m")
9446        (match_operand:SI 1 "s_register_operand" "r"))
9447   (set (match_operand:SI 6 "memory_operand" "=m")
9448        (match_operand:SI 2 "s_register_operand" "r"))
9449   (set (match_operand:SI 7 "memory_operand" "=m")
9450        (match_operand:SI 3 "s_register_operand" "r"))]
9451  "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9452  "*
9453  return emit_stm_seq (operands, 4);
9454  "
9455)
9456
9457(define_peephole
9458  [(set (match_operand:SI 3 "memory_operand" "=m")
9459        (match_operand:SI 0 "s_register_operand" "r"))
9460   (set (match_operand:SI 4 "memory_operand" "=m")
9461        (match_operand:SI 1 "s_register_operand" "r"))
9462   (set (match_operand:SI 5 "memory_operand" "=m")
9463        (match_operand:SI 2 "s_register_operand" "r"))]
9464  "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9465  "*
9466  return emit_stm_seq (operands, 3);
9467  "
9468)
9469
9470(define_peephole
9471  [(set (match_operand:SI 2 "memory_operand" "=m")
9472        (match_operand:SI 0 "s_register_operand" "r"))
9473   (set (match_operand:SI 3 "memory_operand" "=m")
9474        (match_operand:SI 1 "s_register_operand" "r"))]
9475  "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9476  "*
9477  return emit_stm_seq (operands, 2);
9478  "
9479)
9480
9481(define_split
9482  [(set (match_operand:SI 0 "s_register_operand" "")
9483	(and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9484		       (const_int 0))
9485		(neg:SI (match_operator:SI 2 "arm_comparison_operator"
9486			 [(match_operand:SI 3 "s_register_operand" "")
9487			  (match_operand:SI 4 "arm_rhs_operand" "")]))))
9488   (clobber (match_operand:SI 5 "s_register_operand" ""))]
9489  "TARGET_ARM"
9490  [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9491   (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9492			      (match_dup 5)))]
9493  ""
9494)
9495
9496;; This split can be used because CC_Z mode implies that the following
9497;; branch will be an equality, or an unsigned inequality, so the sign
9498;; extension is not needed.
9499
9500(define_split
9501  [(set (reg:CC_Z CC_REGNUM)
9502	(compare:CC_Z
9503	 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9504		    (const_int 24))
9505	 (match_operand 1 "const_int_operand" "")))
9506   (clobber (match_scratch:SI 2 ""))]
9507  "TARGET_ARM
9508   && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9509       == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9510  [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9511   (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9512  "
9513  operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9514  "
9515)
9516
9517(define_expand "prologue"
9518  [(clobber (const_int 0))]
9519  "TARGET_EITHER"
9520  "if (TARGET_ARM)
9521     arm_expand_prologue ();
9522   else
9523     thumb_expand_prologue ();
9524  DONE;
9525  "
9526)
9527
9528(define_expand "epilogue"
9529  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9530  "TARGET_EITHER"
9531  "
9532  if (TARGET_THUMB)
9533    thumb_expand_epilogue ();
9534  else if (USE_RETURN_INSN (FALSE))
9535    {
9536      emit_jump_insn (gen_return ());
9537      DONE;
9538    }
9539  emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9540	gen_rtvec (1,
9541		gen_rtx_RETURN (VOIDmode)),
9542	VUNSPEC_EPILOGUE));
9543  DONE;
9544  "
9545)
9546
9547;; Note - although unspec_volatile's USE all hard registers,
9548;; USEs are ignored after relaod has completed.  Thus we need
9549;; to add an unspec of the link register to ensure that flow
9550;; does not think that it is unused by the sibcall branch that
9551;; will replace the standard function epilogue.
9552(define_insn "sibcall_epilogue"
9553  [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9554              (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9555  "TARGET_ARM"
9556  "*
9557  if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9558    return output_return_instruction (const_true_rtx, FALSE, FALSE);
9559  return arm_output_epilogue (next_nonnote_insn (insn));
9560  "
9561;; Length is absolute worst case
9562  [(set_attr "length" "44")
9563   (set_attr "type" "block")
9564   ;; We don't clobber the conditions, but the potential length of this
9565   ;; operation is sufficient to make conditionalizing the sequence 
9566   ;; unlikely to be profitable.
9567   (set_attr "conds" "clob")]
9568)
9569
9570(define_insn "*epilogue_insns"
9571  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9572  "TARGET_EITHER"
9573  "*
9574  if (TARGET_ARM)
9575    return arm_output_epilogue (NULL);
9576  else /* TARGET_THUMB */
9577    return thumb_unexpanded_epilogue ();
9578  "
9579  ; Length is absolute worst case
9580  [(set_attr "length" "44")
9581   (set_attr "type" "block")
9582   ;; We don't clobber the conditions, but the potential length of this
9583   ;; operation is sufficient to make conditionalizing the sequence 
9584   ;; unlikely to be profitable.
9585   (set_attr "conds" "clob")]
9586)
9587
9588(define_expand "eh_epilogue"
9589  [(use (match_operand:SI 0 "register_operand" ""))
9590   (use (match_operand:SI 1 "register_operand" ""))
9591   (use (match_operand:SI 2 "register_operand" ""))]
9592  "TARGET_EITHER"
9593  "
9594  {
9595    cfun->machine->eh_epilogue_sp_ofs = operands[1];
9596    if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9597      {
9598	rtx ra = gen_rtx_REG (Pmode, 2);
9599
9600	emit_move_insn (ra, operands[2]);
9601	operands[2] = ra;
9602      }
9603    /* This is a hack -- we may have crystalized the function type too
9604       early.  */
9605    cfun->machine->func_type = 0;
9606  }"
9607)
9608
9609;; This split is only used during output to reduce the number of patterns
9610;; that need assembler instructions adding to them.  We allowed the setting
9611;; of the conditions to be implicit during rtl generation so that
9612;; the conditional compare patterns would work.  However this conflicts to
9613;; some extent with the conditional data operations, so we have to split them
9614;; up again here.
9615
9616(define_split
9617  [(set (match_operand:SI 0 "s_register_operand" "")
9618	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9619			  [(match_operand 2 "" "") (match_operand 3 "" "")])
9620			 (match_dup 0)
9621			 (match_operand 4 "" "")))
9622   (clobber (reg:CC CC_REGNUM))]
9623  "TARGET_ARM && reload_completed"
9624  [(set (match_dup 5) (match_dup 6))
9625   (cond_exec (match_dup 7)
9626	      (set (match_dup 0) (match_dup 4)))]
9627  "
9628  {
9629    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9630					     operands[2], operands[3]);
9631    enum rtx_code rc = GET_CODE (operands[1]);
9632
9633    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9634    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9635    if (mode == CCFPmode || mode == CCFPEmode)
9636      rc = reverse_condition_maybe_unordered (rc);
9637    else
9638      rc = reverse_condition (rc);
9639
9640    operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9641  }"
9642)
9643
9644(define_split
9645  [(set (match_operand:SI 0 "s_register_operand" "")
9646	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9647			  [(match_operand 2 "" "") (match_operand 3 "" "")])
9648			 (match_operand 4 "" "")
9649			 (match_dup 0)))
9650   (clobber (reg:CC CC_REGNUM))]
9651  "TARGET_ARM && reload_completed"
9652  [(set (match_dup 5) (match_dup 6))
9653   (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9654	      (set (match_dup 0) (match_dup 4)))]
9655  "
9656  {
9657    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9658					     operands[2], operands[3]);
9659
9660    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9661    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9662  }"
9663)
9664
9665(define_split
9666  [(set (match_operand:SI 0 "s_register_operand" "")
9667	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9668			  [(match_operand 2 "" "") (match_operand 3 "" "")])
9669			 (match_operand 4 "" "")
9670			 (match_operand 5 "" "")))
9671   (clobber (reg:CC CC_REGNUM))]
9672  "TARGET_ARM && reload_completed"
9673  [(set (match_dup 6) (match_dup 7))
9674   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9675	      (set (match_dup 0) (match_dup 4)))
9676   (cond_exec (match_dup 8)
9677	      (set (match_dup 0) (match_dup 5)))]
9678  "
9679  {
9680    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9681					     operands[2], operands[3]);
9682    enum rtx_code rc = GET_CODE (operands[1]);
9683
9684    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9685    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9686    if (mode == CCFPmode || mode == CCFPEmode)
9687      rc = reverse_condition_maybe_unordered (rc);
9688    else
9689      rc = reverse_condition (rc);
9690
9691    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9692  }"
9693)
9694
9695(define_split
9696  [(set (match_operand:SI 0 "s_register_operand" "")
9697	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9698			  [(match_operand:SI 2 "s_register_operand" "")
9699			   (match_operand:SI 3 "arm_add_operand" "")])
9700			 (match_operand:SI 4 "arm_rhs_operand" "")
9701			 (not:SI
9702			  (match_operand:SI 5 "s_register_operand" ""))))
9703   (clobber (reg:CC CC_REGNUM))]
9704  "TARGET_ARM && reload_completed"
9705  [(set (match_dup 6) (match_dup 7))
9706   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9707	      (set (match_dup 0) (match_dup 4)))
9708   (cond_exec (match_dup 8)
9709	      (set (match_dup 0) (not:SI (match_dup 5))))]
9710  "
9711  {
9712    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9713					     operands[2], operands[3]);
9714    enum rtx_code rc = GET_CODE (operands[1]);
9715
9716    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9717    operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
9718    if (mode == CCFPmode || mode == CCFPEmode)
9719      rc = reverse_condition_maybe_unordered (rc);
9720    else
9721      rc = reverse_condition (rc);
9722
9723    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9724  }"
9725)
9726
9727(define_insn "*cond_move_not"
9728  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9729	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
9730			  [(match_operand 3 "cc_register" "") (const_int 0)])
9731			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9732			 (not:SI
9733			  (match_operand:SI 2 "s_register_operand" "r,r"))))]
9734  "TARGET_ARM"
9735  "@
9736   mvn%D4\\t%0, %2
9737   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9738  [(set_attr "conds" "use")
9739   (set_attr "length" "4,8")]
9740)
9741
9742;; The next two patterns occur when an AND operation is followed by a
9743;; scc insn sequence 
9744
9745(define_insn "*sign_extract_onebit"
9746  [(set (match_operand:SI 0 "s_register_operand" "=r")
9747	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9748			 (const_int 1)
9749			 (match_operand:SI 2 "const_int_operand" "n")))
9750    (clobber (reg:CC CC_REGNUM))]
9751  "TARGET_ARM"
9752  "*
9753    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9754    output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9755    return \"mvnne\\t%0, #0\";
9756  "
9757  [(set_attr "conds" "clob")
9758   (set_attr "length" "8")]
9759)
9760
9761(define_insn "*not_signextract_onebit"
9762  [(set (match_operand:SI 0 "s_register_operand" "=r")
9763	(not:SI
9764	 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9765			  (const_int 1)
9766			  (match_operand:SI 2 "const_int_operand" "n"))))
9767   (clobber (reg:CC CC_REGNUM))]
9768  "TARGET_ARM"
9769  "*
9770    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9771    output_asm_insn (\"tst\\t%1, %2\", operands);
9772    output_asm_insn (\"mvneq\\t%0, #0\", operands);
9773    return \"movne\\t%0, #0\";
9774  "
9775  [(set_attr "conds" "clob")
9776   (set_attr "length" "12")]
9777)
9778
9779;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9780;; expressions.  For simplicity, the first register is also in the unspec
9781;; part.
9782(define_insn "*push_multi"
9783  [(match_parallel 2 "multi_register_push"
9784    [(set (match_operand:BLK 0 "memory_operand" "=m")
9785	  (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9786		      UNSPEC_PUSH_MULT))])]
9787  "TARGET_ARM"
9788  "*
9789  {
9790    int num_saves = XVECLEN (operands[2], 0);
9791     
9792    /* For the StrongARM at least it is faster to
9793       use STR to store only a single register.  */
9794    if (num_saves == 1)
9795      output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9796    else
9797      {
9798	int i;
9799	char pattern[100];
9800
9801	strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9802
9803	for (i = 1; i < num_saves; i++)
9804	  {
9805	    strcat (pattern, \", %|\");
9806	    strcat (pattern,
9807		    reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9808	  }
9809
9810	strcat (pattern, \"}\");
9811	output_asm_insn (pattern, operands);
9812      }
9813
9814    return \"\";
9815  }"
9816  [(set_attr "type" "store4")]
9817)
9818
9819(define_insn "stack_tie"
9820  [(set (mem:BLK (scratch))
9821	(unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9822		     (match_operand:SI 1 "s_register_operand" "r")]
9823		    UNSPEC_PRLG_STK))]
9824  ""
9825  ""
9826  [(set_attr "length" "0")]
9827)
9828
9829;; Similarly for the floating point registers
9830(define_insn "*push_fp_multi"
9831  [(match_parallel 2 "multi_register_push"
9832    [(set (match_operand:BLK 0 "memory_operand" "=m")
9833	  (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9834		      UNSPEC_PUSH_MULT))])]
9835  "TARGET_ARM"
9836  "*
9837  {
9838    char pattern[100];
9839
9840    sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9841    output_asm_insn (pattern, operands);
9842    return \"\";
9843  }"
9844  [(set_attr "type" "f_store")]
9845)
9846
9847;; Special patterns for dealing with the constant pool
9848
9849(define_insn "align_4"
9850  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9851  "TARGET_EITHER"
9852  "*
9853  assemble_align (32);
9854  return \"\";
9855  "
9856)
9857
9858(define_insn "align_8"
9859  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9860  "TARGET_REALLY_IWMMXT"
9861  "*
9862  assemble_align (64);
9863  return \"\";
9864  "
9865)
9866
9867(define_insn "consttable_end"
9868  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9869  "TARGET_EITHER"
9870  "*
9871  making_const_table = FALSE;
9872  return \"\";
9873  "
9874)
9875
9876(define_insn "consttable_1"
9877  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9878  "TARGET_THUMB"
9879  "*
9880  making_const_table = TRUE;
9881  assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9882  assemble_zeros (3);
9883  return \"\";
9884  "
9885  [(set_attr "length" "4")]
9886)
9887
9888(define_insn "consttable_2"
9889  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9890  "TARGET_THUMB"
9891  "*
9892  making_const_table = TRUE;
9893  assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9894  assemble_zeros (2);
9895  return \"\";
9896  "
9897  [(set_attr "length" "4")]
9898)
9899
9900(define_insn "consttable_4"
9901  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9902  "TARGET_EITHER"
9903  "*
9904  {
9905    making_const_table = TRUE;
9906    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9907      {
9908      case MODE_FLOAT:
9909      {
9910        REAL_VALUE_TYPE r;
9911        REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9912        assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9913        break;
9914      }
9915      default:
9916        assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9917        break;
9918      }
9919    return \"\";
9920  }"
9921  [(set_attr "length" "4")]
9922)
9923
9924(define_insn "consttable_8"
9925  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9926  "TARGET_EITHER"
9927  "*
9928  {
9929    making_const_table = TRUE;
9930    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9931      {
9932       case MODE_FLOAT:
9933        {
9934          REAL_VALUE_TYPE r;
9935          REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9936          assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9937          break;
9938        }
9939      default:
9940        assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9941        break;
9942      }
9943    return \"\";
9944  }"
9945  [(set_attr "length" "8")]
9946)
9947
9948;; Miscellaneous Thumb patterns
9949
9950(define_expand "tablejump"
9951  [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9952	      (use (label_ref (match_operand 1 "" "")))])]
9953  "TARGET_THUMB"
9954  "
9955  if (flag_pic)
9956    {
9957      /* Hopefully, CSE will eliminate this copy.  */
9958      rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9959      rtx reg2 = gen_reg_rtx (SImode);
9960
9961      emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9962      operands[0] = reg2;
9963    }
9964  "
9965)
9966
9967(define_insn "*thumb_tablejump"
9968  [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9969   (use (label_ref (match_operand 1 "" "")))]
9970  "TARGET_THUMB"
9971  "mov\\t%|pc, %0"
9972  [(set_attr "length" "2")]
9973)
9974
9975;; V5 Instructions,
9976
9977(define_insn "clzsi2"
9978  [(set (match_operand:SI 0 "s_register_operand" "=r")
9979	(clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
9980  "TARGET_ARM && arm_arch5"
9981  "clz%?\\t%0, %1"
9982  [(set_attr "predicable" "yes")])
9983
9984(define_expand "ffssi2"
9985  [(set (match_operand:SI 0 "s_register_operand" "")
9986	(ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9987  "TARGET_ARM && arm_arch5"
9988  "
9989  {
9990    rtx t1, t2, t3;
9991
9992    t1 = gen_reg_rtx (SImode);
9993    t2 = gen_reg_rtx (SImode);
9994    t3 = gen_reg_rtx (SImode);
9995
9996    emit_insn (gen_negsi2 (t1, operands[1]));
9997    emit_insn (gen_andsi3 (t2, operands[1], t1));
9998    emit_insn (gen_clzsi2 (t3, t2));
9999    emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10000    DONE;
10001  }"
10002)
10003
10004(define_expand "ctzsi2"
10005  [(set (match_operand:SI 0 "s_register_operand" "")
10006	(ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10007  "TARGET_ARM && arm_arch5"
10008  "
10009  {
10010    rtx t1, t2, t3;
10011
10012    t1 = gen_reg_rtx (SImode);
10013    t2 = gen_reg_rtx (SImode);
10014    t3 = gen_reg_rtx (SImode);
10015
10016    emit_insn (gen_negsi2 (t1, operands[1]));
10017    emit_insn (gen_andsi3 (t2, operands[1], t1));
10018    emit_insn (gen_clzsi2 (t3, t2));
10019    emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10020    DONE;
10021  }"
10022)
10023
10024;; V5E instructions.
10025
10026(define_insn "prefetch"
10027  [(prefetch (match_operand:SI 0 "address_operand" "p")
10028	     (match_operand:SI 1 "" "")
10029	     (match_operand:SI 2 "" ""))]
10030  "TARGET_ARM && arm_arch5e"
10031  "pld\\t%a0")
10032
10033;; General predication pattern
10034
10035(define_cond_exec
10036  [(match_operator 0 "arm_comparison_operator"
10037    [(match_operand 1 "cc_register" "")
10038     (const_int 0)])]
10039  "TARGET_ARM"
10040  ""
10041)
10042
10043(define_insn "prologue_use"
10044  [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10045  ""
10046  "%@ %0 needed for prologue"
10047)
10048
10049;; Load the FPA co-processor patterns
10050(include "fpa.md")
10051;; Load the Maverick co-processor patterns
10052(include "cirrus.md")
10053;; Load the Intel Wireless Multimedia Extension patterns
10054(include "iwmmxt.md")
10055