arm.md revision 117395
1;;- Machine description for ARM for GNU compiler
2;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3;;  2001, 2002  Free Software Foundation, Inc.
4;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5;;  and Martin Simmons (@harleqn.co.uk).
6;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
7
8;; This file is part of GNU CC.
9
10;; GNU CC is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation; either version 2, or (at your option)
13;; any later version.
14
15;; GNU CC is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU CC; see the file COPYING.  If not, write to
22;; the Free Software Foundation, 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27;; There are patterns in this file to support XFmode arithmetic.
28;; Unfortunately RISC iX doesn't work well with these so they are disabled.
29;; (See arm.h)
30
31;;---------------------------------------------------------------------------
32;; Constants
33
34;; Register numbers
35(define_constants
36  [(IP_REGNUM	    12)		; Scratch register
37   (SP_REGNUM	    13)		; Stack pointer
38   (LR_REGNUM       14)		; Return address register
39   (PC_REGNUM	    15)		; Program counter
40   (CC_REGNUM       24)		; Condition code pseudo register
41   (LAST_ARM_REGNUM 15)
42  ]
43)
44
45;; UNSPEC Usage:
46;; Note: sin and cos are no-longer used.
47
48(define_constants
49  [(UNSPEC_SIN       0)	; `sin' operation (MODE_FLOAT):
50			;   operand 0 is the result,
51			;   operand 1 the parameter.
52   (UNPSEC_COS	     1)	; `cos' operation (MODE_FLOAT):
53			;   operand 0 is the result,
54			;   operand 1 the parameter.
55   (UNSPEC_PUSH_MULT 2)	; `push multiple' operation:
56			;   operand 0 is the first register,
57			;   subsequent registers are in parallel (use ...)
58			;   expressions.
59   (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
60			;   usage, that is, we will add the pic_register
61			;   value to it before trying to dereference it.
62   (UNSPEC_PIC_BASE  4)	; Adding the PC value to the offset to the
63			;   GLOBAL_OFFSET_TABLE.  The operation is fully
64			;   described by the RTL but must be wrapped to
65			;   prevent combine from trying to rip it apart.
66   (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
67			;   being scheduled before the stack adjustment insn.
68   (UNSPEC_CLZ	     5) ; `clz' instruction, count leading zeros (SImode):
69			;   operand 0 is the result,
70			;   operand 1 is the parameter.
71   (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
72   			; this unspec is used to prevent the deletion of
73   			; instructions setting registers for EH handling
74   			; and stack frame generation.  Operand 0 is the
75   			; register to "use".
76   (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
77  ]
78)
79
80;; UNSPEC_VOLATILE Usage:
81
82(define_constants
83  [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
84			;   insn in the code.
85   (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
86			;   instruction epilogue sequence that isn't expanded
87			;   into normal RTL.  Used for both normal and sibcall
88			;   epilogues.
89   (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
90			;   for inlined constants.
91   (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
92			;   table.
93   (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
94			;   an 8-bit object.
95   (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
96			;   a 16-bit object.
97   (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
98			;   a 32-bit object.
99   (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
100			;   a 64-bit object.
101  ]
102)
103
104;;---------------------------------------------------------------------------
105;; Attributes
106
107; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
108; generating ARM code.  This is used to control the length of some insn
109; patterns that share the same RTL in both ARM and Thumb code.
110(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
111
112; PROG_MODE attribute is used to determine whether condition codes are
113; clobbered by a call insn: they are if in prog32 mode.  This is controlled
114; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
115(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
116
117; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
118; scheduling decisions for the load unit and the multiplier.
119(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
120
121;; Operand number of an input operand that is shifted.  Zero if the
122;; given instruction does not shift one of its input operands.
123(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
124(define_attr "shift" "" (const_int 0))
125
126; Floating Point Unit.  If we only have floating point emulation, then there
127; is no point in scheduling the floating point insns.  (Well, for best
128; performance we should try and group them together).
129(define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
130
131; LENGTH of an instruction (in bytes)
132(define_attr "length" "" (const_int 4))
133
134; POOL_RANGE is how far away from a constant pool entry that this insn
135; can be placed.  If the distance is zero, then this insn will never
136; reference the pool.
137; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
138; before its address.
139(define_attr "pool_range" "" (const_int 0))
140(define_attr "neg_pool_range" "" (const_int 0))
141
142; An assembler sequence may clobber the condition codes without us knowing.
143; If such an insn references the pool, then we have no way of knowing how,
144; so use the most conservative value for pool_range.
145(define_asm_attributes
146 [(set_attr "conds" "clob")
147  (set_attr "length" "4")
148  (set_attr "pool_range" "250")])
149
150; TYPE attribute is used to detect floating point instructions which, if
151; running on a co-processor can run in parallel with other, basic instructions
152; If write-buffer scheduling is enabled then it can also be used in the
153; scheduling of writes.
154
155; Classification of each insn
156; normal	any data instruction that doesn't hit memory or fp regs
157; mult		a multiply instruction
158; block		blockage insn, this blocks all functional units
159; float		a floating point arithmetic operation (subject to expansion)
160; fdivx		XFmode floating point division
161; fdivd		DFmode floating point division
162; fdivs		SFmode floating point division
163; fmul		Floating point multiply
164; ffmul		Fast floating point multiply
165; farith	Floating point arithmetic (4 cycle)
166; ffarith	Fast floating point arithmetic (2 cycle)
167; float_em	a floating point arithmetic operation that is normally emulated
168;		even on a machine with an fpa.
169; f_load	a floating point load from memory
170; f_store	a floating point store to memory
171; f_mem_r	a transfer of a floating point register to a real reg via mem
172; r_mem_f	the reverse of f_mem_r
173; f_2_r		fast transfer float to arm (no memory needed)
174; r_2_f		fast transfer arm to float
175; call		a subroutine call
176; load		any load from memory
177; store1	store 1 word to memory from arm registers
178; store2	store 2 words
179; store3	store 3 words
180; store4	store 4 words
181;
182(define_attr "type"
183	"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" 
184	(const_string "normal"))
185
186; Load scheduling, set from the arm_ld_sched variable
187; initialized by arm_override_options() 
188(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
189
190; condition codes: this one is used by final_prescan_insn to speed up
191; conditionalizing instructions.  It saves having to scan the rtl to see if
192; it uses or alters the condition codes.
193; 
194; USE means that the condition codes are used by the insn in the process of
195;   outputting code, this means (at present) that we can't use the insn in
196;   inlined branches
197;
198; SET means that the purpose of the insn is to set the condition codes in a
199;   well defined manner.
200;
201; CLOB means that the condition codes are altered in an undefined manner, if
202;   they are altered at all
203;
204; JUMP_CLOB is used when the condition cannot be represented by a single
205;   instruction (UNEQ and LTGT).  These cannot be predicated.
206;
207; NOCOND means that the condition codes are neither altered nor affect the
208;   output of this insn
209
210(define_attr "conds" "use,set,clob,jump_clob,nocond"
211	(if_then_else (eq_attr "type" "call")
212	 (if_then_else (eq_attr "prog_mode" "prog32")
213	  (const_string "clob") (const_string "nocond"))
214	 (const_string "nocond")))
215
216; Predicable means that the insn can be conditionally executed based on
217; an automatically added predicate (additional patterns are generated by 
218; gen...).  We default to 'no' because no Thumb patterns match this rule
219; and not all ARM patterns do.
220(define_attr "predicable" "no,yes" (const_string "no"))
221
222; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
223; have one.  Later ones, such as StrongARM, have write-back caches, so don't
224; suffer blockages enough to warrent modelling this (and it can adversely
225; affect the schedule).
226(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
227
228; WRITE_CONFLICT implies that a read following an unrelated write is likely
229; to stall the processor.  Used with model_wbuf above.
230(define_attr "write_conflict" "no,yes"
231  (if_then_else (eq_attr "type"
232		 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
233		(const_string "yes")
234		(const_string "no")))
235
236; Classify the insns into those that take one cycle and those that take more
237; than one on the main cpu execution unit.
238(define_attr "core_cycles" "single,multi"
239  (if_then_else (eq_attr "type"
240		 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
241		(const_string "single")
242	        (const_string "multi")))
243
244;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
245;; distant label.  Only applicable to Thumb code.
246(define_attr "far_jump" "yes,no" (const_string "no"))
247
248;; (define_function_unit {name} {num-units} {n-users} {test}
249;;                       {ready-delay} {issue-delay} [{conflict-list}])
250
251;;--------------------------------------------------------------------
252;; Floating point unit (FPA)
253;;--------------------------------------------------------------------
254(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
255				     (eq_attr "type" "fdivx")) 71 69)
256
257(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
258				     (eq_attr "type" "fdivd")) 59 57)
259
260(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
261				     (eq_attr "type" "fdivs")) 31 29)
262
263(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
264				     (eq_attr "type" "fmul")) 9 7)
265
266(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
267				     (eq_attr "type" "ffmul")) 6 4)
268
269(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
270				     (eq_attr "type" "farith")) 4 2)
271
272(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
273				     (eq_attr "type" "ffarith")) 2 2)
274
275(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
276				     (eq_attr "type" "r_2_f")) 5 3)
277
278(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
279				     (eq_attr "type" "f_2_r")) 1 2)
280
281; The fpa10 doesn't really have a memory read unit, but it can start to
282; speculatively execute the instruction in the pipeline, provided the data
283; is already loaded, so pretend reads have a delay of 2 (and that the
284; pipeline is infinite).
285
286(define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
287					 (eq_attr "type" "f_load")) 3 1)
288
289;;--------------------------------------------------------------------
290;; Write buffer
291;;--------------------------------------------------------------------
292; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
293;
294; The write buffer on some of the arm6 processors is hard to model exactly.
295; There is room in the buffer for up to two addresses and up to eight words
296; of memory, but the two needn't be split evenly.  When writing the two
297; addresses are fully pipelined.  However, a read from memory that is not
298; currently in the cache will block until the writes have completed.
299; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
300; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
301; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
302; cycle to add as well.
303
304(define_function_unit "write_buf" 1 2
305  (and (eq_attr "model_wbuf" "yes")
306       (eq_attr "type" "store1,r_mem_f")) 5 3)
307(define_function_unit "write_buf" 1 2 
308  (and (eq_attr "model_wbuf" "yes")
309       (eq_attr "type" "store2")) 7 4)
310(define_function_unit "write_buf" 1 2
311  (and (eq_attr "model_wbuf" "yes")
312       (eq_attr "type" "store3")) 9 5)
313(define_function_unit "write_buf" 1 2
314  (and (eq_attr "model_wbuf" "yes")
315       (eq_attr "type" "store4")) 11 6)
316
317;;--------------------------------------------------------------------
318;; Write blockage unit
319;;--------------------------------------------------------------------
320; The write_blockage unit models (partially), the fact that reads will stall
321; until the write buffer empties.
322; The f_mem_r and r_mem_f could also block, but they are to the stack,
323; so we don't model them here
324(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
325						(eq_attr "type" "store1")) 5 5
326	[(eq_attr "write_conflict" "yes")])
327(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
328						(eq_attr "type" "store2")) 7 7
329	[(eq_attr "write_conflict" "yes")])
330(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
331						(eq_attr "type" "store3")) 9 9
332	[(eq_attr "write_conflict" "yes")])
333(define_function_unit "write_blockage" 1 0
334	(and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
335	[(eq_attr "write_conflict" "yes")])
336(define_function_unit "write_blockage" 1 0
337	(and (eq_attr "model_wbuf" "yes")
338	     (eq_attr "write_conflict" "yes")) 1 1)
339
340;;--------------------------------------------------------------------
341;; Core unit
342;;--------------------------------------------------------------------
343; Everything must spend at least one cycle in the core unit
344(define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
345
346(define_function_unit "core" 1 0
347  (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
348
349(define_function_unit "core" 1 0
350  (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
351
352;; We do not need to conditionalize the define_function_unit immediately
353;; above.  This one will be ignored for anything other than xscale
354;; compiles and for xscale compiles it provides a larger delay
355;; and the scheduler will DTRT.
356;; FIXME: this test needs to be revamped to not depend on this feature 
357;; of the scheduler.
358
359(define_function_unit "core" 1 0
360  (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
361       (eq_attr "is_xscale" "yes"))
362   3 1)
363
364(define_function_unit "core" 1 0
365  (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
366
367(define_function_unit "core" 1 0
368  (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
369
370(define_function_unit "core" 1 0
371  (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
372
373(define_function_unit "core" 1 0
374  (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
375
376(define_function_unit "core" 1 0
377  (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
378
379(define_function_unit "core" 1 0
380  (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
381
382(define_function_unit "core" 1 0
383  (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
384       (eq_attr "type" "mult")) 4 4)
385
386(define_function_unit "core" 1 0
387  (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
388       (eq_attr "type" "mult")) 3 2)
389
390(define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
391
392(define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
393
394(define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
395
396(define_function_unit "core" 1 0
397  (and (eq_attr "core_cycles" "multi")
398       (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
399
400;;---------------------------------------------------------------------------
401;; Insn patterns
402;;
403;; Addition insns.
404
405;; Note: For DImode insns, there is normally no reason why operands should
406;; not be in the same register, what we don't want is for something being
407;; written to partially overlap something that is an input.
408
409(define_expand "adddi3"
410 [(parallel
411   [(set (match_operand:DI           0 "s_register_operand" "")
412	  (plus:DI (match_operand:DI 1 "s_register_operand" "")
413	           (match_operand:DI 2 "s_register_operand" "")))
414    (clobber (reg:CC CC_REGNUM))])]
415  "TARGET_EITHER"
416  "
417  if (TARGET_THUMB)
418    {
419      if (GET_CODE (operands[1]) != REG)
420        operands[1] = force_reg (SImode, operands[1]);
421      if (GET_CODE (operands[2]) != REG)
422        operands[2] = force_reg (SImode, operands[2]);
423     }
424  "
425)
426
427(define_insn "*thumb_adddi3"
428  [(set (match_operand:DI          0 "register_operand" "=l")
429	(plus:DI (match_operand:DI 1 "register_operand" "%0")
430		 (match_operand:DI 2 "register_operand" "l")))
431   (clobber (reg:CC CC_REGNUM))
432  ]
433  "TARGET_THUMB"
434  "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
435  [(set_attr "length" "4")]
436)
437
438(define_insn_and_split "*arm_adddi3"
439  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
440	(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
441		 (match_operand:DI 2 "s_register_operand" "r,  0")))
442   (clobber (reg:CC CC_REGNUM))]
443  "TARGET_ARM"
444  "#"
445  "TARGET_ARM && reload_completed"
446  [(parallel [(set (reg:CC_C CC_REGNUM)
447		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
448				 (match_dup 1)))
449	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
450   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
451			       (plus:SI (match_dup 4) (match_dup 5))))]
452  "
453  {
454    operands[3] = gen_highpart (SImode, operands[0]);
455    operands[0] = gen_lowpart (SImode, operands[0]);
456    operands[4] = gen_highpart (SImode, operands[1]);
457    operands[1] = gen_lowpart (SImode, operands[1]);
458    operands[5] = gen_highpart (SImode, operands[2]);
459    operands[2] = gen_lowpart (SImode, operands[2]);
460  }"
461  [(set_attr "conds" "clob")
462   (set_attr "length" "8")]
463)
464
465(define_insn_and_split "*adddi_sesidi_di"
466  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
467	(plus:DI (sign_extend:DI
468		  (match_operand:SI 2 "s_register_operand" "r,r"))
469		 (match_operand:DI 1 "s_register_operand" "r,0")))
470   (clobber (reg:CC CC_REGNUM))]
471  "TARGET_ARM"
472  "#"
473  "TARGET_ARM && reload_completed"
474  [(parallel [(set (reg:CC_C CC_REGNUM)
475		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
476				 (match_dup 1)))
477	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
478   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
479			       (plus:SI (ashiftrt:SI (match_dup 2)
480						     (const_int 31))
481					(match_dup 4))))]
482  "
483  {
484    operands[3] = gen_highpart (SImode, operands[0]);
485    operands[0] = gen_lowpart (SImode, operands[0]);
486    operands[4] = gen_highpart (SImode, operands[1]);
487    operands[1] = gen_lowpart (SImode, operands[1]);
488    operands[2] = gen_lowpart (SImode, operands[2]);
489  }"
490  [(set_attr "conds" "clob")
491   (set_attr "length" "8")]
492)
493
494(define_insn_and_split "*adddi_zesidi_di"
495  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
496	(plus:DI (zero_extend:DI
497		  (match_operand:SI 2 "s_register_operand" "r,r"))
498		 (match_operand:DI 1 "s_register_operand" "r,0")))
499   (clobber (reg:CC CC_REGNUM))]
500  "TARGET_ARM"
501  "#"
502  "TARGET_ARM && reload_completed"
503  [(parallel [(set (reg:CC_C CC_REGNUM)
504		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
505				 (match_dup 1)))
506	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
507   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
508			       (plus:SI (match_dup 4) (const_int 0))))]
509  "
510  {
511    operands[3] = gen_highpart (SImode, operands[0]);
512    operands[0] = gen_lowpart (SImode, operands[0]);
513    operands[4] = gen_highpart (SImode, operands[1]);
514    operands[1] = gen_lowpart (SImode, operands[1]);
515    operands[2] = gen_lowpart (SImode, operands[2]);
516  }"
517  [(set_attr "conds" "clob")
518   (set_attr "length" "8")]
519)
520
521(define_expand "addsi3"
522  [(set (match_operand:SI          0 "s_register_operand" "")
523	(plus:SI (match_operand:SI 1 "s_register_operand" "")
524		 (match_operand:SI 2 "reg_or_int_operand" "")))]
525  "TARGET_EITHER"
526  "
527  if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
528    {
529      arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
530			  operands[1],
531			  (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
532      DONE;
533    }
534  "
535)
536
537; If there is a scratch available, this will be faster than synthesising the
538; addition.
539(define_peephole2
540  [(match_scratch:SI 3 "r")
541   (set (match_operand:SI          0 "s_register_operand" "")
542	(plus:SI (match_operand:SI 1 "s_register_operand" "")
543		 (match_operand:SI 2 "const_int_operand"  "")))]
544  "TARGET_ARM &&
545   !(const_ok_for_arm (INTVAL (operands[2]))
546     || const_ok_for_arm (-INTVAL (operands[2])))
547    && const_ok_for_arm (~INTVAL (operands[2]))"
548  [(set (match_dup 3) (match_dup 2))
549   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
550  ""
551)
552
553(define_insn_and_split "*arm_addsi3"
554  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
555	(plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
556		 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
557  "TARGET_ARM"
558  "@
559   add%?\\t%0, %1, %2
560   sub%?\\t%0, %1, #%n2
561   #"
562  "TARGET_ARM &&
563   GET_CODE (operands[2]) == CONST_INT
564   && !(const_ok_for_arm (INTVAL (operands[2]))
565        || const_ok_for_arm (-INTVAL (operands[2])))"
566  [(clobber (const_int 0))]
567  "
568  arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
569		      operands[1], 0);
570  DONE;
571  "
572  [(set_attr "length" "4,4,16")
573   (set_attr "predicable" "yes")]
574)
575
576;; Register group 'k' is a single register group containing only the stack
577;; register.  Trying to reload it will always fail catastrophically,
578;; so never allow those alternatives to match if reloading is needed.
579
580(define_insn "*thumb_addsi3"
581  [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
582	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
583		 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
584  "TARGET_THUMB"
585  "*
586   static const char * const asms[] = 
587   {
588     \"add\\t%0, %0, %2\",
589     \"sub\\t%0, %0, #%n2\",
590     \"add\\t%0, %1, %2\",
591     \"add\\t%0, %0, %2\",
592     \"add\\t%0, %0, %2\",
593     \"add\\t%0, %1, %2\",
594     \"add\\t%0, %1, %2\"
595   };
596   if ((which_alternative == 2 || which_alternative == 6)
597       && GET_CODE (operands[2]) == CONST_INT
598       && INTVAL (operands[2]) < 0)
599     return \"sub\\t%0, %1, #%n2\";
600   return asms[which_alternative];
601  "
602  [(set_attr "length" "2")]
603)
604
605;; Reloading and elimination of the frame pointer can
606;; sometimes cause this optimization to be missed.
607(define_peephole2
608  [(set (match_operand:SI 0 "register_operand" "")
609	(match_operand:SI 1 "const_int_operand" ""))
610   (set (match_dup 0)
611	(plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
612  "TARGET_THUMB
613   && REGNO (operands[2]) == STACK_POINTER_REGNUM 
614   && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
615   && (INTVAL (operands[1]) & 3) == 0"
616  [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
617  ""
618)
619
620(define_insn "*addsi3_compare0"
621  [(set (reg:CC_NOOV CC_REGNUM)
622	(compare:CC_NOOV
623	 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
624		  (match_operand:SI 2 "arm_add_operand"    "rI,L"))
625	 (const_int 0)))
626   (set (match_operand:SI 0 "s_register_operand" "=r,r")
627	(plus:SI (match_dup 1) (match_dup 2)))]
628  "TARGET_ARM"
629  "@
630   add%?s\\t%0, %1, %2
631   sub%?s\\t%0, %1, #%n2"
632  [(set_attr "conds" "set")]
633)
634
635(define_insn "*addsi3_compare0_scratch"
636  [(set (reg:CC_NOOV CC_REGNUM)
637	(compare:CC_NOOV
638	 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
639		  (match_operand:SI 1 "arm_add_operand"    "rI,L"))
640	 (const_int 0)))]
641  "TARGET_ARM"
642  "@
643   cmn%?\\t%0, %1
644   cmp%?\\t%0, #%n1"
645  [(set_attr "conds" "set")]
646)
647
648;; These patterns are the same ones as the two regular addsi3_compare0
649;; patterns, except we write them slightly different - the combiner
650;; tends to generate them this way.
651(define_insn "*addsi3_compare0_for_combiner"
652  [(set (reg:CC CC_REGNUM)
653	(compare:CC
654	 (match_operand:SI 1 "s_register_operand" "r,r")
655	 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
656   (set (match_operand:SI 0 "s_register_operand" "=r,r")
657	(plus:SI (match_dup 1) (match_dup 2)))]
658  "TARGET_ARM"
659  "@
660   add%?s\\t%0, %1, %2
661   sub%?s\\t%0, %1, #%n2"
662  [(set_attr "conds" "set")]
663)
664
665(define_insn "*addsi3_compare0_scratch_for_combiner"
666  [(set (reg:CC CC_REGNUM)
667	(compare:CC
668	 (match_operand:SI 0 "s_register_operand" "r,r")
669	 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
670  "TARGET_ARM"
671  "@
672   cmn%?\\t%0, %1
673   cmp%?\\t%0, #%n1"
674  [(set_attr "conds" "set")]
675)
676
677;; The next four insns work because they compare the result with one of
678;; the operands, and we know that the use of the condition code is
679;; either GEU or LTU, so we can use the carry flag from the addition
680;; instead of doing the compare a second time.
681(define_insn "*addsi3_compare_op1"
682  [(set (reg:CC_C CC_REGNUM)
683	(compare:CC_C
684	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
685		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
686	 (match_dup 1)))
687   (set (match_operand:SI 0 "s_register_operand" "=r,r")
688	(plus:SI (match_dup 1) (match_dup 2)))]
689  "TARGET_ARM"
690  "@
691   add%?s\\t%0, %1, %2
692   sub%?s\\t%0, %1, #%n2"
693  [(set_attr "conds" "set")]
694)
695
696(define_insn "*addsi3_compare_op2"
697  [(set (reg:CC_C CC_REGNUM)
698	(compare:CC_C
699	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
700		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
701	 (match_dup 2)))
702   (set (match_operand:SI 0 "s_register_operand" "=r,r")
703	(plus:SI (match_dup 1) (match_dup 2)))]
704  "TARGET_ARM"
705  "@
706   add%?s\\t%0, %1, %2
707   sub%?s\\t%0, %1, #%n2"
708  [(set_attr "conds" "set")]
709)
710
711(define_insn "*compare_addsi2_op0"
712  [(set (reg:CC_C CC_REGNUM)
713	(compare:CC_C
714	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
715		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
716	 (match_dup 0)))]
717  "TARGET_ARM"
718  "@
719   cmn%?\\t%0, %1
720   cmp%?\\t%0, #%n1"
721  [(set_attr "conds" "set")]
722)
723
724(define_insn "*compare_addsi2_op1"
725  [(set (reg:CC_C CC_REGNUM)
726	(compare:CC_C
727	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
728		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
729	 (match_dup 1)))]
730  "TARGET_ARM"
731  "@
732   cmn%?\\t%0, %1
733   cmp%?\\t%0, #%n1"
734  [(set_attr "conds" "set")]
735)
736
737(define_insn "*addsi3_carryin"
738  [(set (match_operand:SI 0 "s_register_operand" "=r")
739	(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
740		 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
741			  (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
742  "TARGET_ARM"
743  "adc%?\\t%0, %1, %2"
744  [(set_attr "conds" "use")]
745)
746
747(define_insn "*addsi3_carryin_shift"
748  [(set (match_operand:SI 0 "s_register_operand" "")
749	(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
750		 (plus:SI
751		   (match_operator:SI 2 "shift_operator"
752		      [(match_operand:SI 3 "s_register_operand" "")
753		       (match_operand:SI 4 "reg_or_int_operand" "")])
754		    (match_operand:SI 1 "s_register_operand" ""))))]
755  "TARGET_ARM"
756  "adc%?\\t%0, %1, %3%S2"
757  [(set_attr "conds" "use")]
758)
759
760(define_insn "*addsi3_carryin_alt1"
761  [(set (match_operand:SI 0 "s_register_operand" "=r")
762	(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
763			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
764		 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
765  "TARGET_ARM"
766  "adc%?\\t%0, %1, %2"
767  [(set_attr "conds" "use")]
768)
769
770(define_insn "*addsi3_carryin_alt2"
771  [(set (match_operand:SI 0 "s_register_operand" "=r")
772	(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
773			  (match_operand:SI 1 "s_register_operand" "r"))
774		 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
775  "TARGET_ARM"
776  "adc%?\\t%0, %1, %2"
777  [(set_attr "conds" "use")]
778)
779
780(define_insn "*addsi3_carryin_alt3"
781  [(set (match_operand:SI 0 "s_register_operand" "=r")
782	(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
783			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
784		 (match_operand:SI 1 "s_register_operand" "r")))]
785  "TARGET_ARM"
786  "adc%?\\t%0, %1, %2"
787  [(set_attr "conds" "use")]
788)
789
790(define_insn "incscc"
791  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
792        (plus:SI (match_operator:SI 2 "arm_comparison_operator"
793                    [(match_operand:CC 3 "cc_register" "") (const_int 0)])
794                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
795  "TARGET_ARM"
796  "@
797  add%d2\\t%0, %1, #1
798  mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
799  [(set_attr "conds" "use")
800   (set_attr "length" "4,8")]
801)
802
803(define_insn "addsf3"
804  [(set (match_operand:SF          0 "s_register_operand" "=f,f")
805	(plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
806		 (match_operand:SF 2 "fpu_add_operand"    "fG,H")))]
807  "TARGET_ARM && TARGET_HARD_FLOAT"
808  "@
809   adf%?s\\t%0, %1, %2
810   suf%?s\\t%0, %1, #%N2"
811  [(set_attr "type" "farith")
812   (set_attr "predicable" "yes")]
813)
814
815(define_insn "adddf3"
816  [(set (match_operand:DF          0 "s_register_operand" "=f,f")
817	(plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
818		 (match_operand:DF 2 "fpu_add_operand"    "fG,H")))]
819  "TARGET_ARM && TARGET_HARD_FLOAT"
820  "@
821   adf%?d\\t%0, %1, %2
822   suf%?d\\t%0, %1, #%N2"
823  [(set_attr "type" "farith")
824   (set_attr "predicable" "yes")]
825)
826
827(define_insn "*adddf_esfdf_df"
828  [(set (match_operand:DF           0 "s_register_operand" "=f,f")
829	(plus:DF (float_extend:DF
830		  (match_operand:SF 1 "s_register_operand"  "f,f"))
831		 (match_operand:DF  2 "fpu_add_operand"    "fG,H")))]
832  "TARGET_ARM && TARGET_HARD_FLOAT"
833  "@
834   adf%?d\\t%0, %1, %2
835   suf%?d\\t%0, %1, #%N2"
836  [(set_attr "type" "farith")
837   (set_attr "predicable" "yes")]
838)
839
840(define_insn "*adddf_df_esfdf"
841  [(set (match_operand:DF           0 "s_register_operand" "=f")
842	(plus:DF (match_operand:DF  1 "s_register_operand"  "f")
843		 (float_extend:DF
844		  (match_operand:SF 2 "s_register_operand"  "f"))))]
845  "TARGET_ARM && TARGET_HARD_FLOAT"
846  "adf%?d\\t%0, %1, %2"
847  [(set_attr "type" "farith")
848   (set_attr "predicable" "yes")]
849)
850
851(define_insn "*adddf_esfdf_esfdf"
852  [(set (match_operand:DF           0 "s_register_operand" "=f")
853	(plus:DF (float_extend:DF 
854		  (match_operand:SF 1 "s_register_operand" "f"))
855		 (float_extend:DF
856		  (match_operand:SF 2 "s_register_operand" "f"))))]
857  "TARGET_ARM && TARGET_HARD_FLOAT"
858  "adf%?d\\t%0, %1, %2"
859  [(set_attr "type" "farith")
860   (set_attr "predicable" "yes")]
861)
862
863(define_insn "addxf3"
864  [(set (match_operand:XF          0 "s_register_operand" "=f,f")
865	(plus:XF (match_operand:XF 1 "s_register_operand"  "f,f")
866		 (match_operand:XF 2 "fpu_add_operand"    "fG,H")))]
867  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
868  "@
869   adf%?e\\t%0, %1, %2
870   suf%?e\\t%0, %1, #%N2"
871  [(set_attr "type" "farith")
872   (set_attr "predicable" "yes")]
873)
874
875(define_expand "subdi3"
876 [(parallel
877   [(set (match_operand:DI            0 "s_register_operand" "")
878	  (minus:DI (match_operand:DI 1 "s_register_operand" "")
879	            (match_operand:DI 2 "s_register_operand" "")))
880    (clobber (reg:CC CC_REGNUM))])]
881  "TARGET_EITHER"
882  "
883  if (TARGET_THUMB)
884    {
885      if (GET_CODE (operands[1]) != REG)
886        operands[1] = force_reg (SImode, operands[1]);
887      if (GET_CODE (operands[2]) != REG)
888        operands[2] = force_reg (SImode, operands[2]);
889     }	
890  "
891)
892
893(define_insn "*arm_subdi3"
894  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
895	(minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
896		  (match_operand:DI 2 "s_register_operand" "r,0,0")))
897   (clobber (reg:CC CC_REGNUM))]
898  "TARGET_ARM"
899  "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
900  [(set_attr "conds" "clob")
901   (set_attr "length" "8")]
902)
903
904(define_insn "*thumb_subdi3"
905  [(set (match_operand:DI           0 "register_operand" "=l")
906	(minus:DI (match_operand:DI 1 "register_operand"  "0")
907		  (match_operand:DI 2 "register_operand"  "l")))
908   (clobber (reg:CC CC_REGNUM))]
909  "TARGET_THUMB"
910  "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
911  [(set_attr "length" "4")]
912)
913
914(define_insn "*subdi_di_zesidi"
915  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
916	(minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
917		  (zero_extend:DI
918		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
919   (clobber (reg:CC CC_REGNUM))]
920  "TARGET_ARM"
921  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
922  [(set_attr "conds" "clob")
923   (set_attr "length" "8")]
924)
925
926(define_insn "*subdi_di_sesidi"
927  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
928	(minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
929		  (sign_extend:DI
930		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
931   (clobber (reg:CC CC_REGNUM))]
932  "TARGET_ARM"
933  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
934  [(set_attr "conds" "clob")
935   (set_attr "length" "8")]
936)
937
938(define_insn "*subdi_zesidi_di"
939  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
940	(minus:DI (zero_extend:DI
941		   (match_operand:SI 2 "s_register_operand"  "r,r"))
942		  (match_operand:DI  1 "s_register_operand" "?r,0")))
943   (clobber (reg:CC CC_REGNUM))]
944  "TARGET_ARM"
945  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
946  [(set_attr "conds" "clob")
947   (set_attr "length" "8")]
948)
949
950(define_insn "*subdi_sesidi_di"
951  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
952	(minus:DI (sign_extend:DI
953		   (match_operand:SI 2 "s_register_operand"   "r,r"))
954		  (match_operand:DI  1 "s_register_operand"  "?r,0")))
955   (clobber (reg:CC CC_REGNUM))]
956  "TARGET_ARM"
957  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
958  [(set_attr "conds" "clob")
959   (set_attr "length" "8")]
960)
961
962(define_insn "*subdi_zesidi_zesidi"
963  [(set (match_operand:DI            0 "s_register_operand" "=r")
964	(minus:DI (zero_extend:DI
965		   (match_operand:SI 1 "s_register_operand"  "r"))
966		  (zero_extend:DI
967		   (match_operand:SI 2 "s_register_operand"  "r"))))
968   (clobber (reg:CC CC_REGNUM))]
969  "TARGET_ARM"
970  "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
971  [(set_attr "conds" "clob")
972   (set_attr "length" "8")]
973)
974
975(define_expand "subsi3"
976  [(set (match_operand:SI           0 "s_register_operand" "")
977	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
978		  (match_operand:SI 2 "s_register_operand" "")))]
979  "TARGET_EITHER"
980  "
981  if (GET_CODE (operands[1]) == CONST_INT)
982    {
983      if (TARGET_ARM)
984        {
985          arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
986	  		      operands[2],
987			      (no_new_pseudos ? 0
988			       :  preserve_subexpressions_p ()));
989          DONE;
990	}
991      else /* TARGET_THUMB */
992        operands[1] = force_reg (SImode, operands[1]);
993    }
994  "
995)
996
997(define_insn "*thumb_subsi3_insn"
998  [(set (match_operand:SI           0 "register_operand" "=l")
999	(minus:SI (match_operand:SI 1 "register_operand" "l")
1000		  (match_operand:SI 2 "register_operand" "l")))]
1001  "TARGET_THUMB"
1002  "sub\\t%0, %1, %2"
1003  [(set_attr "length" "2")]
1004)
1005
1006(define_insn_and_split "*arm_subsi3_insn"
1007  [(set (match_operand:SI           0 "s_register_operand" "=r,r")
1008	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1009		  (match_operand:SI 2 "s_register_operand" "r,r")))]
1010  "TARGET_ARM"
1011  "@
1012   rsb%?\\t%0, %2, %1
1013   #"
1014  "TARGET_ARM
1015   && GET_CODE (operands[1]) == CONST_INT
1016   && !const_ok_for_arm (INTVAL (operands[1]))"
1017  [(clobber (const_int 0))]
1018  "
1019  arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1020		      operands[2], 0);
1021  DONE;
1022  "
1023  [(set_attr "length" "4,16")
1024   (set_attr "predicable" "yes")]
1025)
1026
1027(define_peephole2
1028  [(match_scratch:SI 3 "r")
1029   (set (match_operand:SI           0 "s_register_operand" "")
1030	(minus:SI (match_operand:SI 1 "const_int_operand" "")
1031		  (match_operand:SI 2 "s_register_operand" "")))]
1032  "TARGET_ARM
1033   && !const_ok_for_arm (INTVAL (operands[1]))
1034   && const_ok_for_arm (~INTVAL (operands[1]))"
1035  [(set (match_dup 3) (match_dup 1))
1036   (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1037  ""
1038)
1039
1040(define_insn "*subsi3_compare0"
1041  [(set (reg:CC_NOOV CC_REGNUM)
1042	(compare:CC_NOOV
1043	 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1044		   (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1045	 (const_int 0)))
1046   (set (match_operand:SI 0 "s_register_operand" "=r,r")
1047	(minus:SI (match_dup 1) (match_dup 2)))]
1048  "TARGET_ARM"
1049  "@
1050   sub%?s\\t%0, %1, %2
1051   rsb%?s\\t%0, %2, %1"
1052  [(set_attr "conds" "set")]
1053)
1054
1055(define_insn "decscc"
1056  [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1057        (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1058		  (match_operator:SI 2 "arm_comparison_operator"
1059                   [(match_operand   3 "cc_register" "") (const_int 0)])))]
1060  "TARGET_ARM"
1061  "@
1062   sub%d2\\t%0, %1, #1
1063   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1064  [(set_attr "conds" "use")
1065   (set_attr "length" "*,8")]
1066)
1067
1068(define_insn "subsf3"
1069  [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1070	(minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1071		  (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1072  "TARGET_ARM && TARGET_HARD_FLOAT"
1073  "@
1074   suf%?s\\t%0, %1, %2
1075   rsf%?s\\t%0, %2, %1"
1076  [(set_attr "type" "farith")]
1077)
1078
1079(define_insn "subdf3"
1080  [(set (match_operand:DF           0 "s_register_operand" "=f,f")
1081	(minus:DF (match_operand:DF 1 "fpu_rhs_operand"     "f,G")
1082		  (match_operand:DF 2 "fpu_rhs_operand"    "fG,f")))]
1083  "TARGET_ARM && TARGET_HARD_FLOAT"
1084  "@
1085   suf%?d\\t%0, %1, %2
1086   rsf%?d\\t%0, %2, %1"
1087  [(set_attr "type" "farith")
1088   (set_attr "predicable" "yes")]
1089)
1090
1091(define_insn "*subdf_esfdf_df"
1092  [(set (match_operand:DF            0 "s_register_operand" "=f")
1093	(minus:DF (float_extend:DF
1094		   (match_operand:SF 1 "s_register_operand"  "f"))
1095		  (match_operand:DF  2 "fpu_rhs_operand"    "fG")))]
1096  "TARGET_ARM && TARGET_HARD_FLOAT"
1097  "suf%?d\\t%0, %1, %2"
1098  [(set_attr "type" "farith")
1099   (set_attr "predicable" "yes")]
1100)
1101
1102(define_insn "*subdf_df_esfdf"
1103  [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1104	(minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1105		  (float_extend:DF
1106		   (match_operand:SF 2 "s_register_operand" "f,f"))))]
1107  "TARGET_ARM && TARGET_HARD_FLOAT"
1108  "@
1109   suf%?d\\t%0, %1, %2
1110   rsf%?d\\t%0, %2, %1"
1111  [(set_attr "type" "farith")
1112   (set_attr "predicable" "yes")]
1113)
1114
1115(define_insn "*subdf_esfdf_esfdf"
1116  [(set (match_operand:DF 0 "s_register_operand" "=f")
1117	(minus:DF (float_extend:DF
1118		   (match_operand:SF 1 "s_register_operand" "f"))
1119		  (float_extend:DF
1120		   (match_operand:SF 2 "s_register_operand" "f"))))]
1121  "TARGET_ARM && TARGET_HARD_FLOAT"
1122  "suf%?d\\t%0, %1, %2"
1123  [(set_attr "type" "farith")
1124   (set_attr "predicable" "yes")]
1125)
1126
1127(define_insn "subxf3"
1128  [(set (match_operand:XF           0 "s_register_operand" "=f,f")
1129	(minus:XF (match_operand:XF 1 "fpu_rhs_operand"     "f,G")
1130		  (match_operand:XF 2 "fpu_rhs_operand"    "fG,f")))]
1131  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1132  "@
1133   suf%?e\\t%0, %1, %2
1134   rsf%?e\\t%0, %2, %1"
1135  [(set_attr "type" "farith")
1136   (set_attr "predicable" "yes")]
1137)
1138
1139;; Multiplication insns
1140
1141(define_expand "mulsi3"
1142  [(set (match_operand:SI          0 "s_register_operand" "")
1143	(mult:SI (match_operand:SI 2 "s_register_operand" "")
1144		 (match_operand:SI 1 "s_register_operand" "")))]
1145  "TARGET_EITHER"
1146  ""
1147)
1148
1149;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1150(define_insn "*arm_mulsi3"
1151  [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1152	(mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1153		 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1154  "TARGET_ARM"
1155  "mul%?\\t%0, %2, %1"
1156  [(set_attr "type" "mult")
1157   (set_attr "predicable" "yes")]
1158)
1159
1160; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1161; 1 and 2; are the same, because reload will make operand 0 match 
1162; operand 1 without realizing that this conflicts with operand 2.  We fix 
1163; this by adding another alternative to match this case, and then `reload' 
1164; it ourselves.  This alternative must come first.
1165(define_insn "*thumb_mulsi3"
1166  [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1167	(mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1168		 (match_operand:SI 2 "register_operand" "l,l,l")))]
1169  "TARGET_THUMB"
1170  "*
1171  if (which_alternative < 2)
1172    return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1173  else
1174    return \"mul\\t%0, %0, %2\";
1175  "
1176  [(set_attr "length" "4,4,2")
1177   (set_attr "type" "mult")]
1178)
1179
1180(define_insn "*mulsi3_compare0"
1181  [(set (reg:CC_NOOV CC_REGNUM)
1182	(compare:CC_NOOV (mult:SI
1183			  (match_operand:SI 2 "s_register_operand" "r,r")
1184			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
1185			 (const_int 0)))
1186   (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1187	(mult:SI (match_dup 2) (match_dup 1)))]
1188  "TARGET_ARM && !arm_is_xscale"
1189  "mul%?s\\t%0, %2, %1"
1190  [(set_attr "conds" "set")
1191   (set_attr "type" "mult")]
1192)
1193
1194(define_insn "*mulsi_compare0_scratch"
1195  [(set (reg:CC_NOOV CC_REGNUM)
1196	(compare:CC_NOOV (mult:SI
1197			  (match_operand:SI 2 "s_register_operand" "r,r")
1198			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
1199			 (const_int 0)))
1200   (clobber (match_scratch:SI 0 "=&r,&r"))]
1201  "TARGET_ARM && !arm_is_xscale"
1202  "mul%?s\\t%0, %2, %1"
1203  [(set_attr "conds" "set")
1204   (set_attr "type" "mult")]
1205)
1206
1207;; Unnamed templates to match MLA instruction.
1208
1209(define_insn "*mulsi3addsi"
1210  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1211	(plus:SI
1212	  (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1213		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1214	  (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1215  "TARGET_ARM"
1216  "mla%?\\t%0, %2, %1, %3"
1217  [(set_attr "type" "mult")
1218   (set_attr "predicable" "yes")]
1219)
1220
1221(define_insn "*mulsi3addsi_compare0"
1222  [(set (reg:CC_NOOV CC_REGNUM)
1223	(compare:CC_NOOV
1224	 (plus:SI (mult:SI
1225		   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1226		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1227		  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1228	 (const_int 0)))
1229   (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1230	(plus:SI (mult:SI (match_dup 2) (match_dup 1))
1231		 (match_dup 3)))]
1232  "TARGET_ARM && !arm_is_xscale"
1233  "mla%?s\\t%0, %2, %1, %3"
1234  [(set_attr "conds" "set")
1235   (set_attr "type" "mult")]
1236)
1237
1238(define_insn "*mulsi3addsi_compare0_scratch"
1239  [(set (reg:CC_NOOV CC_REGNUM)
1240	(compare:CC_NOOV
1241	 (plus:SI (mult:SI
1242		   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1243		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1244		  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1245	 (const_int 0)))
1246   (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1247  "TARGET_ARM && !arm_is_xscale"
1248  "mla%?s\\t%0, %2, %1, %3"
1249  [(set_attr "conds" "set")
1250   (set_attr "type" "mult")]
1251)
1252
1253;; Unnamed template to match long long multiply-accumlate (smlal)
1254
1255(define_insn "*mulsidi3adddi"
1256  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1257	(plus:DI
1258	 (mult:DI
1259	  (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1260	  (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1261	 (match_operand:DI 1 "s_register_operand" "0")))]
1262  "TARGET_ARM && arm_fast_multiply"
1263  "smlal%?\\t%Q0, %R0, %3, %2"
1264  [(set_attr "type" "mult")
1265   (set_attr "predicable" "yes")]
1266)
1267
1268(define_insn "mulsidi3"
1269  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1270	(mult:DI
1271	 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1272	 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1273  "TARGET_ARM && arm_fast_multiply"
1274  "smull%?\\t%Q0, %R0, %1, %2"
1275  [(set_attr "type" "mult")
1276   (set_attr "predicable" "yes")]
1277)
1278
1279(define_insn "umulsidi3"
1280  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1281	(mult:DI
1282	 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1283	 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1284  "TARGET_ARM && arm_fast_multiply"
1285  "umull%?\\t%Q0, %R0, %1, %2"
1286  [(set_attr "type" "mult")
1287   (set_attr "predicable" "yes")]
1288)
1289
1290;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1291
1292(define_insn "*umulsidi3adddi"
1293  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1294	(plus:DI
1295	 (mult:DI
1296	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1297	  (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1298	 (match_operand:DI 1 "s_register_operand" "0")))]
1299  "TARGET_ARM && arm_fast_multiply"
1300  "umlal%?\\t%Q0, %R0, %3, %2"
1301  [(set_attr "type" "mult")
1302   (set_attr "predicable" "yes")]
1303)
1304
1305(define_insn "smulsi3_highpart"
1306  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1307	(truncate:SI
1308	 (lshiftrt:DI
1309	  (mult:DI
1310	   (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1311	   (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1312	  (const_int 32))))
1313   (clobber (match_scratch:SI 3 "=&r,&r"))]
1314  "TARGET_ARM && arm_fast_multiply"
1315  "smull%?\\t%3, %0, %2, %1"
1316  [(set_attr "type" "mult")
1317   (set_attr "predicable" "yes")]
1318)
1319
1320(define_insn "umulsi3_highpart"
1321  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1322	(truncate:SI
1323	 (lshiftrt:DI
1324	  (mult:DI
1325	   (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1326	   (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1327	  (const_int 32))))
1328   (clobber (match_scratch:SI 3 "=&r,&r"))]
1329  "TARGET_ARM && arm_fast_multiply"
1330  "umull%?\\t%3, %0, %2, %1"
1331  [(set_attr "type" "mult")
1332   (set_attr "predicable" "yes")]
1333)
1334
1335(define_insn "mulhisi3"
1336  [(set (match_operand:SI 0 "s_register_operand" "=r")
1337	(mult:SI (sign_extend:SI
1338		  (match_operand:HI 1 "s_register_operand" "%r"))
1339		 (sign_extend:SI
1340		  (match_operand:HI 2 "s_register_operand" "r"))))]
1341  "TARGET_ARM && arm_is_xscale"
1342  "smulbb%?\\t%0, %1, %2"
1343  [(set_attr "type" "mult")]
1344)
1345
1346(define_insn "*mulhisi3addsi"
1347  [(set (match_operand:SI 0 "s_register_operand" "=r")
1348	(plus:SI (match_operand:SI 1 "s_register_operand" "r")
1349		 (mult:SI (sign_extend:SI
1350			   (match_operand:HI 2 "s_register_operand" "%r"))
1351			  (sign_extend:SI
1352			   (match_operand:HI 3 "s_register_operand" "r")))))]
1353  "TARGET_ARM && arm_is_xscale"
1354  "smlabb%?\\t%0, %2, %3, %1"
1355  [(set_attr "type" "mult")]
1356)
1357
1358(define_insn "*mulhidi3adddi"
1359  [(set (match_operand:DI 0 "s_register_operand" "=r")
1360	(plus:DI
1361	  (match_operand:DI 1 "s_register_operand" "0")
1362	  (mult:DI (sign_extend:DI
1363	 	    (match_operand:HI 2 "s_register_operand" "%r"))
1364		   (sign_extend:DI
1365		    (match_operand:HI 3 "s_register_operand" "r")))))]
1366  "TARGET_ARM && arm_is_xscale"
1367  "smlalbb%?\\t%Q0, %R0, %2, %3"
1368[(set_attr "type" "mult")])
1369
1370(define_insn "mulsf3"
1371  [(set (match_operand:SF 0 "s_register_operand" "=f")
1372	(mult:SF (match_operand:SF 1 "s_register_operand" "f")
1373		 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1374  "TARGET_ARM && TARGET_HARD_FLOAT"
1375  "fml%?s\\t%0, %1, %2"
1376  [(set_attr "type" "ffmul")
1377   (set_attr "predicable" "yes")]
1378)
1379
1380(define_insn "muldf3"
1381  [(set (match_operand:DF 0 "s_register_operand" "=f")
1382	(mult:DF (match_operand:DF 1 "s_register_operand" "f")
1383		 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1384  "TARGET_ARM && TARGET_HARD_FLOAT"
1385  "muf%?d\\t%0, %1, %2"
1386  [(set_attr "type" "fmul")
1387   (set_attr "predicable" "yes")]
1388)
1389
1390(define_insn "*muldf_esfdf_df"
1391  [(set (match_operand:DF 0 "s_register_operand" "=f")
1392	(mult:DF (float_extend:DF
1393		  (match_operand:SF 1 "s_register_operand" "f"))
1394		 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1395  "TARGET_ARM && TARGET_HARD_FLOAT"
1396  "muf%?d\\t%0, %1, %2"
1397  [(set_attr "type" "fmul")
1398   (set_attr "predicable" "yes")]
1399)
1400
1401(define_insn "*muldf_df_esfdf"
1402  [(set (match_operand:DF 0 "s_register_operand" "=f")
1403	(mult:DF (match_operand:DF 1 "s_register_operand" "f")
1404		 (float_extend:DF
1405		  (match_operand:SF 2 "s_register_operand" "f"))))]
1406  "TARGET_ARM && TARGET_HARD_FLOAT"
1407  "muf%?d\\t%0, %1, %2"
1408  [(set_attr "type" "fmul")
1409   (set_attr "predicable" "yes")]
1410)
1411
1412(define_insn "*muldf_esfdf_esfdf"
1413  [(set (match_operand:DF 0 "s_register_operand" "=f")
1414	(mult:DF
1415	 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1416	 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1417  "TARGET_ARM && TARGET_HARD_FLOAT"
1418  "muf%?d\\t%0, %1, %2"
1419  [(set_attr "type" "fmul")
1420   (set_attr "predicable" "yes")]
1421)
1422
1423(define_insn "mulxf3"
1424  [(set (match_operand:XF 0 "s_register_operand" "=f")
1425	(mult:XF (match_operand:XF 1 "s_register_operand" "f")
1426		 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1427  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1428  "muf%?e\\t%0, %1, %2"
1429  [(set_attr "type" "fmul")
1430   (set_attr "predicable" "yes")]
1431)
1432
1433;; Division insns
1434
1435(define_insn "divsf3"
1436  [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1437	(div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1438		(match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1439  "TARGET_ARM && TARGET_HARD_FLOAT"
1440  "@
1441   fdv%?s\\t%0, %1, %2
1442   frd%?s\\t%0, %2, %1"
1443  [(set_attr "type" "fdivs")
1444   (set_attr "predicable" "yes")]
1445)
1446
1447(define_insn "divdf3"
1448  [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1449	(div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1450		(match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1451  "TARGET_ARM && TARGET_HARD_FLOAT"
1452  "@
1453   dvf%?d\\t%0, %1, %2
1454   rdf%?d\\t%0, %2, %1"
1455  [(set_attr "type" "fdivd")
1456   (set_attr "predicable" "yes")]
1457)
1458
1459(define_insn "*divdf_esfdf_df"
1460  [(set (match_operand:DF 0 "s_register_operand" "=f")
1461	(div:DF (float_extend:DF
1462		 (match_operand:SF 1 "s_register_operand" "f"))
1463		(match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1464  "TARGET_ARM && TARGET_HARD_FLOAT"
1465  "dvf%?d\\t%0, %1, %2"
1466  [(set_attr "type" "fdivd")
1467   (set_attr "predicable" "yes")]
1468)
1469
1470(define_insn "*divdf_df_esfdf"
1471  [(set (match_operand:DF 0 "s_register_operand" "=f")
1472	(div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1473		(float_extend:DF
1474		 (match_operand:SF 2 "s_register_operand" "f"))))]
1475  "TARGET_ARM && TARGET_HARD_FLOAT"
1476  "rdf%?d\\t%0, %2, %1"
1477  [(set_attr "type" "fdivd")
1478   (set_attr "predicable" "yes")]
1479)
1480
1481(define_insn "*divdf_esfdf_esfdf"
1482  [(set (match_operand:DF 0 "s_register_operand" "=f")
1483	(div:DF (float_extend:DF
1484		 (match_operand:SF 1 "s_register_operand" "f"))
1485		(float_extend:DF
1486		 (match_operand:SF 2 "s_register_operand" "f"))))]
1487  "TARGET_ARM && TARGET_HARD_FLOAT"
1488  "dvf%?d\\t%0, %1, %2"
1489  [(set_attr "type" "fdivd")
1490   (set_attr "predicable" "yes")]
1491)
1492
1493(define_insn "divxf3"
1494  [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1495	(div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1496		(match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1497  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1498  "@
1499   dvf%?e\\t%0, %1, %2
1500   rdf%?e\\t%0, %2, %1"
1501  [(set_attr "type" "fdivx")
1502   (set_attr "predicable" "yes")]
1503)
1504
1505;; Modulo insns
1506
1507(define_insn "modsf3"
1508  [(set (match_operand:SF 0 "s_register_operand" "=f")
1509	(mod:SF (match_operand:SF 1 "s_register_operand" "f")
1510		(match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1511  "TARGET_ARM && TARGET_HARD_FLOAT"
1512  "rmf%?s\\t%0, %1, %2"
1513  [(set_attr "type" "fdivs")
1514   (set_attr "predicable" "yes")]
1515)
1516
1517(define_insn "moddf3"
1518  [(set (match_operand:DF 0 "s_register_operand" "=f")
1519	(mod:DF (match_operand:DF 1 "s_register_operand" "f")
1520		(match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1521  "TARGET_ARM && TARGET_HARD_FLOAT"
1522  "rmf%?d\\t%0, %1, %2"
1523  [(set_attr "type" "fdivd")
1524   (set_attr "predicable" "yes")]
1525)
1526
1527(define_insn "*moddf_esfdf_df"
1528  [(set (match_operand:DF 0 "s_register_operand" "=f")
1529	(mod:DF (float_extend:DF
1530		 (match_operand:SF 1 "s_register_operand" "f"))
1531		(match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1532  "TARGET_ARM && TARGET_HARD_FLOAT"
1533  "rmf%?d\\t%0, %1, %2"
1534  [(set_attr "type" "fdivd")
1535   (set_attr "predicable" "yes")]
1536)
1537
1538(define_insn "*moddf_df_esfdf"
1539  [(set (match_operand:DF 0 "s_register_operand" "=f")
1540	(mod:DF (match_operand:DF 1 "s_register_operand" "f")
1541		(float_extend:DF
1542		 (match_operand:SF 2 "s_register_operand" "f"))))]
1543  "TARGET_ARM && TARGET_HARD_FLOAT"
1544  "rmf%?d\\t%0, %1, %2"
1545  [(set_attr "type" "fdivd")
1546   (set_attr "predicable" "yes")]
1547)
1548
1549(define_insn "*moddf_esfdf_esfdf"
1550  [(set (match_operand:DF 0 "s_register_operand" "=f")
1551	(mod:DF (float_extend:DF
1552		 (match_operand:SF 1 "s_register_operand" "f"))
1553		(float_extend:DF
1554		 (match_operand:SF 2 "s_register_operand" "f"))))]
1555  "TARGET_ARM && TARGET_HARD_FLOAT"
1556  "rmf%?d\\t%0, %1, %2"
1557  [(set_attr "type" "fdivd")
1558   (set_attr "predicable" "yes")]
1559)
1560
1561(define_insn "modxf3"
1562  [(set (match_operand:XF 0 "s_register_operand" "=f")
1563	(mod:XF (match_operand:XF 1 "s_register_operand" "f")
1564		(match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1565  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1566  "rmf%?e\\t%0, %1, %2"
1567  [(set_attr "type" "fdivx")
1568   (set_attr "predicable" "yes")]
1569)
1570
1571;; Boolean and,ior,xor insns
1572
1573;; Split up double word logical operations
1574
1575;; Split up simple DImode logical operations.  Simply perform the logical
1576;; operation on the upper and lower halves of the registers.
1577(define_split
1578  [(set (match_operand:DI 0 "s_register_operand" "")
1579	(match_operator:DI 6 "logical_binary_operator"
1580	  [(match_operand:DI 1 "s_register_operand" "")
1581	   (match_operand:DI 2 "s_register_operand" "")]))]
1582  "TARGET_ARM && reload_completed"
1583  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1584   (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1585  "
1586  {
1587    operands[3] = gen_highpart (SImode, operands[0]);
1588    operands[0] = gen_lowpart (SImode, operands[0]);
1589    operands[4] = gen_highpart (SImode, operands[1]);
1590    operands[1] = gen_lowpart (SImode, operands[1]);
1591    operands[5] = gen_highpart (SImode, operands[2]);
1592    operands[2] = gen_lowpart (SImode, operands[2]);
1593  }"
1594)
1595
1596(define_split
1597  [(set (match_operand:DI 0 "s_register_operand" "")
1598	(match_operator:DI 6 "logical_binary_operator"
1599	  [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1600	   (match_operand:DI 1 "s_register_operand" "")]))]
1601  "TARGET_ARM && reload_completed"
1602  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1603   (set (match_dup 3) (match_op_dup:SI 6
1604			[(ashiftrt:SI (match_dup 2) (const_int 31))
1605			 (match_dup 4)]))]
1606  "
1607  {
1608    operands[3] = gen_highpart (SImode, operands[0]);
1609    operands[0] = gen_lowpart (SImode, operands[0]);
1610    operands[4] = gen_highpart (SImode, operands[1]);
1611    operands[1] = gen_lowpart (SImode, operands[1]);
1612    operands[5] = gen_highpart (SImode, operands[2]);
1613    operands[2] = gen_lowpart (SImode, operands[2]);
1614  }"
1615)
1616
1617;; The zero extend of operand 2 means we can just copy the high part of
1618;; operand1 into operand0.
1619(define_split
1620  [(set (match_operand:DI 0 "s_register_operand" "")
1621	(ior:DI
1622	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1623	  (match_operand:DI 1 "s_register_operand" "")))]
1624  "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1625  [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1626   (set (match_dup 3) (match_dup 4))]
1627  "
1628  {
1629    operands[4] = gen_highpart (SImode, operands[1]);
1630    operands[3] = gen_highpart (SImode, operands[0]);
1631    operands[0] = gen_lowpart (SImode, operands[0]);
1632    operands[1] = gen_lowpart (SImode, operands[1]);
1633  }"
1634)
1635
1636;; The zero extend of operand 2 means we can just copy the high part of
1637;; operand1 into operand0.
1638(define_split
1639  [(set (match_operand:DI 0 "s_register_operand" "")
1640	(xor:DI
1641	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1642	  (match_operand:DI 1 "s_register_operand" "")))]
1643  "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1644  [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1645   (set (match_dup 3) (match_dup 4))]
1646  "
1647  {
1648    operands[4] = gen_highpart (SImode, operands[1]);
1649    operands[3] = gen_highpart (SImode, operands[0]);
1650    operands[0] = gen_lowpart (SImode, operands[0]);
1651    operands[1] = gen_lowpart (SImode, operands[1]);
1652  }"
1653)
1654
1655(define_insn "anddi3"
1656  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1657	(and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1658		(match_operand:DI 2 "s_register_operand"   "r,r")))]
1659  "TARGET_ARM"
1660  "#"
1661  [(set_attr "length" "8")]
1662)
1663
1664(define_insn_and_split "*anddi_zesidi_di"
1665  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1666	(and:DI (zero_extend:DI
1667		 (match_operand:SI 2 "s_register_operand" "r,r"))
1668		(match_operand:DI 1 "s_register_operand" "?r,0")))]
1669  "TARGET_ARM"
1670  "#"
1671  "TARGET_ARM && reload_completed"
1672  ; The zero extend of operand 2 clears the high word of the output
1673  ; operand.
1674  [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1675   (set (match_dup 3) (const_int 0))]
1676  "
1677  {
1678    operands[3] = gen_highpart (SImode, operands[0]);
1679    operands[0] = gen_lowpart (SImode, operands[0]);
1680    operands[1] = gen_lowpart (SImode, operands[1]);
1681  }"
1682  [(set_attr "length" "8")]
1683)
1684
1685(define_insn "*anddi_sesdi_di"
1686  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1687	(and:DI (sign_extend:DI
1688		 (match_operand:SI 2 "s_register_operand" "r,r"))
1689		(match_operand:DI  1 "s_register_operand" "?r,0")))]
1690  "TARGET_ARM"
1691  "#"
1692  [(set_attr "length" "8")]
1693)
1694
1695(define_expand "andsi3"
1696  [(set (match_operand:SI         0 "s_register_operand" "")
1697	(and:SI (match_operand:SI 1 "s_register_operand" "")
1698		(match_operand:SI 2 "reg_or_int_operand" "")))]
1699  "TARGET_EITHER"
1700  "
1701  if (TARGET_ARM)
1702    {
1703      if (GET_CODE (operands[2]) == CONST_INT)
1704        {
1705          arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1706			      operands[1],
1707			      (no_new_pseudos
1708			       ? 0 : preserve_subexpressions_p ()));
1709          DONE;
1710        }
1711    }
1712  else /* TARGET_THUMB */
1713    {
1714      if (GET_CODE (operands[2]) != CONST_INT)
1715        operands[2] = force_reg (SImode, operands[2]);
1716      else
1717        {
1718          int i;
1719	  
1720          if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1721  	    {
1722	      operands[2] = force_reg (SImode,
1723				       GEN_INT (~INTVAL (operands[2])));
1724	      
1725	      emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1726	      
1727	      DONE;
1728	    }
1729
1730          for (i = 9; i <= 31; i++)
1731	    {
1732	      if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1733	        {
1734	          emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1735			 	        const0_rtx));
1736	          DONE;
1737	        }
1738	      else if ((((HOST_WIDE_INT) 1) << i) - 1
1739		       == ~INTVAL (operands[2]))
1740	        {
1741	          rtx shift = GEN_INT (i);
1742	          rtx reg = gen_reg_rtx (SImode);
1743		
1744	          emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1745	          emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1746		  
1747	          DONE;
1748	        }
1749	    }
1750
1751          operands[2] = force_reg (SImode, operands[2]);
1752        }
1753    }
1754  "
1755)
1756
1757(define_insn_and_split "*arm_andsi3_insn"
1758  [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1759	(and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1760		(match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1761  "TARGET_ARM"
1762  "@
1763   and%?\\t%0, %1, %2
1764   bic%?\\t%0, %1, #%B2
1765   #"
1766  "TARGET_ARM
1767   && GET_CODE (operands[2]) == CONST_INT
1768   && !(const_ok_for_arm (INTVAL (operands[2]))
1769	|| const_ok_for_arm (~INTVAL (operands[2])))"
1770  [(clobber (const_int 0))]
1771  "
1772  arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1773		       operands[1], 0);
1774  DONE;
1775  "
1776  [(set_attr "length" "4,4,16")
1777   (set_attr "predicable" "yes")]
1778)
1779
1780(define_insn "*thumb_andsi3_insn"
1781  [(set (match_operand:SI         0 "register_operand" "=l")
1782	(and:SI (match_operand:SI 1 "register_operand" "%0")
1783		(match_operand:SI 2 "register_operand" "l")))]
1784  "TARGET_THUMB"
1785  "and\\t%0, %0, %2"
1786  [(set_attr "length" "2")]
1787)
1788
1789(define_insn "*andsi3_compare0"
1790  [(set (reg:CC_NOOV CC_REGNUM)
1791	(compare:CC_NOOV
1792	 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1793		 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1794	 (const_int 0)))
1795   (set (match_operand:SI          0 "s_register_operand" "=r,r")
1796	(and:SI (match_dup 1) (match_dup 2)))]
1797  "TARGET_ARM"
1798  "@
1799   and%?s\\t%0, %1, %2
1800   bic%?s\\t%0, %1, #%B2"
1801  [(set_attr "conds" "set")]
1802)
1803
1804(define_insn "*andsi3_compare0_scratch"
1805  [(set (reg:CC_NOOV CC_REGNUM)
1806	(compare:CC_NOOV
1807	 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1808		 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1809	 (const_int 0)))
1810   (clobber (match_scratch:SI 2 "=X,r"))]
1811  "TARGET_ARM"
1812  "@
1813   tst%?\\t%0, %1
1814   bic%?s\\t%2, %0, #%B1"
1815  [(set_attr "conds" "set")]
1816)
1817
1818(define_insn "*zeroextractsi_compare0_scratch"
1819  [(set (reg:CC_NOOV CC_REGNUM)
1820	(compare:CC_NOOV (zero_extract:SI
1821			  (match_operand:SI 0 "s_register_operand" "r")
1822		 	  (match_operand 1 "const_int_operand" "n")
1823			  (match_operand 2 "const_int_operand" "n"))
1824			 (const_int 0)))]
1825  "TARGET_ARM
1826  && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1827      && INTVAL (operands[1]) > 0 
1828      && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1829      && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1830  "*
1831  operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1832			 << INTVAL (operands[2]));
1833  output_asm_insn (\"tst%?\\t%0, %1\", operands);
1834  return \"\";
1835  "
1836  [(set_attr "conds" "set")]
1837)
1838
1839(define_insn "*ne_zeroextractsi"
1840  [(set (match_operand:SI 0 "s_register_operand" "=r")
1841	(ne:SI (zero_extract:SI
1842		(match_operand:SI 1 "s_register_operand" "r")
1843		(match_operand:SI 2 "const_int_operand" "n")
1844		(match_operand:SI 3 "const_int_operand" "n"))
1845	       (const_int 0)))
1846   (clobber (reg:CC CC_REGNUM))]
1847  "TARGET_ARM
1848   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1849       && INTVAL (operands[2]) > 0 
1850       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1851       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1852  "*
1853  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1854			 << INTVAL (operands[3]));
1855  output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1856  return \"movne\\t%0, #1\";
1857  "
1858  [(set_attr "conds" "clob")
1859   (set_attr "length" "8")]
1860)
1861
1862;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1863;;; represented by the bitfield, then this will produce incorrect results.
1864;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1865;;; which have a real bit-field insert instruction, the truncation happens
1866;;; in the bit-field insert instruction itself.  Since arm does not have a
1867;;; bit-field insert instruction, we would have to emit code here to truncate
1868;;; the value before we insert.  This loses some of the advantage of having
1869;;; this insv pattern, so this pattern needs to be reevalutated.
1870
1871(define_expand "insv"
1872  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1873                         (match_operand:SI 1 "general_operand" "")
1874                         (match_operand:SI 2 "general_operand" ""))
1875        (match_operand:SI 3 "reg_or_int_operand" ""))]
1876  "TARGET_ARM"
1877  "
1878  {
1879    int start_bit = INTVAL (operands[2]);
1880    int width = INTVAL (operands[1]);
1881    HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1882    rtx target, subtarget;
1883
1884    target = operands[0];
1885    /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1886       subreg as the final target.  */
1887    if (GET_CODE (target) == SUBREG)
1888      {
1889	subtarget = gen_reg_rtx (SImode);
1890	if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1891	    < GET_MODE_SIZE (SImode))
1892	  target = SUBREG_REG (target);
1893      }
1894    else
1895      subtarget = target;    
1896
1897    if (GET_CODE (operands[3]) == CONST_INT)
1898      {
1899	/* Since we are inserting a known constant, we may be able to
1900	   reduce the number of bits that we have to clear so that
1901	   the mask becomes simple.  */
1902	/* ??? This code does not check to see if the new mask is actually
1903	   simpler.  It may not be.  */
1904	rtx op1 = gen_reg_rtx (SImode);
1905	/* ??? Truncate operand3 to fit in the bitfield.  See comment before
1906	   start of this pattern.  */
1907	HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1908	HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1909
1910	emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1911	emit_insn (gen_iorsi3 (subtarget, op1,
1912			       GEN_INT (op3_value << start_bit)));
1913      }
1914    else if (start_bit == 0
1915	     && !(const_ok_for_arm (mask)
1916		  || const_ok_for_arm (~mask)))
1917      {
1918	/* A Trick, since we are setting the bottom bits in the word,
1919	   we can shift operand[3] up, operand[0] down, OR them together
1920	   and rotate the result back again.  This takes 3 insns, and
1921	   the third might be mergable into another op.  */
1922	/* The shift up copes with the possibility that operand[3] is
1923           wider than the bitfield.  */
1924	rtx op0 = gen_reg_rtx (SImode);
1925	rtx op1 = gen_reg_rtx (SImode);
1926
1927	emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1928	emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1929	emit_insn (gen_iorsi3  (op1, op1, op0));
1930	emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1931      }
1932    else if ((width + start_bit == 32)
1933	     && !(const_ok_for_arm (mask)
1934		  || const_ok_for_arm (~mask)))
1935      {
1936	/* Similar trick, but slightly less efficient.  */
1937
1938	rtx op0 = gen_reg_rtx (SImode);
1939	rtx op1 = gen_reg_rtx (SImode);
1940
1941	emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1942	emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1943	emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1944	emit_insn (gen_iorsi3 (subtarget, op1, op0));
1945      }
1946    else
1947      {
1948	rtx op0 = GEN_INT (mask);
1949	rtx op1 = gen_reg_rtx (SImode);
1950	rtx op2 = gen_reg_rtx (SImode);
1951
1952	if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1953	  {
1954	    rtx tmp = gen_reg_rtx (SImode);
1955
1956	    emit_insn (gen_movsi (tmp, op0));
1957	    op0 = tmp;
1958	  }
1959
1960	/* Mask out any bits in operand[3] that are not needed.  */
1961	   emit_insn (gen_andsi3 (op1, operands[3], op0));
1962
1963	if (GET_CODE (op0) == CONST_INT
1964	    && (const_ok_for_arm (mask << start_bit)
1965		|| const_ok_for_arm (~(mask << start_bit))))
1966	  {
1967	    op0 = GEN_INT (~(mask << start_bit));
1968	    emit_insn (gen_andsi3 (op2, operands[0], op0));
1969	  }
1970	else
1971	  {
1972	    if (GET_CODE (op0) == CONST_INT)
1973	      {
1974		rtx tmp = gen_reg_rtx (SImode);
1975
1976		emit_insn (gen_movsi (tmp, op0));
1977		op0 = tmp;
1978	      }
1979
1980	    if (start_bit != 0)
1981	      emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1982	    
1983	    emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1984	  }
1985
1986	if (start_bit != 0)
1987          emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1988
1989	emit_insn (gen_iorsi3 (subtarget, op1, op2));
1990      }
1991
1992    if (subtarget != target)
1993      {
1994	/* If TARGET is still a SUBREG, then it must be wider than a word,
1995	   so we must be careful only to set the subword we were asked to.  */
1996	if (GET_CODE (target) == SUBREG)
1997	  emit_move_insn (target, subtarget);
1998	else
1999	  emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2000      }
2001
2002    DONE;
2003  }"
2004)
2005
2006; constants for op 2 will never be given to these patterns.
2007(define_insn_and_split "*anddi_notdi_di"
2008  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2009	(and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2010		(match_operand:DI 2 "s_register_operand" "0,r")))]
2011  "TARGET_ARM"
2012  "#"
2013  "TARGET_ARM && reload_completed"
2014  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2015   (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2016  "
2017  {
2018    operands[3] = gen_highpart (SImode, operands[0]);
2019    operands[0] = gen_lowpart (SImode, operands[0]);
2020    operands[4] = gen_highpart (SImode, operands[1]);
2021    operands[1] = gen_lowpart (SImode, operands[1]);
2022    operands[5] = gen_highpart (SImode, operands[2]);
2023    operands[2] = gen_lowpart (SImode, operands[2]);
2024  }"
2025  [(set_attr "length" "8")
2026   (set_attr "predicable" "yes")]
2027)
2028  
2029(define_insn_and_split "*anddi_notzesidi_di"
2030  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2031	(and:DI (not:DI (zero_extend:DI
2032			 (match_operand:SI 2 "s_register_operand" "r,r")))
2033		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2034  "TARGET_ARM"
2035  "@
2036   bic%?\\t%Q0, %Q1, %2
2037   #"
2038  ; (not (zero_extend ...)) allows us to just copy the high word from
2039  ; operand1 to operand0.
2040  "TARGET_ARM
2041   && reload_completed
2042   && operands[0] != operands[1]"
2043  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2044   (set (match_dup 3) (match_dup 4))]
2045  "
2046  {
2047    operands[3] = gen_highpart (SImode, operands[0]);
2048    operands[0] = gen_lowpart (SImode, operands[0]);
2049    operands[4] = gen_highpart (SImode, operands[1]);
2050    operands[1] = gen_lowpart (SImode, operands[1]);
2051  }"
2052  [(set_attr "length" "4,8")
2053   (set_attr "predicable" "yes")]
2054)
2055  
2056(define_insn_and_split "*anddi_notsesidi_di"
2057  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2058	(and:DI (not:DI (sign_extend:DI
2059			 (match_operand:SI 2 "s_register_operand" "r,r")))
2060		(match_operand:DI 1 "s_register_operand" "0,r")))]
2061  "TARGET_ARM"
2062  "#"
2063  "TARGET_ARM && reload_completed"
2064  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2065   (set (match_dup 3) (and:SI (not:SI
2066				(ashiftrt:SI (match_dup 2) (const_int 31)))
2067			       (match_dup 4)))]
2068  "
2069  {
2070    operands[3] = gen_highpart (SImode, operands[0]);
2071    operands[0] = gen_lowpart (SImode, operands[0]);
2072    operands[4] = gen_highpart (SImode, operands[1]);
2073    operands[1] = gen_lowpart (SImode, operands[1]);
2074  }"
2075  [(set_attr "length" "8")
2076   (set_attr "predicable" "yes")]
2077)
2078  
2079(define_insn "andsi_notsi_si"
2080  [(set (match_operand:SI 0 "s_register_operand" "=r")
2081	(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2082		(match_operand:SI 1 "s_register_operand" "r")))]
2083  "TARGET_ARM"
2084  "bic%?\\t%0, %1, %2"
2085  [(set_attr "predicable" "yes")]
2086)
2087
2088(define_insn "bicsi3"
2089  [(set (match_operand:SI                 0 "register_operand" "=l")
2090	(and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2091		(match_operand:SI         2 "register_operand" "0")))]
2092  "TARGET_THUMB"
2093  "bic\\t%0, %0, %1"
2094  [(set_attr "length" "2")]
2095)
2096
2097(define_insn "andsi_not_shiftsi_si"
2098  [(set (match_operand:SI                   0 "s_register_operand" "=r")
2099	(and:SI (not:SI (match_operator:SI  4 "shift_operator"
2100			 [(match_operand:SI 2 "s_register_operand"  "r")
2101			  (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2102		(match_operand:SI           1 "s_register_operand"  "r")))]
2103  "TARGET_ARM"
2104  "bic%?\\t%0, %1, %2%S4"
2105  [(set_attr "predicable" "yes")
2106   (set_attr "shift" "2")
2107   ]
2108)
2109
2110(define_insn "*andsi_notsi_si_compare0"
2111  [(set (reg:CC_NOOV CC_REGNUM)
2112	(compare:CC_NOOV
2113	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114		 (match_operand:SI 1 "s_register_operand" "r"))
2115	 (const_int 0)))
2116   (set (match_operand:SI 0 "s_register_operand" "=r")
2117	(and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2118  "TARGET_ARM"
2119  "bic%?s\\t%0, %1, %2"
2120  [(set_attr "conds" "set")]
2121)
2122
2123(define_insn "*andsi_notsi_si_compare0_scratch"
2124  [(set (reg:CC_NOOV CC_REGNUM)
2125	(compare:CC_NOOV
2126	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2127		 (match_operand:SI 1 "s_register_operand" "r"))
2128	 (const_int 0)))
2129   (clobber (match_scratch:SI 0 "=r"))]
2130  "TARGET_ARM"
2131  "bic%?s\\t%0, %1, %2"
2132  [(set_attr "conds" "set")]
2133)
2134
2135(define_insn "iordi3"
2136  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2137	(ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2138		(match_operand:DI 2 "s_register_operand"   "r,r")))]
2139  "TARGET_ARM"
2140  "#"
2141  [(set_attr "length" "8")
2142   (set_attr "predicable" "yes")]
2143)
2144
2145(define_insn "*iordi_zesidi_di"
2146  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147	(ior:DI (zero_extend:DI
2148		 (match_operand:SI 2 "s_register_operand" "r,r"))
2149		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2150  "TARGET_ARM"
2151  "@
2152   orr%?\\t%Q0, %Q1, %2
2153   #"
2154  [(set_attr "length" "4,8")
2155   (set_attr "predicable" "yes")]
2156)
2157
2158(define_insn "*iordi_sesidi_di"
2159  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160	(ior:DI (sign_extend:DI
2161		 (match_operand:SI 2 "s_register_operand" "r,r"))
2162		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2163  "TARGET_ARM"
2164  "#"
2165  [(set_attr "length" "8")
2166   (set_attr "predicable" "yes")]
2167)
2168
2169(define_expand "iorsi3"
2170  [(set (match_operand:SI         0 "s_register_operand" "")
2171	(ior:SI (match_operand:SI 1 "s_register_operand" "")
2172		(match_operand:SI 2 "reg_or_int_operand" "")))]
2173  "TARGET_EITHER"
2174  "
2175  if (GET_CODE (operands[2]) == CONST_INT)
2176    {
2177      if (TARGET_ARM)
2178        {
2179          arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2180		 	      operands[1],
2181			      (no_new_pseudos
2182			      ? 0 : preserve_subexpressions_p ()));
2183          DONE;
2184	}
2185      else /* TARGET_THUMB */
2186	operands [2] = force_reg (SImode, operands [2]);
2187    }
2188  "
2189)
2190
2191(define_insn_and_split "*arm_iorsi3"
2192  [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2193	(ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2194		(match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2195  "TARGET_ARM"
2196  "@
2197   orr%?\\t%0, %1, %2
2198   #"
2199  "TARGET_ARM
2200   && GET_CODE (operands[2]) == CONST_INT
2201   && !const_ok_for_arm (INTVAL (operands[2]))"
2202  [(clobber (const_int 0))]
2203  "
2204  arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2205		      operands[1], 0);
2206  DONE;
2207  "
2208  [(set_attr "length" "4,16")
2209   (set_attr "predicable" "yes")]
2210)
2211
2212(define_insn "*thumb_iorsi3"
2213  [(set (match_operand:SI         0 "register_operand" "=l")
2214	(ior:SI (match_operand:SI 1 "register_operand" "%0")
2215		(match_operand:SI 2 "register_operand" "l")))]
2216  "TARGET_THUMB"
2217  "orr\\t%0, %0, %2"
2218  [(set_attr "length" "2")]
2219)
2220
2221(define_peephole2
2222  [(match_scratch:SI 3 "r")
2223   (set (match_operand:SI         0 "s_register_operand" "")
2224	(ior:SI (match_operand:SI 1 "s_register_operand" "")
2225		(match_operand:SI 2 "const_int_operand" "")))]
2226  "TARGET_ARM
2227   && !const_ok_for_arm (INTVAL (operands[2]))
2228   && const_ok_for_arm (~INTVAL (operands[2]))"
2229  [(set (match_dup 3) (match_dup 2))
2230   (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2231  ""
2232)
2233
2234(define_insn "*iorsi3_compare0"
2235  [(set (reg:CC_NOOV CC_REGNUM)
2236	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2237				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2238			 (const_int 0)))
2239   (set (match_operand:SI 0 "s_register_operand" "=r")
2240	(ior:SI (match_dup 1) (match_dup 2)))]
2241  "TARGET_ARM"
2242  "orr%?s\\t%0, %1, %2"
2243  [(set_attr "conds" "set")]
2244)
2245
2246(define_insn "*iorsi3_compare0_scratch"
2247  [(set (reg:CC_NOOV CC_REGNUM)
2248	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2249				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2250			 (const_int 0)))
2251   (clobber (match_scratch:SI 0 "=r"))]
2252  "TARGET_ARM"
2253  "orr%?s\\t%0, %1, %2"
2254  [(set_attr "conds" "set")]
2255)
2256
2257(define_insn "xordi3"
2258  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2259	(xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2260		(match_operand:DI 2 "s_register_operand"   "r,r")))]
2261  "TARGET_ARM"
2262  "#"
2263  [(set_attr "length" "8")
2264   (set_attr "predicable" "yes")]
2265)
2266
2267(define_insn "*xordi_zesidi_di"
2268  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2269	(xor:DI (zero_extend:DI
2270		 (match_operand:SI 2 "s_register_operand" "r,r"))
2271		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2272  "TARGET_ARM"
2273  "@
2274   eor%?\\t%Q0, %Q1, %2
2275   #"
2276  [(set_attr "length" "4,8")
2277   (set_attr "predicable" "yes")]
2278)
2279
2280(define_insn "*xordi_sesidi_di"
2281  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2282	(xor:DI (sign_extend:DI
2283		 (match_operand:SI 2 "s_register_operand" "r,r"))
2284		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2285  "TARGET_ARM"
2286  "#"
2287  [(set_attr "length" "8")
2288   (set_attr "predicable" "yes")]
2289)
2290
2291(define_expand "xorsi3"
2292  [(set (match_operand:SI         0 "s_register_operand" "")
2293	(xor:SI (match_operand:SI 1 "s_register_operand" "")
2294		(match_operand:SI 2 "arm_rhs_operand"  "")))]
2295  "TARGET_EITHER"
2296  "if (TARGET_THUMB)
2297     if (GET_CODE (operands[2]) == CONST_INT)
2298       operands[2] = force_reg (SImode, operands[2]);
2299  "
2300)
2301
2302(define_insn "*arm_xorsi3"
2303  [(set (match_operand:SI         0 "s_register_operand" "=r")
2304	(xor:SI (match_operand:SI 1 "s_register_operand" "r")
2305		(match_operand:SI 2 "arm_rhs_operand" "rI")))]
2306  "TARGET_ARM"
2307  "eor%?\\t%0, %1, %2"
2308  [(set_attr "predicable" "yes")]
2309)
2310
2311(define_insn "*thumb_xorsi3"
2312  [(set (match_operand:SI         0 "register_operand" "=l")
2313	(xor:SI (match_operand:SI 1 "register_operand" "%0")
2314		(match_operand:SI 2 "register_operand" "l")))]
2315  "TARGET_THUMB"
2316  "eor\\t%0, %0, %2"
2317  [(set_attr "length" "2")]
2318)
2319
2320(define_insn "*xorsi3_compare0"
2321  [(set (reg:CC_NOOV CC_REGNUM)
2322	(compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2323				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2324			 (const_int 0)))
2325   (set (match_operand:SI 0 "s_register_operand" "=r")
2326	(xor:SI (match_dup 1) (match_dup 2)))]
2327  "TARGET_ARM"
2328  "eor%?s\\t%0, %1, %2"
2329  [(set_attr "conds" "set")]
2330)
2331
2332(define_insn "*xorsi3_compare0_scratch"
2333  [(set (reg:CC_NOOV CC_REGNUM)
2334	(compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2335				 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2336			 (const_int 0)))]
2337  "TARGET_ARM"
2338  "teq%?\\t%0, %1"
2339  [(set_attr "conds" "set")]
2340)
2341
2342; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2343; (NOT D) we can sometimes merge the final NOT into one of the following
2344; insns.
2345
2346(define_split
2347  [(set (match_operand:SI 0 "s_register_operand" "")
2348	(ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2349			(not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2350		(match_operand:SI 3 "arm_rhs_operand" "")))
2351   (clobber (match_operand:SI 4 "s_register_operand" ""))]
2352  "TARGET_ARM"
2353  [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2354			      (not:SI (match_dup 3))))
2355   (set (match_dup 0) (not:SI (match_dup 4)))]
2356  ""
2357)
2358
2359(define_insn "*andsi_iorsi3_notsi"
2360  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2361	(and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2362			(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2363		(not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2364  "TARGET_ARM"
2365  "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2366  [(set_attr "length" "8")
2367   (set_attr "predicable" "yes")]
2368)
2369
2370
2371
2372;; Minimum and maximum insns
2373
2374(define_insn "smaxsi3"
2375  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2376	(smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2377		 (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2378   (clobber (reg:CC CC_REGNUM))]
2379  "TARGET_ARM"
2380  "@
2381   cmp\\t%1, %2\;movlt\\t%0, %2
2382   cmp\\t%1, %2\;movge\\t%0, %1
2383   cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2384  [(set_attr "conds" "clob")
2385   (set_attr "length" "8,8,12")]
2386)
2387
2388(define_insn "sminsi3"
2389  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2390	(smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2391		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2392   (clobber (reg:CC CC_REGNUM))]
2393  "TARGET_ARM"
2394  "@
2395   cmp\\t%1, %2\;movge\\t%0, %2
2396   cmp\\t%1, %2\;movlt\\t%0, %1
2397   cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2398  [(set_attr "conds" "clob")
2399   (set_attr "length" "8,8,12")]
2400)
2401
2402(define_insn "umaxsi3"
2403  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2404	(umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2405		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2406   (clobber (reg:CC CC_REGNUM))]
2407  "TARGET_ARM"
2408  "@
2409   cmp\\t%1, %2\;movcc\\t%0, %2
2410   cmp\\t%1, %2\;movcs\\t%0, %1
2411   cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2412  [(set_attr "conds" "clob")
2413   (set_attr "length" "8,8,12")]
2414)
2415
2416(define_insn "uminsi3"
2417  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2418	(umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2419		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2420   (clobber (reg:CC CC_REGNUM))]
2421  "TARGET_ARM"
2422  "@
2423   cmp\\t%1, %2\;movcs\\t%0, %2
2424   cmp\\t%1, %2\;movcc\\t%0, %1
2425   cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2426  [(set_attr "conds" "clob")
2427   (set_attr "length" "8,8,12")]
2428)
2429
2430(define_insn "*store_minmaxsi"
2431  [(set (match_operand:SI 0 "memory_operand" "=m")
2432	(match_operator:SI 3 "minmax_operator"
2433	 [(match_operand:SI 1 "s_register_operand" "r")
2434	  (match_operand:SI 2 "s_register_operand" "r")]))
2435   (clobber (reg:CC CC_REGNUM))]
2436  "TARGET_ARM"
2437  "*
2438  operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2439			 operands[2]);
2440  output_asm_insn (\"cmp\\t%1, %2\", operands);
2441  output_asm_insn (\"str%d3\\t%1, %0\", operands);
2442  output_asm_insn (\"str%D3\\t%2, %0\", operands);
2443  return \"\";
2444  "
2445  [(set_attr "conds" "clob")
2446   (set_attr "length" "12")
2447   (set_attr "type" "store1")]
2448)
2449
2450; Reject the frame pointer in operand[1], since reloading this after
2451; it has been eliminated can cause carnage.
2452(define_insn "*minmax_arithsi"
2453  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2454	(match_operator:SI 4 "shiftable_operator"
2455	 [(match_operator:SI 5 "minmax_operator"
2456	   [(match_operand:SI 2 "s_register_operand" "r,r")
2457	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2458	  (match_operand:SI 1 "s_register_operand" "0,?r")]))
2459   (clobber (reg:CC CC_REGNUM))]
2460  "TARGET_ARM
2461   && (GET_CODE (operands[1]) != REG
2462       || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2463           && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2464  "*
2465  {
2466    enum rtx_code code = GET_CODE (operands[4]);
2467
2468    operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2469			   operands[3]);
2470    output_asm_insn (\"cmp\\t%2, %3\", operands);
2471    output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2472    if (which_alternative != 0 || operands[3] != const0_rtx
2473        || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2474      output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2475    return \"\";
2476  }"
2477  [(set_attr "conds" "clob")
2478   (set_attr "length" "12")]
2479)
2480
2481
2482;; Shift and rotation insns
2483
2484(define_expand "ashlsi3"
2485  [(set (match_operand:SI            0 "s_register_operand" "")
2486	(ashift:SI (match_operand:SI 1 "s_register_operand" "")
2487		   (match_operand:SI 2 "arm_rhs_operand" "")))]
2488  "TARGET_EITHER"
2489  "
2490  if (GET_CODE (operands[2]) == CONST_INT
2491      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2492    {
2493      emit_insn (gen_movsi (operands[0], const0_rtx));
2494      DONE;
2495    }
2496  "
2497)
2498
2499(define_insn "*thumb_ashlsi3"
2500  [(set (match_operand:SI            0 "register_operand" "=l,l")
2501	(ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2502		   (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2503  "TARGET_THUMB"
2504  "lsl\\t%0, %1, %2"
2505  [(set_attr "length" "2")]
2506)
2507
2508(define_expand "ashrsi3"
2509  [(set (match_operand:SI              0 "s_register_operand" "")
2510	(ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2511		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2512  "TARGET_EITHER"
2513  "
2514  if (GET_CODE (operands[2]) == CONST_INT
2515      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2516    operands[2] = GEN_INT (31);
2517  "
2518)
2519
2520(define_insn "*thumb_ashrsi3"
2521  [(set (match_operand:SI              0 "register_operand" "=l,l")
2522	(ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2523		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2524  "TARGET_THUMB"
2525  "asr\\t%0, %1, %2"
2526  [(set_attr "length" "2")]
2527)
2528
2529(define_expand "lshrsi3"
2530  [(set (match_operand:SI              0 "s_register_operand" "")
2531	(lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2532		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2533  "TARGET_EITHER"
2534  "
2535  if (GET_CODE (operands[2]) == CONST_INT
2536      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2537    {
2538      emit_insn (gen_movsi (operands[0], const0_rtx));
2539      DONE;
2540    }
2541  "
2542)
2543
2544(define_insn "*thumb_lshrsi3"
2545  [(set (match_operand:SI              0 "register_operand" "=l,l")
2546	(lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2547		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2548  "TARGET_THUMB"
2549  "lsr\\t%0, %1, %2"
2550  [(set_attr "length" "2")]
2551)
2552
2553(define_expand "rotlsi3"
2554  [(set (match_operand:SI              0 "s_register_operand" "")
2555	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2556		     (match_operand:SI 2 "reg_or_int_operand" "")))]
2557  "TARGET_ARM"
2558  "
2559  if (GET_CODE (operands[2]) == CONST_INT)
2560    operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2561  else
2562    {
2563      rtx reg = gen_reg_rtx (SImode);
2564      emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2565      operands[2] = reg;
2566    }
2567  "
2568)
2569
2570(define_expand "rotrsi3"
2571  [(set (match_operand:SI              0 "s_register_operand" "")
2572	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2573		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2574  "TARGET_EITHER"
2575  "
2576  if (TARGET_ARM)
2577    {
2578      if (GET_CODE (operands[2]) == CONST_INT
2579          && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2580        operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2581    }
2582  else /* TARGET_THUMB */
2583    {
2584      if (GET_CODE (operands [2]) == CONST_INT)
2585        operands [2] = force_reg (SImode, operands[2]);
2586    }
2587  "
2588)
2589
2590(define_insn "*thumb_rotrsi3"
2591  [(set (match_operand:SI              0 "register_operand" "=l")
2592	(rotatert:SI (match_operand:SI 1 "register_operand" "0")
2593		     (match_operand:SI 2 "register_operand" "l")))]
2594  "TARGET_THUMB"
2595  "ror\\t%0, %0, %2"
2596  [(set_attr "length" "2")]
2597)
2598
2599(define_insn "*arm_shiftsi3"
2600  [(set (match_operand:SI   0 "s_register_operand" "=r")
2601	(match_operator:SI  3 "shift_operator"
2602	 [(match_operand:SI 1 "s_register_operand"  "r")
2603	  (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2604  "TARGET_ARM"
2605  "mov%?\\t%0, %1%S3"
2606  [(set_attr "predicable" "yes")
2607   (set_attr "shift" "1")
2608   ]
2609)
2610
2611(define_insn "*shiftsi3_compare0"
2612  [(set (reg:CC_NOOV CC_REGNUM)
2613	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2614			  [(match_operand:SI 1 "s_register_operand" "r")
2615			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
2616			 (const_int 0)))
2617   (set (match_operand:SI 0 "s_register_operand" "=r")
2618	(match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2619  "TARGET_ARM"
2620  "mov%?s\\t%0, %1%S3"
2621  [(set_attr "conds" "set")
2622   (set_attr "shift" "1")
2623   ]
2624)
2625
2626(define_insn "*shiftsi3_compare0_scratch"
2627  [(set (reg:CC_NOOV CC_REGNUM)
2628	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2629			  [(match_operand:SI 1 "s_register_operand" "r")
2630			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
2631			 (const_int 0)))
2632   (clobber (match_scratch:SI 0 "=r"))]
2633  "TARGET_ARM"
2634  "mov%?s\\t%0, %1%S3"
2635  [(set_attr "conds" "set")
2636   (set_attr "shift" "1")
2637   ]
2638)
2639
2640(define_insn "*notsi_shiftsi"
2641  [(set (match_operand:SI 0 "s_register_operand" "=r")
2642	(not:SI (match_operator:SI 3 "shift_operator"
2643		 [(match_operand:SI 1 "s_register_operand" "r")
2644		  (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2645  "TARGET_ARM"
2646  "mvn%?\\t%0, %1%S3"
2647  [(set_attr "predicable" "yes")
2648   (set_attr "shift" "1")
2649   ]
2650)
2651
2652(define_insn "*notsi_shiftsi_compare0"
2653  [(set (reg:CC_NOOV CC_REGNUM)
2654	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2655			  [(match_operand:SI 1 "s_register_operand" "r")
2656			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2657			 (const_int 0)))
2658   (set (match_operand:SI 0 "s_register_operand" "=r")
2659	(not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2660  "TARGET_ARM"
2661  "mvn%?s\\t%0, %1%S3"
2662  [(set_attr "conds" "set")
2663   (set_attr "shift" "1")
2664   ]
2665)
2666
2667(define_insn "*not_shiftsi_compare0_scratch"
2668  [(set (reg:CC_NOOV CC_REGNUM)
2669	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2670			  [(match_operand:SI 1 "s_register_operand" "r")
2671			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2672			 (const_int 0)))
2673   (clobber (match_scratch:SI 0 "=r"))]
2674  "TARGET_ARM"
2675  "mvn%?s\\t%0, %1%S3"
2676  [(set_attr "conds" "set")
2677   (set_attr "shift" "1")
2678  ]
2679)
2680
2681;; We don't really have extzv, but defining this using shifts helps
2682;; to reduce register pressure later on.
2683
2684(define_expand "extzv"
2685  [(set (match_dup 4)
2686	(ashift:SI (match_operand:SI   1 "register_operand" "")
2687		   (match_operand:SI   2 "const_int_operand" "")))
2688   (set (match_operand:SI              0 "register_operand" "")
2689	(lshiftrt:SI (match_dup 4)
2690		     (match_operand:SI 3 "const_int_operand" "")))]
2691  "TARGET_THUMB"
2692  "
2693  {
2694    HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2695    HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2696    
2697    operands[3] = GEN_INT (rshift);
2698    
2699    if (lshift == 0)
2700      {
2701        emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2702        DONE;
2703      }
2704      
2705    operands[2] = GEN_INT (lshift);
2706    operands[4] = gen_reg_rtx (SImode);
2707  }"
2708)
2709
2710
2711;; Unary arithmetic insns
2712
2713(define_expand "negdi2"
2714 [(parallel
2715   [(set (match_operand:DI          0 "s_register_operand" "")
2716	  (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2717    (clobber (reg:CC CC_REGNUM))])]
2718  "TARGET_EITHER"
2719  "
2720  if (TARGET_THUMB)
2721    {
2722      if (GET_CODE (operands[1]) != REG)
2723        operands[1] = force_reg (SImode, operands[1]);
2724     }
2725  "
2726)
2727
2728;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2729;; The second alternative is to allow the common case of a *full* overlap.
2730(define_insn "*arm_negdi2"
2731  [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2732	(neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2733   (clobber (reg:CC CC_REGNUM))]
2734  "TARGET_ARM"
2735  "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2736  [(set_attr "conds" "clob")
2737   (set_attr "length" "8")]
2738)
2739
2740(define_insn "*thumb_negdi2"
2741  [(set (match_operand:DI         0 "register_operand" "=&l")
2742	(neg:DI (match_operand:DI 1 "register_operand"   "l")))
2743   (clobber (reg:CC CC_REGNUM))]
2744  "TARGET_THUMB"
2745  "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2746  [(set_attr "length" "6")]
2747)
2748
2749(define_expand "negsi2"
2750  [(set (match_operand:SI         0 "s_register_operand" "")
2751	(neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2752  "TARGET_EITHER"
2753  ""
2754)
2755
2756(define_insn "*arm_negsi2"
2757  [(set (match_operand:SI         0 "s_register_operand" "=r")
2758	(neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2759  "TARGET_ARM"
2760  "rsb%?\\t%0, %1, #0"
2761  [(set_attr "predicable" "yes")]
2762)
2763
2764(define_insn "*thumb_negsi2"
2765  [(set (match_operand:SI         0 "register_operand" "=l")
2766	(neg:SI (match_operand:SI 1 "register_operand" "l")))]
2767  "TARGET_THUMB"
2768  "neg\\t%0, %1"
2769  [(set_attr "length" "2")]
2770)
2771
2772(define_insn "negsf2"
2773  [(set (match_operand:SF         0 "s_register_operand" "=f")
2774	(neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2775  "TARGET_ARM && TARGET_HARD_FLOAT"
2776  "mnf%?s\\t%0, %1"
2777  [(set_attr "type" "ffarith")
2778   (set_attr "predicable" "yes")]
2779)
2780
2781(define_insn "negdf2"
2782  [(set (match_operand:DF         0 "s_register_operand" "=f")
2783	(neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2784  "TARGET_ARM && TARGET_HARD_FLOAT"
2785  "mnf%?d\\t%0, %1"
2786  [(set_attr "type" "ffarith")
2787   (set_attr "predicable" "yes")]
2788)
2789
2790(define_insn "*negdf_esfdf"
2791  [(set (match_operand:DF 0 "s_register_operand" "=f")
2792	(neg:DF (float_extend:DF
2793		 (match_operand:SF 1 "s_register_operand" "f"))))]
2794  "TARGET_ARM && TARGET_HARD_FLOAT"
2795  "mnf%?d\\t%0, %1"
2796  [(set_attr "type" "ffarith")
2797   (set_attr "predicable" "yes")]
2798)
2799
2800(define_insn "negxf2"
2801  [(set (match_operand:XF 0 "s_register_operand" "=f")
2802	(neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2803  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2804  "mnf%?e\\t%0, %1"
2805  [(set_attr "type" "ffarith")
2806   (set_attr "predicable" "yes")]
2807)
2808
2809;; abssi2 doesn't really clobber the condition codes if a different register
2810;; is being set.  To keep things simple, assume during rtl manipulations that
2811;; it does, but tell the final scan operator the truth.  Similarly for
2812;; (neg (abs...))
2813
2814(define_insn "abssi2"
2815  [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2816	(abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2817   (clobber (reg:CC CC_REGNUM))]
2818  "TARGET_ARM"
2819  "@
2820   cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2821   eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2822  [(set_attr "conds" "clob,*")
2823   (set_attr "shift" "1")
2824   ;; predicable can't be set based on the variant, so left as no
2825   (set_attr "length" "8")]
2826)
2827
2828(define_insn "*neg_abssi2"
2829  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2830	(neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2831   (clobber (reg:CC CC_REGNUM))]
2832  "TARGET_ARM"
2833  "@
2834   cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2835   eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2836  [(set_attr "conds" "clob,*")
2837   (set_attr "shift" "1")
2838   ;; predicable can't be set based on the variant, so left as no
2839   (set_attr "length" "8")]
2840)
2841
2842(define_insn "abssf2"
2843  [(set (match_operand:SF          0 "s_register_operand" "=f")
2844	 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2845  "TARGET_ARM && TARGET_HARD_FLOAT"
2846  "abs%?s\\t%0, %1"
2847  [(set_attr "type" "ffarith")
2848   (set_attr "predicable" "yes")]
2849)
2850
2851(define_insn "absdf2"
2852  [(set (match_operand:DF         0 "s_register_operand" "=f")
2853	(abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2854  "TARGET_ARM && TARGET_HARD_FLOAT"
2855  "abs%?d\\t%0, %1"
2856  [(set_attr "type" "ffarith")
2857   (set_attr "predicable" "yes")]
2858)
2859
2860(define_insn "*absdf_esfdf"
2861  [(set (match_operand:DF 0 "s_register_operand" "=f")
2862	(abs:DF (float_extend:DF
2863		 (match_operand:SF 1 "s_register_operand" "f"))))]
2864  "TARGET_ARM && TARGET_HARD_FLOAT"
2865  "abs%?d\\t%0, %1"
2866  [(set_attr "type" "ffarith")
2867   (set_attr "predicable" "yes")]
2868)
2869
2870(define_insn "absxf2"
2871  [(set (match_operand:XF 0 "s_register_operand" "=f")
2872	(abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2873  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2874  "abs%?e\\t%0, %1"
2875  [(set_attr "type" "ffarith")
2876   (set_attr "predicable" "yes")]
2877)
2878
2879(define_insn "sqrtsf2"
2880  [(set (match_operand:SF 0 "s_register_operand" "=f")
2881	(sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2882  "TARGET_ARM && TARGET_HARD_FLOAT"
2883  "sqt%?s\\t%0, %1"
2884  [(set_attr "type" "float_em")
2885   (set_attr "predicable" "yes")]
2886)
2887
2888(define_insn "sqrtdf2"
2889  [(set (match_operand:DF 0 "s_register_operand" "=f")
2890	(sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2891  "TARGET_ARM && TARGET_HARD_FLOAT"
2892  "sqt%?d\\t%0, %1"
2893  [(set_attr "type" "float_em")
2894   (set_attr "predicable" "yes")]
2895)
2896
2897(define_insn "*sqrtdf_esfdf"
2898  [(set (match_operand:DF 0 "s_register_operand" "=f")
2899	(sqrt:DF (float_extend:DF
2900		  (match_operand:SF 1 "s_register_operand" "f"))))]
2901  "TARGET_ARM && TARGET_HARD_FLOAT"
2902  "sqt%?d\\t%0, %1"
2903  [(set_attr "type" "float_em")
2904   (set_attr "predicable" "yes")]
2905)
2906
2907(define_insn "sqrtxf2"
2908  [(set (match_operand:XF 0 "s_register_operand" "=f")
2909	(sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2910  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2911  "sqt%?e\\t%0, %1"
2912  [(set_attr "type" "float_em")
2913   (set_attr "predicable" "yes")]
2914)
2915
2916;; SIN COS TAN and family are always emulated, so it's probably better
2917;; to always call a library function.
2918;(define_insn "sinsf2"
2919;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2920;	(unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2921;		    UNSPEC_SIN))]
2922;  "TARGET_ARM && TARGET_HARD_FLOAT"
2923;  "sin%?s\\t%0, %1"
2924;[(set_attr "type" "float_em")])
2925;
2926;(define_insn "sindf2"
2927;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2928;	(unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2929;		    UNSPEC_SIN))]
2930;  "TARGET_ARM && TARGET_HARD_FLOAT"
2931;  "sin%?d\\t%0, %1"
2932;[(set_attr "type" "float_em")])
2933;
2934;(define_insn "*sindf_esfdf"
2935;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2936;	(unspec:DF [(float_extend:DF
2937;		     (match_operand:SF 1 "s_register_operand" "f"))]
2938;		    UNSPEC_SIN))]
2939;  "TARGET_ARM && TARGET_HARD_FLOAT"
2940;  "sin%?d\\t%0, %1"
2941;[(set_attr "type" "float_em")])
2942;
2943;(define_insn "sinxf2"
2944;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2945;	(unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2946;		   UNSPEC_SIN))]
2947;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2948;  "sin%?e\\t%0, %1"
2949;[(set_attr "type" "float_em")])
2950;
2951;(define_insn "cossf2"
2952;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2953;	(unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2954;		   UNSPEC_COS))]
2955;  "TARGET_ARM && TARGET_HARD_FLOAT"
2956;  "cos%?s\\t%0, %1"
2957;[(set_attr "type" "float_em")])
2958;
2959;(define_insn "cosdf2"
2960;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2961;	(unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2962;		   UNSPEC_COS))]
2963;  "TARGET_ARM && TARGET_HARD_FLOAT"
2964;  "cos%?d\\t%0, %1"
2965;[(set_attr "type" "float_em")])
2966;
2967;(define_insn "*cosdf_esfdf"
2968;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2969;	(unspec:DF [(float_extend:DF
2970;		     (match_operand:SF 1 "s_register_operand" "f"))]
2971;		   UNSPEC_COS))]
2972;  "TARGET_ARM && TARGET_HARD_FLOAT"
2973;  "cos%?d\\t%0, %1"
2974;[(set_attr "type" "float_em")])
2975;
2976;(define_insn "cosxf2"
2977;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2978;	(unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2979;		   UNSEPC_COS))]
2980;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2981;  "cos%?e\\t%0, %1"
2982;[(set_attr "type" "float_em")])
2983
2984(define_insn_and_split "one_cmpldi2"
2985  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2986	(not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2987  "TARGET_ARM"
2988  "#"
2989  "TARGET_ARM && reload_completed"
2990  [(set (match_dup 0) (not:SI (match_dup 1)))
2991   (set (match_dup 2) (not:SI (match_dup 3)))]
2992  "
2993  {
2994    operands[2] = gen_highpart (SImode, operands[0]);
2995    operands[0] = gen_lowpart (SImode, operands[0]);
2996    operands[3] = gen_highpart (SImode, operands[1]);
2997    operands[1] = gen_lowpart (SImode, operands[1]);
2998  }"
2999  [(set_attr "length" "8")
3000   (set_attr "predicable" "yes")]
3001)
3002
3003(define_expand "one_cmplsi2"
3004  [(set (match_operand:SI         0 "s_register_operand" "")
3005	(not:SI (match_operand:SI 1 "s_register_operand" "")))]
3006  "TARGET_EITHER"
3007  ""
3008)
3009
3010(define_insn "*arm_one_cmplsi2"
3011  [(set (match_operand:SI         0 "s_register_operand" "=r")
3012	(not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3013  "TARGET_ARM"
3014  "mvn%?\\t%0, %1"
3015  [(set_attr "predicable" "yes")]
3016)
3017
3018(define_insn "*thumb_one_cmplsi2"
3019  [(set (match_operand:SI         0 "register_operand" "=l")
3020	(not:SI (match_operand:SI 1 "register_operand"  "l")))]
3021  "TARGET_THUMB"
3022  "mvn\\t%0, %1"
3023  [(set_attr "length" "2")]
3024)
3025
3026(define_insn "*notsi_compare0"
3027  [(set (reg:CC_NOOV CC_REGNUM)
3028	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3029			 (const_int 0)))
3030   (set (match_operand:SI 0 "s_register_operand" "=r")
3031	(not:SI (match_dup 1)))]
3032  "TARGET_ARM"
3033  "mvn%?s\\t%0, %1"
3034  [(set_attr "conds" "set")]
3035)
3036
3037(define_insn "*notsi_compare0_scratch"
3038  [(set (reg:CC_NOOV CC_REGNUM)
3039	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3040			 (const_int 0)))
3041   (clobber (match_scratch:SI 0 "=r"))]
3042  "TARGET_ARM"
3043  "mvn%?s\\t%0, %1"
3044  [(set_attr "conds" "set")]
3045)
3046
3047;; Fixed <--> Floating conversion insns
3048
3049(define_insn "floatsisf2"
3050  [(set (match_operand:SF           0 "s_register_operand" "=f")
3051	(float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3052  "TARGET_ARM && TARGET_HARD_FLOAT"
3053  "flt%?s\\t%0, %1"
3054  [(set_attr "type" "r_2_f")
3055   (set_attr "predicable" "yes")]
3056)
3057
3058(define_insn "floatsidf2"
3059  [(set (match_operand:DF           0 "s_register_operand" "=f")
3060	(float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3061  "TARGET_ARM && TARGET_HARD_FLOAT"
3062  "flt%?d\\t%0, %1"
3063  [(set_attr "type" "r_2_f")
3064   (set_attr "predicable" "yes")]
3065)
3066
3067(define_insn "floatsixf2"
3068  [(set (match_operand:XF 0 "s_register_operand" "=f")
3069	(float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3070  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3071  "flt%?e\\t%0, %1"
3072  [(set_attr "type" "r_2_f")
3073   (set_attr "predicable" "yes")]
3074)
3075
3076(define_insn "fix_truncsfsi2"
3077  [(set (match_operand:SI         0 "s_register_operand" "=r")
3078	(fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3079  "TARGET_ARM && TARGET_HARD_FLOAT"
3080  "fix%?z\\t%0, %1"
3081  [(set_attr "type" "f_2_r")
3082   (set_attr "predicable" "yes")]
3083)
3084
3085(define_insn "fix_truncdfsi2"
3086  [(set (match_operand:SI         0 "s_register_operand" "=r")
3087	(fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3088  "TARGET_ARM && TARGET_HARD_FLOAT"
3089  "fix%?z\\t%0, %1"
3090  [(set_attr "type" "f_2_r")
3091   (set_attr "predicable" "yes")]
3092)
3093
3094(define_insn "fix_truncxfsi2"
3095  [(set (match_operand:SI 0 "s_register_operand" "=r")
3096	(fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3097  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3098  "fix%?z\\t%0, %1"
3099  [(set_attr "type" "f_2_r")
3100   (set_attr "predicable" "yes")]
3101)
3102
3103;; Truncation insns
3104
3105(define_insn "truncdfsf2"
3106  [(set (match_operand:SF 0 "s_register_operand" "=f")
3107	(float_truncate:SF
3108	 (match_operand:DF 1 "s_register_operand" "f")))]
3109  "TARGET_ARM && TARGET_HARD_FLOAT"
3110  "mvf%?s\\t%0, %1"
3111  [(set_attr "type" "ffarith")
3112   (set_attr "predicable" "yes")]
3113)
3114
3115(define_insn "truncxfsf2"
3116  [(set (match_operand:SF 0 "s_register_operand" "=f")
3117	(float_truncate:SF
3118	 (match_operand:XF 1 "s_register_operand" "f")))]
3119  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3120  "mvf%?s\\t%0, %1"
3121  [(set_attr "type" "ffarith")
3122   (set_attr "predicable" "yes")]
3123)
3124
3125(define_insn "truncxfdf2"
3126  [(set (match_operand:DF 0 "s_register_operand" "=f")
3127	(float_truncate:DF
3128	 (match_operand:XF 1 "s_register_operand" "f")))]
3129  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3130  "mvf%?d\\t%0, %1"
3131  [(set_attr "type" "ffarith")
3132   (set_attr "predicable" "yes")]
3133)
3134
3135;; Zero and sign extension instructions.
3136
3137(define_insn "zero_extendsidi2"
3138  [(set (match_operand:DI 0 "s_register_operand" "=r")
3139        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3140  "TARGET_ARM"
3141  "*
3142    if (REGNO (operands[1])
3143        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3144      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3145    return \"mov%?\\t%R0, #0\";
3146  "
3147  [(set_attr "length" "8")
3148   (set_attr "predicable" "yes")]
3149)
3150
3151(define_insn "zero_extendqidi2"
3152  [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3153	(zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3154  "TARGET_ARM"
3155  "@
3156   and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3157   ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3158  [(set_attr "length" "8")
3159   (set_attr "predicable" "yes")
3160   (set_attr "type" "*,load")
3161   (set_attr "pool_range" "*,4092")
3162   (set_attr "neg_pool_range" "*,4084")]
3163)
3164
3165(define_insn "extendsidi2"
3166  [(set (match_operand:DI 0 "s_register_operand" "=r")
3167        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3168  "TARGET_ARM"
3169  "*
3170    if (REGNO (operands[1])
3171        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3172      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3173    return \"mov%?\\t%R0, %Q0, asr #31\";
3174  "
3175  [(set_attr "length" "8")
3176   (set_attr "shift" "1")
3177   (set_attr "predicable" "yes")]
3178)
3179
3180(define_expand "zero_extendhisi2"
3181  [(set (match_dup 2)
3182	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3183		   (const_int 16)))
3184   (set (match_operand:SI 0 "s_register_operand" "")
3185	(lshiftrt:SI (match_dup 2) (const_int 16)))]
3186  "TARGET_EITHER"
3187  "
3188  {
3189    if (TARGET_ARM)
3190      {
3191        if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3192          {
3193           /* Note: We do not have to worry about TARGET_MMU_TRAPS
3194	      here because the insn below will generate an LDRH instruction
3195	      rather than an LDR instruction, so we cannot get an unaligned
3196	      word access.  */
3197            emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3198			            gen_rtx_ZERO_EXTEND (SImode,
3199							 operands[1])));
3200            DONE;
3201          }
3202        if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3203          {
3204            emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3205            DONE;
3206          }
3207        if (!s_register_operand (operands[1], HImode))
3208          operands[1] = copy_to_mode_reg (HImode, operands[1]);
3209        operands[1] = gen_lowpart (SImode, operands[1]);
3210        operands[2] = gen_reg_rtx (SImode);
3211      }
3212    else /* TARGET_THUMB */
3213      {
3214        if (GET_CODE (operands[1]) == MEM)
3215	  {
3216	    rtx tmp;
3217
3218	    tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3219	    tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3220	    emit_insn (tmp);
3221	  }
3222	else
3223	  {
3224	    rtx ops[3];
3225	    
3226	    if (!s_register_operand (operands[1], HImode))
3227	      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3228	    operands[1] = gen_lowpart (SImode, operands[1]);
3229	    operands[2] = gen_reg_rtx (SImode);
3230	    
3231	    ops[0] = operands[2];
3232	    ops[1] = operands[1];
3233	    ops[2] = GEN_INT (16);
3234	    
3235	    emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3236				    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3237
3238	    ops[0] = operands[0];
3239	    ops[1] = operands[2];
3240	    ops[2] = GEN_INT (16);
3241
3242	    emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3243				    gen_rtx_LSHIFTRT (SImode, ops[1],
3244						      ops[2])));
3245	  }
3246	DONE; 
3247      }
3248  }"
3249)
3250
3251(define_insn "*thumb_zero_extendhisi2"
3252  [(set (match_operand:SI                 0 "register_operand" "=l")
3253	(zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3254  "TARGET_THUMB"
3255  "*
3256  rtx mem = XEXP (operands[1], 0);
3257
3258  if (GET_CODE (mem) == CONST)
3259    mem = XEXP (mem, 0);
3260    
3261  if (GET_CODE (mem) == LABEL_REF)
3262    return \"ldr\\t%0, %1\";
3263    
3264  if (GET_CODE (mem) == PLUS)
3265    {
3266      rtx a = XEXP (mem, 0);
3267      rtx b = XEXP (mem, 1);
3268
3269      /* This can happen due to bugs in reload.  */
3270      if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3271        {
3272          rtx ops[2];
3273          ops[0] = operands[0];
3274          ops[1] = a;
3275      
3276          output_asm_insn (\"mov	%0, %1\", ops);
3277
3278          XEXP (mem, 0) = operands[0];
3279       }
3280
3281      else if (   GET_CODE (a) == LABEL_REF
3282	       && GET_CODE (b) == CONST_INT)
3283        return \"ldr\\t%0, %1\";
3284    }
3285    
3286  return \"ldrh\\t%0, %1\";
3287  "
3288  [(set_attr "length" "4")
3289   (set_attr "type" "load")
3290   (set_attr "pool_range" "60")]
3291)
3292
3293(define_insn "*arm_zero_extendhisi2"
3294  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3295	(zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3296  "TARGET_ARM && arm_arch4"
3297  "ldr%?h\\t%0, %1"
3298  [(set_attr "type" "load")
3299   (set_attr "predicable" "yes")
3300   (set_attr "pool_range" "256")
3301   (set_attr "neg_pool_range" "244")]
3302)
3303
3304(define_split
3305  [(set (match_operand:SI 0 "s_register_operand" "")
3306	(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3307   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3308  "TARGET_ARM && (!arm_arch4)"
3309  [(set (match_dup 2) (match_dup 1))
3310   (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3311  "
3312  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3313    FAIL;
3314  "
3315)
3316
3317(define_split
3318  [(set (match_operand:SI 0 "s_register_operand" "")
3319	(match_operator:SI 3 "shiftable_operator"
3320	 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3321	  (match_operand:SI 4 "s_register_operand" "")]))
3322   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3323  "TARGET_ARM && (!arm_arch4)"
3324  [(set (match_dup 2) (match_dup 1))
3325   (set (match_dup 0)
3326	(match_op_dup 3
3327	 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3328  "
3329  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3330    FAIL;
3331  "
3332)
3333
3334(define_expand "zero_extendqisi2"
3335  [(set (match_operand:SI 0 "s_register_operand" "")
3336	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3337  "TARGET_EITHER"
3338  "
3339  if (GET_CODE (operands[1]) != MEM)
3340    {
3341      if (TARGET_ARM)
3342        {
3343          emit_insn (gen_andsi3 (operands[0],
3344				 gen_lowpart (SImode, operands[1]),
3345			         GEN_INT (255)));
3346        }
3347      else /* TARGET_THUMB */
3348        {
3349          rtx temp = gen_reg_rtx (SImode);
3350	  rtx ops[3];
3351	  
3352          operands[1] = copy_to_mode_reg (QImode, operands[1]);
3353          operands[1] = gen_lowpart (SImode, operands[1]);
3354
3355	  ops[0] = temp;
3356	  ops[1] = operands[1];
3357	  ops[2] = GEN_INT (24);
3358
3359	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3360				  gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3361	  
3362          ops[0] = operands[0];
3363	  ops[1] = temp;
3364	  ops[2] = GEN_INT (24);
3365
3366	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3367				  gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3368	}
3369      DONE;
3370    }
3371  "
3372)
3373
3374(define_insn "*thumb_zero_extendqisi2"
3375  [(set (match_operand:SI                 0 "register_operand" "=l")
3376	(zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3377  "TARGET_THUMB"
3378  "ldrb\\t%0, %1"
3379  [(set_attr "length" "2")
3380   (set_attr "type" "load")
3381   (set_attr "pool_range" "32")]
3382)
3383
3384(define_insn "*arm_zero_extendqisi2"
3385  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3386	(zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3387  "TARGET_ARM"
3388  "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3389  [(set_attr "type" "load")
3390   (set_attr "predicable" "yes")
3391   (set_attr "pool_range" "4096")
3392   (set_attr "neg_pool_range" "4084")]
3393)
3394
3395(define_split
3396  [(set (match_operand:SI 0 "s_register_operand" "")
3397	(zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3398   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3399  "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3400  [(set (match_dup 2) (match_dup 1))
3401   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3402  ""
3403)
3404
3405(define_insn "*compareqi_eq0"
3406  [(set (reg:CC_Z CC_REGNUM)
3407	(compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3408			 (const_int 0)))]
3409  "TARGET_ARM"
3410  "tst\\t%0, #255"
3411  [(set_attr "conds" "set")]
3412)
3413
3414(define_expand "extendhisi2"
3415  [(set (match_dup 2)
3416	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3417		   (const_int 16)))
3418   (set (match_operand:SI 0 "s_register_operand" "")
3419	(ashiftrt:SI (match_dup 2)
3420		     (const_int 16)))]
3421  "TARGET_EITHER"
3422  "
3423  {
3424    if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3425      {
3426       /* Note: We do not have to worry about TARGET_MMU_TRAPS
3427	  here because the insn below will generate an LDRH instruction
3428	  rather than an LDR instruction, so we cannot get an unaligned
3429	  word access.  */
3430        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3431		   gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3432        DONE;
3433      }
3434
3435    if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3436      {
3437        emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3438        DONE;
3439      }
3440    if (!s_register_operand (operands[1], HImode))
3441      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3442    operands[1] = gen_lowpart (SImode, operands[1]);
3443    operands[2] = gen_reg_rtx (SImode);
3444
3445    if (TARGET_THUMB)
3446      {
3447	rtx ops[3];
3448	
3449	ops[0] = operands[2];
3450	ops[1] = operands[1];
3451	ops[2] = GEN_INT (16);
3452	
3453        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3454				gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3455	    
3456	ops[0] = operands[0];
3457	ops[1] = operands[2];
3458	ops[2] = GEN_INT (16);
3459	
3460        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3461				gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3462	
3463	DONE;
3464      }
3465  }"
3466)
3467
3468(define_insn "*thumb_extendhisi2_insn"
3469  [(set (match_operand:SI                 0 "register_operand" "=l")
3470	(sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3471   (clobber (match_scratch:SI             2                   "=&l"))]
3472  "TARGET_THUMB"
3473  "*
3474  {
3475    rtx ops[4];
3476    rtx mem = XEXP (operands[1], 0);
3477
3478    /* This code used to try to use 'V', and fix the address only if it was
3479       offsettable, but this fails for e.g. REG+48 because 48 is outside the
3480       range of QImode offsets, and offsettable_address_p does a QImode
3481       address check.  */
3482       
3483    if (GET_CODE (mem) == CONST)
3484      mem = XEXP (mem, 0);
3485    
3486    if (GET_CODE (mem) == LABEL_REF)
3487      return \"ldr\\t%0, %1\";
3488    
3489    if (GET_CODE (mem) == PLUS)
3490      {
3491        rtx a = XEXP (mem, 0);
3492        rtx b = XEXP (mem, 1);
3493
3494        if (GET_CODE (a) == LABEL_REF
3495	    && GET_CODE (b) == CONST_INT)
3496          return \"ldr\\t%0, %1\";
3497
3498        if (GET_CODE (b) == REG)
3499          return \"ldrsh\\t%0, %1\";
3500	  
3501        ops[1] = a;
3502        ops[2] = b;
3503      }
3504    else
3505      {
3506        ops[1] = mem;
3507        ops[2] = const0_rtx;
3508      }
3509      
3510    if (GET_CODE (ops[1]) != REG)
3511      {
3512        debug_rtx (ops[1]);
3513        abort ();
3514      }
3515
3516    ops[0] = operands[0];
3517    ops[3] = operands[2];
3518    output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3519    return \"\";
3520  }"
3521  [(set_attr "length" "4")
3522   (set_attr "type" "load")
3523   (set_attr "pool_range" "1020")]
3524)
3525
3526(define_expand "extendhisi2_mem"
3527  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3528   (set (match_dup 3)
3529	(zero_extend:SI (match_dup 7)))
3530   (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3531   (set (match_operand:SI 0 "" "")
3532	(ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3533  "TARGET_ARM"
3534  "
3535  {
3536    rtx mem1, mem2;
3537    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3538
3539    mem1 = gen_rtx_MEM (QImode, addr);
3540    MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3541    mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3542    MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3543    operands[0] = gen_lowpart (SImode, operands[0]);
3544    operands[1] = mem1;
3545    operands[2] = gen_reg_rtx (SImode);
3546    operands[3] = gen_reg_rtx (SImode);
3547    operands[6] = gen_reg_rtx (SImode);
3548    operands[7] = mem2;
3549
3550    if (BYTES_BIG_ENDIAN)
3551      {
3552	operands[4] = operands[2];
3553	operands[5] = operands[3];
3554      }
3555    else
3556      {
3557	operands[4] = operands[3];
3558	operands[5] = operands[2];
3559      }
3560  }"
3561)
3562
3563(define_insn "*arm_extendhisi_insn"
3564  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3565	(sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3566  "TARGET_ARM && arm_arch4"
3567  "ldr%?sh\\t%0, %1"
3568  [(set_attr "type" "load")
3569   (set_attr "predicable" "yes")
3570   (set_attr "pool_range" "256")
3571   (set_attr "neg_pool_range" "244")]
3572)
3573
3574(define_split
3575  [(set (match_operand:SI                 0 "s_register_operand" "")
3576	(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3577   (clobber (match_operand:SI             2 "s_register_operand" ""))]
3578  "TARGET_ARM && (!arm_arch4)"
3579  [(set (match_dup 2) (match_dup 1))
3580   (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3581  "
3582  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3583    FAIL;
3584  "
3585)
3586
3587(define_split
3588  [(set (match_operand:SI                   0 "s_register_operand" "")
3589	(match_operator:SI                  3 "shiftable_operator"
3590	 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3591	  (match_operand:SI                 4 "s_register_operand" "")]))
3592   (clobber (match_operand:SI               2 "s_register_operand" ""))]
3593  "TARGET_ARM && (!arm_arch4)"
3594  [(set (match_dup 2) (match_dup 1))
3595   (set (match_dup 0)
3596	(match_op_dup 3
3597	 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3598  "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3599     FAIL;
3600  "
3601)
3602
3603(define_expand "extendqihi2"
3604  [(set (match_dup 2)
3605	(ashift:SI (match_operand:QI 1 "general_operand" "")
3606		   (const_int 24)))
3607   (set (match_operand:HI 0 "s_register_operand" "")
3608	(ashiftrt:SI (match_dup 2)
3609		     (const_int 24)))]
3610  "TARGET_ARM"
3611  "
3612  {
3613    if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3614      {
3615	emit_insn (gen_rtx_SET (VOIDmode,
3616				operands[0],
3617				gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3618	DONE;
3619      }
3620    if (!s_register_operand (operands[1], QImode))
3621      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3622    operands[0] = gen_lowpart (SImode, operands[0]);
3623    operands[1] = gen_lowpart (SImode, operands[1]);
3624    operands[2] = gen_reg_rtx (SImode);
3625  }"
3626)
3627
3628; Rather than restricting all byte accesses to memory addresses that ldrsb
3629; can handle, we fix up the ones that ldrsb can't grok with a split.
3630(define_insn "*extendqihi_insn"
3631  [(set (match_operand:HI                 0 "s_register_operand" "=r")
3632	(sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3633  "TARGET_ARM && arm_arch4"
3634  "*
3635  /* If the address is invalid, this will split the instruction into two. */
3636  if (bad_signed_byte_operand (operands[1], VOIDmode))
3637    return \"#\";
3638  return \"ldr%?sb\\t%0, %1\";
3639  "
3640  [(set_attr "type" "load")
3641   (set_attr "predicable" "yes")
3642   (set_attr "length" "8")
3643   (set_attr "pool_range" "256")
3644   (set_attr "neg_pool_range" "244")]
3645)
3646
3647(define_split
3648  [(set (match_operand:HI 0 "s_register_operand" "")
3649	(sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3650  "TARGET_ARM && arm_arch4 && reload_completed"
3651  [(set (match_dup 3) (match_dup 1))
3652   (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3653  "
3654  {
3655    HOST_WIDE_INT offset;
3656
3657    operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3658    operands[2] = gen_rtx_MEM (QImode, operands[3]);
3659    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3660    operands[1] = XEXP (operands[1], 0);
3661    if (GET_CODE (operands[1]) == PLUS
3662	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3663	&& !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3664	     || const_ok_for_arm (-offset)))
3665      {
3666	HOST_WIDE_INT low = (offset > 0
3667			     ? (offset & 0xff) : -((-offset) & 0xff));
3668	XEXP (operands[2], 0) = plus_constant (operands[3], low);
3669	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3670      }
3671    /* Ensure the sum is in correct canonical form */
3672    else if (GET_CODE (operands[1]) == PLUS
3673	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3674	     && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3675      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3676					   XEXP (operands[1], 1),
3677					   XEXP (operands[1], 0));
3678  }"
3679)
3680
3681(define_expand "extendqisi2"
3682  [(set (match_dup 2)
3683	(ashift:SI (match_operand:QI 1 "general_operand" "")
3684		   (const_int 24)))
3685   (set (match_operand:SI 0 "s_register_operand" "")
3686	(ashiftrt:SI (match_dup 2)
3687		     (const_int 24)))]
3688  "TARGET_EITHER"
3689  "
3690  {
3691    if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3692      {
3693        emit_insn (gen_rtx_SET (VOIDmode,
3694			        operands[0],
3695			        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3696        DONE;
3697      }
3698    if (!s_register_operand (operands[1], QImode))
3699      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3700    operands[1] = gen_lowpart (SImode, operands[1]);
3701    operands[2] = gen_reg_rtx (SImode);
3702    
3703    if (TARGET_THUMB)
3704      {
3705	rtx ops[3];
3706	
3707	ops[0] = operands[2];
3708	ops[1] = operands[1];
3709	ops[2] = GEN_INT (24);
3710	
3711        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3712		   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3713
3714	ops[0] = operands[0];
3715	ops[1] = operands[2];
3716	ops[2] = GEN_INT (24);
3717	
3718        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3719		   gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3720	
3721	DONE;
3722      }
3723  }"
3724)
3725
3726; Rather than restricting all byte accesses to memory addresses that ldrsb
3727; can handle, we fix up the ones that ldrsb can't grok with a split.
3728(define_insn "*arm_extendqisi_insn"
3729  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3730	(sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3731  "TARGET_ARM && arm_arch4"
3732  "*
3733  /* If the address is invalid, this will split the instruction into two. */
3734  if (bad_signed_byte_operand (operands[1], VOIDmode))
3735    return \"#\";
3736  return \"ldr%?sb\\t%0, %1\";
3737  "
3738  [(set_attr "type" "load")
3739   (set_attr "predicable" "yes")
3740   (set_attr "length" "8")
3741   (set_attr "pool_range" "256")
3742   (set_attr "neg_pool_range" "244")]
3743)
3744
3745(define_split
3746  [(set (match_operand:SI 0 "s_register_operand" "")
3747	(sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3748  "TARGET_ARM && arm_arch4 && reload_completed"
3749  [(set (match_dup 0) (match_dup 1))
3750   (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3751  "
3752  {
3753    HOST_WIDE_INT offset;
3754
3755    operands[2] = gen_rtx_MEM (QImode, operands[0]);
3756    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3757    operands[1] = XEXP (operands[1], 0);
3758    if (GET_CODE (operands[1]) == PLUS
3759	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3760	&& !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3761	     || const_ok_for_arm (-offset)))
3762      {
3763	HOST_WIDE_INT low = (offset > 0
3764			     ? (offset & 0xff) : -((-offset) & 0xff));
3765	XEXP (operands[2], 0) = plus_constant (operands[0], low);
3766	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3767      }
3768    /* Ensure the sum is in correct canonical form */
3769    else if (GET_CODE (operands[1]) == PLUS
3770	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3771	     && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3772      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3773					   XEXP (operands[1], 1),
3774					   XEXP (operands[1], 0));
3775  }"
3776)
3777
3778(define_insn "*thumb_extendqisi2_insn"
3779  [(set (match_operand:SI                 0 "register_operand" "=l,l")
3780	(sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3781  "TARGET_THUMB"
3782  "*
3783  {
3784    rtx ops[3];
3785    rtx mem = XEXP (operands[1], 0);
3786    
3787    if (GET_CODE (mem) == CONST)
3788      mem = XEXP (mem, 0);
3789    
3790    if (GET_CODE (mem) == LABEL_REF)
3791      return \"ldr\\t%0, %1\";
3792
3793    if (GET_CODE (mem) == PLUS
3794        && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3795      return \"ldr\\t%0, %1\";
3796      
3797    if (which_alternative == 0)
3798      return \"ldrsb\\t%0, %1\";
3799      
3800    ops[0] = operands[0];
3801    
3802    if (GET_CODE (mem) == PLUS)
3803      {
3804        rtx a = XEXP (mem, 0);
3805	rtx b = XEXP (mem, 1);
3806	
3807        ops[1] = a;
3808        ops[2] = b;
3809
3810        if (GET_CODE (a) == REG)
3811	  {
3812	    if (GET_CODE (b) == REG)
3813              output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3814            else if (REGNO (a) == REGNO (ops[0]))
3815	      {
3816                output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3817		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3818		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3819	      }
3820	    else
3821              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3822	  }
3823        else if (GET_CODE (b) != REG)
3824	  abort ();
3825	else
3826          {
3827            if (REGNO (b) == REGNO (ops[0]))
3828	      {
3829                output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3830		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3831		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3832	      }
3833	    else
3834              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3835          }
3836      }
3837    else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3838      {
3839        output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3840	output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3841	output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3842      }
3843    else
3844      {
3845        ops[1] = mem;
3846        ops[2] = const0_rtx;
3847	
3848        output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3849      }
3850    return \"\";
3851  }"
3852  [(set_attr "length" "2,6")
3853   (set_attr "type" "load,load")
3854   (set_attr "pool_range" "32,32")]
3855)
3856
3857(define_insn "extendsfdf2"
3858  [(set (match_operand:DF                  0 "s_register_operand" "=f")
3859	(float_extend:DF (match_operand:SF 1 "s_register_operand"  "f")))]
3860  "TARGET_ARM && TARGET_HARD_FLOAT"
3861  "mvf%?d\\t%0, %1"
3862  [(set_attr "type" "ffarith")
3863   (set_attr "predicable" "yes")]
3864)
3865
3866(define_insn "extendsfxf2"
3867  [(set (match_operand:XF 0 "s_register_operand" "=f")
3868	(float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3869  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3870  "mvf%?e\\t%0, %1"
3871  [(set_attr "type" "ffarith")
3872   (set_attr "predicable" "yes")]
3873)
3874
3875(define_insn "extenddfxf2"
3876  [(set (match_operand:XF 0 "s_register_operand" "=f")
3877	(float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3878  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3879  "mvf%?e\\t%0, %1"
3880  [(set_attr "type" "ffarith")
3881   (set_attr "predicable" "yes")]
3882)
3883
3884
3885;; Move insns (including loads and stores)
3886
3887;; XXX Just some ideas about movti.
3888;; I don't think these are a good idea on the arm, there just aren't enough
3889;; registers
3890;;(define_expand "loadti"
3891;;  [(set (match_operand:TI 0 "s_register_operand" "")
3892;;	(mem:TI (match_operand:SI 1 "address_operand" "")))]
3893;;  "" "")
3894
3895;;(define_expand "storeti"
3896;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3897;;	(match_operand:TI 1 "s_register_operand" ""))]
3898;;  "" "")
3899
3900;;(define_expand "movti"
3901;;  [(set (match_operand:TI 0 "general_operand" "")
3902;;	(match_operand:TI 1 "general_operand" ""))]
3903;;  ""
3904;;  "
3905;;{
3906;;  rtx insn;
3907;;
3908;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3909;;    operands[1] = copy_to_reg (operands[1]);
3910;;  if (GET_CODE (operands[0]) == MEM)
3911;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3912;;  else if (GET_CODE (operands[1]) == MEM)
3913;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3914;;  else
3915;;    FAIL;
3916;;
3917;;  emit_insn (insn);
3918;;  DONE;
3919;;}")
3920
3921;; Recognize garbage generated above.
3922
3923;;(define_insn ""
3924;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3925;;	(match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3926;;  ""
3927;;  "*
3928;;  {
3929;;    register mem = (which_alternative < 3);
3930;;    register const char *template;
3931;;
3932;;    operands[mem] = XEXP (operands[mem], 0);
3933;;    switch (which_alternative)
3934;;      {
3935;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3936;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3937;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3938;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3939;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3940;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3941;;      }
3942;;    output_asm_insn (template, operands);
3943;;    return \"\";
3944;;  }")
3945
3946(define_expand "movdi"
3947  [(set (match_operand:DI 0 "general_operand" "")
3948	(match_operand:DI 1 "general_operand" ""))]
3949  "TARGET_EITHER"
3950  "
3951  if (TARGET_THUMB)
3952    {
3953      if (!no_new_pseudos)
3954        {
3955          if (GET_CODE (operands[0]) != REG)
3956	    operands[1] = force_reg (DImode, operands[1]);
3957        }
3958    }
3959  "
3960)
3961
3962(define_insn "*arm_movdi"
3963  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3964	(match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3965  "TARGET_ARM"
3966  "*
3967  return (output_move_double (operands));
3968  "
3969  [(set_attr "length" "8")
3970   (set_attr "type" "*,load,store2")
3971   (set_attr "pool_range" "*,1020,*")
3972   (set_attr "neg_pool_range" "*,1008,*")]
3973)
3974
3975;;; ??? This should have alternatives for constants.
3976;;; ??? This was originally identical to the movdf_insn pattern.
3977;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3978;;; thumb_reorg with a memory reference.
3979(define_insn "*thumb_movdi_insn"
3980  [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3981	(match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3982  "TARGET_THUMB
3983   && (   register_operand (operands[0], DImode)
3984       || register_operand (operands[1], DImode))"
3985  "*
3986  {
3987  switch (which_alternative)
3988    {
3989    default:
3990    case 0:
3991      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3992	return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3993      return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3994    case 1:
3995      return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3996    case 2:
3997      operands[1] = GEN_INT (- INTVAL (operands[1]));
3998      return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3999    case 3:
4000      return \"ldmia\\t%1, {%0, %H0}\";
4001    case 4:
4002      return \"stmia\\t%0, {%1, %H1}\";
4003    case 5:
4004      return thumb_load_double_from_address (operands);
4005    case 6:
4006      operands[2] = gen_rtx (MEM, SImode,
4007			     plus_constant (XEXP (operands[0], 0), 4));
4008      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4009      return \"\";
4010    case 7:
4011      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4012	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4013      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4014    }
4015  }"
4016  [(set_attr "length" "4,4,6,2,2,6,4,4")
4017   (set_attr "type" "*,*,*,load,store2,load,store2,*")
4018   (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4019)
4020
4021(define_expand "movsi"
4022  [(set (match_operand:SI 0 "general_operand" "")
4023        (match_operand:SI 1 "general_operand" ""))]
4024  "TARGET_EITHER"
4025  "
4026  if (TARGET_ARM)
4027    {
4028      /* Everything except mem = const or mem = mem can be done easily */
4029      if (GET_CODE (operands[0]) == MEM)
4030        operands[1] = force_reg (SImode, operands[1]);
4031      if (GET_CODE (operands[1]) == CONST_INT
4032          && !(const_ok_for_arm (INTVAL (operands[1]))
4033               || const_ok_for_arm (~INTVAL (operands[1]))))
4034        {
4035           arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4036		    	      NULL_RTX,
4037			      (no_new_pseudos ? 0
4038			       : preserve_subexpressions_p ()));
4039          DONE;
4040        }
4041    }
4042  else /* TARGET_THUMB.... */
4043    {
4044      if (!no_new_pseudos)
4045        {
4046          if (GET_CODE (operands[0]) != REG)
4047	    operands[1] = force_reg (SImode, operands[1]);
4048        }
4049    }
4050    
4051  if (flag_pic
4052      && (CONSTANT_P (operands[1])
4053	 || symbol_mentioned_p (operands[1])
4054	 || label_mentioned_p (operands[1])))
4055    operands[1] = legitimize_pic_address (operands[1], SImode,
4056					  (no_new_pseudos ? operands[0] : 0));
4057  "
4058)
4059
4060(define_insn "*arm_movsi_insn"
4061  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4062	(match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4063  "TARGET_ARM
4064   && (   register_operand (operands[0], SImode)
4065       || register_operand (operands[1], SImode))"
4066  "@
4067   mov%?\\t%0, %1
4068   mvn%?\\t%0, #%B1
4069   ldr%?\\t%0, %1
4070   str%?\\t%1, %0"
4071  [(set_attr "type" "*,*,load,store1")
4072   (set_attr "predicable" "yes")
4073   (set_attr "pool_range" "*,*,4096,*")
4074   (set_attr "neg_pool_range" "*,*,4084,*")]
4075)
4076
4077(define_split
4078  [(set (match_operand:SI 0 "s_register_operand" "")
4079	(match_operand:SI 1 "const_int_operand" ""))]
4080  "TARGET_ARM
4081  && (!(const_ok_for_arm (INTVAL (operands[1]))
4082        || const_ok_for_arm (~INTVAL (operands[1]))))"
4083  [(clobber (const_int 0))]
4084  "
4085  arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4086		      NULL_RTX, 0);
4087  DONE;
4088  "
4089)
4090
4091(define_insn "*thumb_movsi_insn"
4092  [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4093	(match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4094  "TARGET_THUMB
4095   && (   register_operand (operands[0], SImode) 
4096       || register_operand (operands[1], SImode))"
4097  "@
4098   mov	%0, %1
4099   mov	%0, %1
4100   #
4101   #
4102   ldmia\\t%1, {%0}
4103   stmia\\t%0, {%1}
4104   ldr\\t%0, %1
4105   str\\t%1, %0
4106   mov\\t%0, %1"
4107  [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4108   (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4109   (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4110)
4111
4112(define_split 
4113  [(set (match_operand:SI 0 "register_operand" "")
4114	(match_operand:SI 1 "const_int_operand" ""))]
4115  "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4116  [(set (match_dup 0) (match_dup 1))
4117   (set (match_dup 0) (neg:SI (match_dup 0)))]
4118  "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4119)
4120
4121(define_split 
4122  [(set (match_operand:SI 0 "register_operand" "")
4123	(match_operand:SI 1 "const_int_operand" ""))]
4124  "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4125  [(set (match_dup 0) (match_dup 1))
4126   (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4127  "
4128  {
4129    unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4130    unsigned HOST_WIDE_INT mask = 0xff;
4131    int i;
4132    
4133    for (i = 0; i < 25; i++)
4134      if ((val & (mask << i)) == val)
4135        break;
4136
4137    /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4138    if (i == 0)
4139      FAIL;
4140
4141    operands[1] = GEN_INT (val >> i);
4142    operands[2] = GEN_INT (i);
4143  }"
4144)
4145
4146;; When generating pic, we need to load the symbol offset into a register.
4147;; So that the optimizer does not confuse this with a normal symbol load
4148;; we use an unspec.  The offset will be loaded from a constant pool entry,
4149;; since that is the only type of relocation we can use.
4150
4151;; The rather odd constraints on the following are to force reload to leave
4152;; the insn alone, and to force the minipool generation pass to then move
4153;; the GOT symbol to memory.
4154
4155(define_insn "pic_load_addr_arm"
4156  [(set (match_operand:SI 0 "s_register_operand" "=r")
4157	(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4158  "TARGET_ARM && flag_pic"
4159  "ldr%?\\t%0, %1"
4160  [(set_attr "type" "load")
4161   (set (attr "pool_range")     (const_int 4096))
4162   (set (attr "neg_pool_range") (const_int 4084))]
4163)
4164
4165(define_insn "pic_load_addr_thumb"
4166  [(set (match_operand:SI 0 "s_register_operand" "=l")
4167	(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4168  "TARGET_THUMB && flag_pic"
4169  "ldr\\t%0, %1"
4170  [(set_attr "type" "load")
4171   (set (attr "pool_range") (const_int 1024))]
4172)
4173
4174;; This variant is used for AOF assembly, since it needs to mention the
4175;; pic register in the rtl.
4176(define_expand "pic_load_addr_based"
4177  [(set (match_operand:SI 0 "s_register_operand" "=r")
4178	(unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4179  "TARGET_ARM && flag_pic"
4180  "operands[2] = pic_offset_table_rtx;"
4181)
4182
4183(define_insn "*pic_load_addr_based_insn"
4184  [(set (match_operand:SI 0 "s_register_operand" "=r")
4185	(unspec:SI [(match_operand 1 "" "")
4186		    (match_operand 2 "s_register_operand" "r")]
4187		   UNSPEC_PIC_SYM))]
4188  "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4189  "*
4190#ifdef AOF_ASSEMBLER
4191  operands[1] = aof_pic_entry (operands[1]);
4192#endif
4193  output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4194  return \"\";
4195  "
4196  [(set_attr "type" "load")
4197   (set (attr "pool_range")
4198	(if_then_else (eq_attr "is_thumb" "yes")
4199		      (const_int 1024)
4200		      (const_int 4096)))
4201   (set (attr "neg_pool_range")
4202	(if_then_else (eq_attr "is_thumb" "yes")
4203		      (const_int 0)
4204		      (const_int 4084)))]
4205)
4206
4207(define_insn "pic_add_dot_plus_four"
4208  [(set (match_operand:SI 0 "register_operand" "+r")
4209	(unspec:SI [(plus:SI (match_dup 0)
4210			     (const (plus:SI (pc) (const_int 4))))]
4211		   UNSPEC_PIC_BASE))
4212   (use (label_ref (match_operand 1 "" "")))]
4213  "TARGET_THUMB && flag_pic"
4214  "*
4215  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4216			     CODE_LABEL_NUMBER (operands[1]));
4217  return \"add\\t%0, %|pc\";
4218  "
4219  [(set_attr "length" "2")]
4220)
4221
4222(define_insn "pic_add_dot_plus_eight"
4223  [(set (match_operand:SI 0 "register_operand" "+r")
4224	(unspec:SI [(plus:SI (match_dup 0)
4225			     (const (plus:SI (pc) (const_int 8))))]
4226		   UNSPEC_PIC_BASE))
4227   (use (label_ref (match_operand 1 "" "")))]
4228  "TARGET_ARM && flag_pic"
4229  "*
4230    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4231			       CODE_LABEL_NUMBER (operands[1]));
4232    return \"add%?\\t%0, %|pc, %0\";
4233  "
4234  [(set_attr "predicable" "yes")]
4235)
4236
4237(define_expand "builtin_setjmp_receiver"
4238  [(label_ref (match_operand 0 "" ""))]
4239  "flag_pic"
4240  "
4241{
4242  arm_finalize_pic (0);
4243  DONE;
4244}")
4245
4246;; If copying one reg to another we can set the condition codes according to
4247;; its value.  Such a move is common after a return from subroutine and the
4248;; result is being tested against zero.
4249
4250(define_insn "*movsi_compare0"
4251  [(set (reg:CC CC_REGNUM)
4252	(compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4253		    (const_int 0)))
4254   (set (match_operand:SI 0 "s_register_operand" "=r,r")
4255	(match_dup 1))]
4256  "TARGET_ARM"
4257  "@
4258   cmp%?\\t%0, #0
4259   sub%?s\\t%0, %1, #0"
4260  [(set_attr "conds" "set")]
4261)
4262
4263;; Subroutine to store a half word from a register into memory.
4264;; Operand 0 is the source register (HImode)
4265;; Operand 1 is the destination address in a register (SImode)
4266
4267;; In both this routine and the next, we must be careful not to spill
4268;; a memory address of reg+large_const into a separate PLUS insn, since this
4269;; can generate unrecognizable rtl.
4270
4271(define_expand "storehi"
4272  [;; store the low byte
4273   (set (match_operand 1 "" "") (match_dup 3))
4274   ;; extract the high byte
4275   (set (match_dup 2)
4276	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4277   ;; store the high byte
4278   (set (match_dup 4) (subreg:QI (match_dup 2) 0))]	;explicit subreg safe
4279  "TARGET_ARM"
4280  "
4281  {
4282    rtx op1 = operands[1];
4283    rtx addr = XEXP (op1, 0);
4284    enum rtx_code code = GET_CODE (addr);
4285
4286    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4287	|| code == MINUS)
4288      op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4289
4290    operands[4] = adjust_address (op1, QImode, 1);
4291    operands[1] = adjust_address (operands[1], QImode, 0);
4292    operands[3] = gen_lowpart (QImode, operands[0]);
4293    operands[0] = gen_lowpart (SImode, operands[0]);
4294    operands[2] = gen_reg_rtx (SImode); 
4295  }"
4296)
4297
4298(define_expand "storehi_bigend"
4299  [(set (match_dup 4) (match_dup 3))
4300   (set (match_dup 2)
4301	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4302   (set (match_operand 1 "" "")	(subreg:QI (match_dup 2) 3))]
4303  "TARGET_ARM"
4304  "
4305  {
4306    rtx op1 = operands[1];
4307    rtx addr = XEXP (op1, 0);
4308    enum rtx_code code = GET_CODE (addr);
4309
4310    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4311	|| code == MINUS)
4312      op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4313
4314    operands[4] = adjust_address (op1, QImode, 1);
4315    operands[1] = adjust_address (operands[1], QImode, 0);
4316    operands[3] = gen_lowpart (QImode, operands[0]);
4317    operands[0] = gen_lowpart (SImode, operands[0]);
4318    operands[2] = gen_reg_rtx (SImode);
4319  }"
4320)
4321
4322;; Subroutine to store a half word integer constant into memory.
4323(define_expand "storeinthi"
4324  [(set (match_operand 0 "" "")
4325	(subreg:QI (match_operand 1 "" "") 0))
4326   (set (match_dup 3) (match_dup 2))]
4327  "TARGET_ARM"
4328  "
4329  {
4330    HOST_WIDE_INT value = INTVAL (operands[1]);
4331    rtx addr = XEXP (operands[0], 0);
4332    rtx op0 = operands[0];
4333    enum rtx_code code = GET_CODE (addr);
4334
4335    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4336	|| code == MINUS)
4337      op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4338
4339    operands[1] = gen_reg_rtx (SImode);
4340    if (BYTES_BIG_ENDIAN)
4341      {
4342	emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4343	if ((value & 255) == ((value >> 8) & 255))
4344	  operands[2] = operands[1];
4345	else
4346	  {
4347	    operands[2] = gen_reg_rtx (SImode);
4348	    emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4349	  }
4350      }
4351    else
4352      {
4353	emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4354	if ((value & 255) == ((value >> 8) & 255))
4355	  operands[2] = operands[1];
4356	else
4357	  {
4358	    operands[2] = gen_reg_rtx (SImode);
4359	    emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4360	  }
4361      }
4362
4363    operands[3] = adjust_address (op0, QImode, 1);
4364    operands[0] = adjust_address (operands[0], QImode, 0);
4365    operands[2] = gen_lowpart (QImode, operands[2]);
4366  }"
4367)
4368
4369(define_expand "storehi_single_op"
4370  [(set (match_operand:HI 0 "memory_operand" "")
4371	(match_operand:HI 1 "general_operand" ""))]
4372  "TARGET_ARM && arm_arch4"
4373  "
4374  if (!s_register_operand (operands[1], HImode))
4375    operands[1] = copy_to_mode_reg (HImode, operands[1]);
4376  "
4377)
4378
4379(define_expand "movhi"
4380  [(set (match_operand:HI 0 "general_operand" "")
4381	(match_operand:HI 1 "general_operand" ""))]
4382  "TARGET_EITHER"
4383  "
4384  if (TARGET_ARM)
4385    {
4386      if (!no_new_pseudos)
4387        {
4388          if (GET_CODE (operands[0]) == MEM)
4389	    {
4390	      if (arm_arch4)
4391	        {
4392	          emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4393	          DONE;
4394	        }
4395	      if (GET_CODE (operands[1]) == CONST_INT)
4396	        emit_insn (gen_storeinthi (operands[0], operands[1]));
4397	      else
4398	        {
4399	          if (GET_CODE (operands[1]) == MEM)
4400		    operands[1] = force_reg (HImode, operands[1]);
4401	          if (BYTES_BIG_ENDIAN)
4402		    emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4403	          else
4404		   emit_insn (gen_storehi (operands[1], operands[0]));
4405	        }
4406	      DONE;
4407	    }
4408          /* Sign extend a constant, and keep it in an SImode reg.  */
4409          else if (GET_CODE (operands[1]) == CONST_INT)
4410	    {
4411	      rtx reg = gen_reg_rtx (SImode);
4412	      HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4413
4414	      /* If the constant is already valid, leave it alone.  */
4415	      if (!const_ok_for_arm (val))
4416	        {
4417	          /* If setting all the top bits will make the constant 
4418		     loadable in a single instruction, then set them.  
4419		     Otherwise, sign extend the number.  */
4420
4421	          if (const_ok_for_arm (~(val | ~0xffff)))
4422		    val |= ~0xffff;
4423	          else if (val & 0x8000)
4424		    val |= ~0xffff;
4425	        }
4426
4427	      emit_insn (gen_movsi (reg, GEN_INT (val)));
4428	      operands[1] = gen_lowpart (HImode, reg);
4429	    }
4430	  else if (arm_arch4 && !no_new_pseudos && optimize > 0
4431		   && GET_CODE (operands[1]) == MEM)
4432	    {
4433	      rtx reg = gen_reg_rtx (SImode);
4434
4435	      emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4436	      operands[1] = gen_lowpart (HImode, reg);
4437	    }
4438          else if (!arm_arch4)
4439	    {
4440	     /* Note: We do not have to worry about TARGET_MMU_TRAPS
4441	        for v4 and up architectures because LDRH instructions will
4442	        be used to access the HI values, and these cannot generate
4443	        unaligned word access faults in the MMU.  */
4444	      if (GET_CODE (operands[1]) == MEM)
4445	        {
4446	          if (TARGET_MMU_TRAPS)
4447		    {
4448		      rtx base;
4449		      rtx offset = const0_rtx;
4450		      rtx reg = gen_reg_rtx (SImode);
4451
4452		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4453		           || (GET_CODE (base) == PLUS
4454			       && (GET_CODE (offset = XEXP (base, 1))
4455				   == CONST_INT)
4456                               && ((INTVAL(offset) & 1) != 1)
4457			       && GET_CODE (base = XEXP (base, 0)) == REG))
4458		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4459		        {
4460		          HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4461		          rtx new;
4462
4463		          new = gen_rtx_MEM (SImode,
4464				   	     plus_constant (base, new_offset));
4465	                  MEM_COPY_ATTRIBUTES (new, operands[1]);
4466		          emit_insn (gen_movsi (reg, new));
4467		          if (((INTVAL (offset) & 2) != 0)
4468			      ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4469			    {
4470			      rtx reg2 = gen_reg_rtx (SImode);
4471
4472			      emit_insn (gen_lshrsi3 (reg2, reg,
4473					 GEN_INT (16)));
4474			      reg = reg2;
4475			    }
4476		        }
4477		      else
4478		        emit_insn (gen_movhi_bytes (reg, operands[1]));
4479
4480		      operands[1] = gen_lowpart (HImode, reg);
4481		    }
4482	          else if (BYTES_BIG_ENDIAN)
4483		    {
4484		      rtx base;
4485		      rtx offset = const0_rtx;
4486
4487		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4488		           || (GET_CODE (base) == PLUS
4489			      && (GET_CODE (offset = XEXP (base, 1))
4490				  == CONST_INT)
4491			      && GET_CODE (base = XEXP (base, 0)) == REG))
4492		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4493		        {
4494		          rtx reg = gen_reg_rtx (SImode);
4495		          rtx new;
4496
4497		          if ((INTVAL (offset) & 2) == 2)
4498			    {
4499			      HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4500			      new = gen_rtx_MEM (SImode,
4501				  	         plus_constant (base,
4502								new_offset));
4503                              MEM_COPY_ATTRIBUTES (new, operands[1]);
4504			      emit_insn (gen_movsi (reg, new));
4505			    }
4506		          else
4507			    {
4508			      new = gen_rtx_MEM (SImode,
4509						 XEXP (operands[1], 0));
4510	                      MEM_COPY_ATTRIBUTES (new, operands[1]);
4511			      emit_insn (gen_rotated_loadsi (reg, new));
4512			    }
4513
4514		          operands[1] = gen_lowpart (HImode, reg);
4515		        }
4516		      else
4517		        {
4518		          emit_insn (gen_movhi_bigend (operands[0],
4519						       operands[1]));
4520		          DONE;
4521		        }
4522		    }
4523	       }
4524	   }
4525        }
4526      /* Handle loading a large integer during reload */
4527      else if (GET_CODE (operands[1]) == CONST_INT
4528	       && !const_ok_for_arm (INTVAL (operands[1]))
4529	       && !const_ok_for_arm (~INTVAL (operands[1])))
4530        {
4531          /* Writing a constant to memory needs a scratch, which should
4532	     be handled with SECONDARY_RELOADs.  */
4533          if (GET_CODE (operands[0]) != REG)
4534	    abort ();
4535
4536          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4537          emit_insn (gen_movsi (operands[0], operands[1]));
4538          DONE;
4539       }
4540    }
4541  else /* TARGET_THUMB */
4542    {
4543      if (!no_new_pseudos)
4544        {
4545          if (GET_CODE (operands[0]) != REG)
4546	    operands[1] = force_reg (HImode, operands[1]);
4547
4548          /* ??? We shouldn't really get invalid addresses here, but this can
4549	     happen if we are passed a SP (never OK for HImode/QImode) or 
4550	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4551	     HImode/QImode) relative address.  */
4552          /* ??? This should perhaps be fixed elsewhere, for instance, in
4553	     fixup_stack_1, by checking for other kinds of invalid addresses,
4554	     e.g. a bare reference to a virtual register.  This may confuse the
4555	     alpha though, which must handle this case differently.  */
4556          if (GET_CODE (operands[0]) == MEM
4557	      && !memory_address_p (GET_MODE (operands[0]),
4558				    XEXP (operands[0], 0)))
4559	    operands[0]
4560	      = replace_equiv_address (operands[0],
4561				       copy_to_reg (XEXP (operands[0], 0)));
4562   
4563          if (GET_CODE (operands[1]) == MEM
4564	      && !memory_address_p (GET_MODE (operands[1]),
4565				    XEXP (operands[1], 0)))
4566	    operands[1]
4567	      = replace_equiv_address (operands[1],
4568				       copy_to_reg (XEXP (operands[1], 0)));
4569        }
4570      /* Handle loading a large integer during reload */
4571      else if (GET_CODE (operands[1]) == CONST_INT
4572	        && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4573        {
4574          /* Writing a constant to memory needs a scratch, which should
4575	     be handled with SECONDARY_RELOADs.  */
4576          if (GET_CODE (operands[0]) != REG)
4577	    abort ();
4578
4579          operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4580          emit_insn (gen_movsi (operands[0], operands[1]));
4581          DONE;
4582        }
4583    }
4584  "
4585)
4586
4587(define_insn "*thumb_movhi_insn"
4588  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4589	(match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4590  "TARGET_THUMB
4591   && (   register_operand (operands[0], HImode)
4592       || register_operand (operands[1], HImode))"
4593  "*
4594  switch (which_alternative)
4595    {
4596    case 0: return \"add	%0, %1, #0\";
4597    case 2: return \"strh	%1, %0\";
4598    case 3: return \"mov	%0, %1\";
4599    case 4: return \"mov	%0, %1\";
4600    case 5: return \"mov	%0, %1\";
4601    default: abort ();
4602    case 1:
4603      /* The stack pointer can end up being taken as an index register.
4604          Catch this case here and deal with it.  */
4605      if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4606	  && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4607	  && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4608        {
4609	  rtx ops[2];
4610          ops[0] = operands[0];
4611          ops[1] = XEXP (XEXP (operands[1], 0), 0);
4612      
4613          output_asm_insn (\"mov	%0, %1\", ops);
4614
4615          XEXP (XEXP (operands[1], 0), 0) = operands[0];
4616    
4617	}
4618      return \"ldrh	%0, %1\";
4619    }"
4620  [(set_attr "length" "2,4,2,2,2,2")
4621   (set_attr "type" "*,load,store1,*,*,*")
4622   (set_attr "pool_range" "*,64,*,*,*,*")]
4623)
4624
4625
4626(define_insn "rotated_loadsi"
4627  [(set (match_operand:SI            0 "s_register_operand"        "=r")
4628	(rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4629		   (const_int 16)))]
4630  "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4631  "*
4632  {
4633    rtx ops[2];
4634
4635    ops[0] = operands[0];
4636    ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4637    output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4638    return \"\";
4639  }"
4640  [(set_attr "type" "load")
4641   (set_attr "predicable" "yes")]
4642)
4643
4644(define_expand "movhi_bytes"
4645  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4646   (set (match_dup 3)
4647	(zero_extend:SI (match_dup 6)))
4648   (set (match_operand:SI 0 "" "")
4649	 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4650  "TARGET_ARM"
4651  "
4652  {
4653    rtx mem1, mem2;
4654    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4655
4656    mem1 = gen_rtx_MEM (QImode, addr);
4657    MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4658    mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4659    MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4660    operands[0] = gen_lowpart (SImode, operands[0]);
4661    operands[1] = mem1;
4662    operands[2] = gen_reg_rtx (SImode);
4663    operands[3] = gen_reg_rtx (SImode);
4664    operands[6] = mem2;
4665
4666    if (BYTES_BIG_ENDIAN)
4667      {
4668	operands[4] = operands[2];
4669	operands[5] = operands[3];
4670      }
4671    else
4672      {
4673	operands[4] = operands[3];
4674	operands[5] = operands[2];
4675      }
4676  }"
4677)
4678
4679(define_expand "movhi_bigend"
4680  [(set (match_dup 2)
4681	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4682		   (const_int 16)))
4683   (set (match_dup 3)
4684	(ashiftrt:SI (match_dup 2) (const_int 16)))
4685   (set (match_operand:HI 0 "s_register_operand" "")
4686	(subreg:HI (match_dup 3) 0))]
4687  "TARGET_ARM"
4688  "
4689  operands[2] = gen_reg_rtx (SImode);
4690  operands[3] = gen_reg_rtx (SImode);
4691  "
4692)
4693
4694;; Pattern to recognize insn generated default case above
4695(define_insn "*movhi_insn_arch4"
4696  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4697	(match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4698  "TARGET_ARM
4699   && arm_arch4
4700   && (GET_CODE (operands[1]) != CONST_INT
4701       || const_ok_for_arm (INTVAL (operands[1]))
4702       || const_ok_for_arm (~INTVAL (operands[1])))"
4703  "@
4704   mov%?\\t%0, %1\\t%@ movhi
4705   mvn%?\\t%0, #%B1\\t%@ movhi
4706   str%?h\\t%1, %0\\t%@ movhi 
4707   ldr%?h\\t%0, %1\\t%@ movhi"
4708  [(set_attr "type" "*,*,store1,load")
4709   (set_attr "predicable" "yes")
4710   (set_attr "pool_range" "*,*,*,256")
4711   (set_attr "neg_pool_range" "*,*,*,244")]
4712)
4713
4714(define_insn "*movhi_insn_littleend"
4715  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4716	(match_operand:HI 1 "general_operand"  "rI,K,m"))]
4717  "TARGET_ARM
4718   && !arm_arch4
4719   && !BYTES_BIG_ENDIAN
4720   && !TARGET_MMU_TRAPS
4721   && (GET_CODE (operands[1]) != CONST_INT
4722       || const_ok_for_arm (INTVAL (operands[1]))
4723       || const_ok_for_arm (~INTVAL (operands[1])))"
4724  "@
4725   mov%?\\t%0, %1\\t%@ movhi
4726   mvn%?\\t%0, #%B1\\t%@ movhi
4727   ldr%?\\t%0, %1\\t%@ movhi"
4728  [(set_attr "type" "*,*,load")
4729   (set_attr "predicable" "yes")
4730   (set_attr "pool_range" "4096")
4731   (set_attr "neg_pool_range" "4084")]
4732)
4733
4734(define_insn "*movhi_insn_bigend"
4735  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4736	(match_operand:HI 1 "general_operand"    "rI,K,m"))]
4737  "TARGET_ARM
4738   && !arm_arch4
4739   && BYTES_BIG_ENDIAN
4740   && !TARGET_MMU_TRAPS
4741   && (GET_CODE (operands[1]) != CONST_INT
4742       || const_ok_for_arm (INTVAL (operands[1]))
4743       || const_ok_for_arm (~INTVAL (operands[1])))"
4744  "@
4745   mov%?\\t%0, %1\\t%@ movhi
4746   mvn%?\\t%0, #%B1\\t%@ movhi
4747   ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4748  [(set_attr "type" "*,*,load")
4749   (set_attr "predicable" "yes")
4750   (set_attr "length" "4,4,8")
4751   (set_attr "pool_range" "*,*,4092")
4752   (set_attr "neg_pool_range" "*,*,4084")]
4753)
4754
4755(define_insn "*loadhi_si_bigend"
4756  [(set (match_operand:SI                       0 "s_register_operand" "=r")
4757	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4758		   (const_int 16)))]
4759  "TARGET_ARM
4760   && BYTES_BIG_ENDIAN
4761   && !TARGET_MMU_TRAPS"
4762  "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4763  [(set_attr "type" "load")
4764   (set_attr "predicable" "yes")
4765   (set_attr "pool_range" "4096")
4766   (set_attr "neg_pool_range" "4084")]
4767)
4768
4769(define_insn "*movhi_bytes"
4770  [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4771	(match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4772  "TARGET_ARM && TARGET_MMU_TRAPS"
4773  "@
4774   mov%?\\t%0, %1\\t%@ movhi
4775   mvn%?\\t%0, #%B1\\t%@ movhi"
4776  [(set_attr "predicable" "yes")]
4777)
4778
4779(define_insn "thumb_movhi_clobber"
4780  [(set (match_operand:HI     0 "memory_operand"   "=m")
4781	(match_operand:HI     1 "register_operand" "l"))
4782   (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4783  "TARGET_THUMB"
4784  "*
4785  abort ();"
4786)
4787	
4788;; We use a DImode scratch because we may occasionally need an additional
4789;; temporary if the address isn't offsettable -- push_reload doesn't seem
4790;; to take any notice of the "o" constraints on reload_memory_operand operand.
4791(define_expand "reload_outhi"
4792  [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4793	      (match_operand:HI 1 "s_register_operand"        "r")
4794	      (match_operand:DI 2 "s_register_operand"        "=&l")])]
4795  "TARGET_EITHER"
4796  "if (TARGET_ARM)
4797     arm_reload_out_hi (operands);
4798   else
4799     thumb_reload_out_hi (operands);
4800  DONE;
4801  "
4802)
4803
4804(define_expand "reload_inhi"
4805  [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4806	      (match_operand:HI 1 "arm_reload_memory_operand" "o")
4807	      (match_operand:DI 2 "s_register_operand" "=&r")])]
4808  "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4809  "
4810  if (TARGET_ARM)
4811    arm_reload_in_hi (operands);
4812  else
4813    thumb_reload_out_hi (operands);
4814  DONE;
4815")
4816
4817(define_expand "movqi"
4818  [(set (match_operand:QI 0 "general_operand" "")
4819        (match_operand:QI 1 "general_operand" ""))]
4820  "TARGET_EITHER"
4821  "
4822  if (TARGET_ARM)
4823    {
4824      /* Everything except mem = const or mem = mem can be done easily */
4825
4826      if (!no_new_pseudos)
4827        {
4828          if (GET_CODE (operands[1]) == CONST_INT)
4829	    {
4830	      rtx reg = gen_reg_rtx (SImode);
4831
4832	      emit_insn (gen_movsi (reg, operands[1]));
4833	      operands[1] = gen_lowpart (QImode, reg);
4834	    }
4835	  if (GET_CODE (operands[1]) == MEM && optimize > 0)
4836	    {
4837	      rtx reg = gen_reg_rtx (SImode);
4838
4839	      emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4840	      operands[1] = gen_lowpart (QImode, reg);
4841	    }
4842          if (GET_CODE (operands[0]) == MEM)
4843	    operands[1] = force_reg (QImode, operands[1]);
4844        }
4845    }
4846  else /* TARGET_THUMB */
4847    {
4848      if (!no_new_pseudos)
4849        {
4850          if (GET_CODE (operands[0]) != REG)
4851	    operands[1] = force_reg (QImode, operands[1]);
4852
4853          /* ??? We shouldn't really get invalid addresses here, but this can
4854	     happen if we are passed a SP (never OK for HImode/QImode) or
4855	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4856	     HImode/QImode) relative address.  */
4857          /* ??? This should perhaps be fixed elsewhere, for instance, in
4858	     fixup_stack_1, by checking for other kinds of invalid addresses,
4859	     e.g. a bare reference to a virtual register.  This may confuse the
4860	     alpha though, which must handle this case differently.  */
4861          if (GET_CODE (operands[0]) == MEM
4862	      && !memory_address_p (GET_MODE (operands[0]),
4863		  		     XEXP (operands[0], 0)))
4864	    operands[0]
4865	      = replace_equiv_address (operands[0],
4866				       copy_to_reg (XEXP (operands[0], 0)));
4867          if (GET_CODE (operands[1]) == MEM
4868	      && !memory_address_p (GET_MODE (operands[1]),
4869				    XEXP (operands[1], 0)))
4870	     operands[1]
4871	       = replace_equiv_address (operands[1],
4872					copy_to_reg (XEXP (operands[1], 0)));
4873        }
4874      /* Handle loading a large integer during reload */
4875      else if (GET_CODE (operands[1]) == CONST_INT
4876	       && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4877        {
4878          /* Writing a constant to memory needs a scratch, which should
4879	     be handled with SECONDARY_RELOADs.  */
4880          if (GET_CODE (operands[0]) != REG)
4881	    abort ();
4882
4883          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4884          emit_insn (gen_movsi (operands[0], operands[1]));
4885          DONE;
4886       }
4887    }
4888  "
4889)
4890
4891
4892(define_insn "*arm_movqi_insn"
4893  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4894	(match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4895  "TARGET_ARM
4896   && (   register_operand (operands[0], QImode)
4897       || register_operand (operands[1], QImode))"
4898  "@
4899   mov%?\\t%0, %1
4900   mvn%?\\t%0, #%B1
4901   ldr%?b\\t%0, %1
4902   str%?b\\t%1, %0"
4903  [(set_attr "type" "*,*,load,store1")
4904   (set_attr "predicable" "yes")]
4905)
4906
4907(define_insn "*thumb_movqi_insn"
4908  [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4909	(match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4910  "TARGET_THUMB
4911   && (   register_operand (operands[0], QImode)
4912       || register_operand (operands[1], QImode))"
4913  "@
4914   add\\t%0, %1, #0
4915   ldrb\\t%0, %1
4916   strb\\t%1, %0
4917   mov\\t%0, %1
4918   mov\\t%0, %1
4919   mov\\t%0, %1"
4920  [(set_attr "length" "2")
4921   (set_attr "type" "*,load,store1,*,*,*")
4922   (set_attr "pool_range" "*,32,*,*,*,*")]
4923)
4924
4925(define_expand "movsf"
4926  [(set (match_operand:SF 0 "general_operand" "")
4927	(match_operand:SF 1 "general_operand" ""))]
4928  "TARGET_EITHER"
4929  "
4930  if (TARGET_ARM)
4931    {
4932      if (GET_CODE (operands[0]) == MEM)
4933        operands[1] = force_reg (SFmode, operands[1]);
4934    }
4935  else /* TARGET_THUMB */
4936    {
4937      if (!no_new_pseudos)
4938        {
4939           if (GET_CODE (operands[0]) != REG)
4940	     operands[1] = force_reg (SFmode, operands[1]);
4941        }
4942    }
4943  "
4944)
4945
4946(define_split
4947  [(set (match_operand:SF 0 "nonimmediate_operand" "")
4948	(match_operand:SF 1 "immediate_operand" ""))]
4949  "TARGET_ARM
4950   && !TARGET_HARD_FLOAT
4951   && reload_completed
4952   && GET_CODE (operands[1]) == CONST_DOUBLE"
4953  [(set (match_dup 2) (match_dup 3))]
4954  "
4955  operands[2] = gen_lowpart (SImode, operands[0]);
4956  operands[3] = gen_lowpart (SImode, operands[1]);
4957  if (operands[2] == 0 || operands[3] == 0)
4958    FAIL;
4959  "
4960)
4961
4962(define_insn "*arm_movsf_hard_insn"
4963  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4964	(match_operand:SF 1 "general_operand"      "fG,H,mE,f,r,f,r,mE,r"))]
4965  "TARGET_ARM
4966   && TARGET_HARD_FLOAT
4967   && (GET_CODE (operands[0]) != MEM
4968       || register_operand (operands[1], SFmode))"
4969  "@
4970   mvf%?s\\t%0, %1
4971   mnf%?s\\t%0, #%N1
4972   ldf%?s\\t%0, %1
4973   stf%?s\\t%1, %0
4974   str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4975   stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4976   mov%?\\t%0, %1
4977   ldr%?\\t%0, %1\\t%@ float
4978   str%?\\t%1, %0\\t%@ float"
4979  [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4980   (set_attr "predicable" "yes")
4981   (set_attr "type"
4982	 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4983   (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4984   (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4985)
4986
4987;; Exactly the same as above, except that all `f' cases are deleted.
4988;; This is necessary to prevent reload from ever trying to use a `f' reg
4989;; when -msoft-float.
4990
4991(define_insn "*arm_movsf_soft_insn"
4992  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4993	(match_operand:SF 1 "general_operand"  "r,mE,r"))]
4994  "TARGET_ARM
4995   && TARGET_SOFT_FLOAT
4996   && (GET_CODE (operands[0]) != MEM
4997       || register_operand (operands[1], SFmode))"
4998  "@
4999   mov%?\\t%0, %1
5000   ldr%?\\t%0, %1\\t%@ float
5001   str%?\\t%1, %0\\t%@ float"
5002  [(set_attr "length" "4,4,4")
5003   (set_attr "predicable" "yes")
5004   (set_attr "type" "*,load,store1")
5005   (set_attr "pool_range" "*,4096,*")
5006   (set_attr "neg_pool_range" "*,4084,*")]
5007)
5008
5009;;; ??? This should have alternatives for constants.
5010(define_insn "*thumb_movsf_insn"
5011  [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5012	(match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5013  "TARGET_THUMB
5014   && (   register_operand (operands[0], SFmode) 
5015       || register_operand (operands[1], SFmode))"
5016  "@
5017   add\\t%0, %1, #0
5018   ldmia\\t%1, {%0}
5019   stmia\\t%0, {%1}
5020   ldr\\t%0, %1
5021   str\\t%1, %0
5022   mov\\t%0, %1
5023   mov\\t%0, %1"
5024  [(set_attr "length" "2")
5025   (set_attr "type" "*,load,store1,load,store1,*,*")
5026   (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5027)
5028
5029(define_expand "movdf"
5030  [(set (match_operand:DF 0 "general_operand" "")
5031	(match_operand:DF 1 "general_operand" ""))]
5032  "TARGET_EITHER"
5033  "
5034  if (TARGET_ARM)
5035    {
5036      if (GET_CODE (operands[0]) == MEM)
5037        operands[1] = force_reg (DFmode, operands[1]);
5038    }
5039  else /* TARGET_THUMB */
5040    {
5041      if (!no_new_pseudos)
5042        {
5043          if (GET_CODE (operands[0]) != REG)
5044	    operands[1] = force_reg (DFmode, operands[1]);
5045        }
5046    }
5047  "
5048)
5049
5050;; Reloading a df mode value stored in integer regs to memory can require a
5051;; scratch reg.
5052(define_expand "reload_outdf"
5053  [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5054   (match_operand:DF 1 "s_register_operand" "r")
5055   (match_operand:SI 2 "s_register_operand" "=&r")]
5056  "TARGET_ARM"
5057  "
5058  {
5059    enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5060
5061    if (code == REG)
5062      operands[2] = XEXP (operands[0], 0);
5063    else if (code == POST_INC || code == PRE_DEC)
5064      {
5065	operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5066	operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5067	emit_insn (gen_movdi (operands[0], operands[1]));
5068	DONE;
5069      }
5070    else if (code == PRE_INC)
5071      {
5072	rtx reg = XEXP (XEXP (operands[0], 0), 0);
5073
5074	emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5075	operands[2] = reg;
5076      }
5077    else if (code == POST_DEC)
5078      operands[2] = XEXP (XEXP (operands[0], 0), 0);
5079    else
5080      emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5081			     XEXP (XEXP (operands[0], 0), 1)));
5082
5083    emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5084			    operands[1]));
5085
5086    if (code == POST_DEC)
5087      emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5088
5089    DONE;
5090  }"
5091)
5092
5093(define_insn "*movdf_hard_insn"
5094  [(set (match_operand:DF 0 "nonimmediate_operand"
5095						"=r,Q,r,m,r, f, f,f, m,!f,!r")
5096	(match_operand:DF 1 "general_operand"
5097						"Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5098  "TARGET_ARM
5099   && TARGET_HARD_FLOAT
5100   && (GET_CODE (operands[0]) != MEM
5101       || register_operand (operands[1], DFmode))"
5102  "*
5103  {
5104  switch (which_alternative)
5105    {
5106    default:
5107    case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5108    case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5109    case 2: case 3: case 4: return output_move_double (operands);
5110    case 5: return \"mvf%?d\\t%0, %1\";
5111    case 6: return \"mnf%?d\\t%0, #%N1\";
5112    case 7: return \"ldf%?d\\t%0, %1\";
5113    case 8: return \"stf%?d\\t%1, %0\";
5114    case 9: return output_mov_double_fpu_from_arm (operands);
5115    case 10: return output_mov_double_arm_from_fpu (operands);
5116    }
5117  }
5118  "
5119  [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5120   (set_attr "predicable" "yes")
5121   (set_attr "type"
5122    "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5123   (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
5124   (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
5125)
5126
5127;; Software floating point version.  This is essentially the same as movdi.
5128;; Do not use `f' as a constraint to prevent reload from ever trying to use
5129;; an `f' reg.
5130
5131(define_insn "*movdf_soft_insn"
5132  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5133	(match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5134  "TARGET_ARM && TARGET_SOFT_FLOAT
5135  "
5136  "* return output_move_double (operands);"
5137  [(set_attr "length" "8,8,8")
5138   (set_attr "type" "*,load,store2")
5139   (set_attr "pool_range" "1020")
5140   (set_attr "neg_pool_range" "1008")]
5141)
5142
5143;;; ??? This should have alternatives for constants.
5144;;; ??? This was originally identical to the movdi_insn pattern.
5145;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5146;;; thumb_reorg with a memory reference.
5147(define_insn "*thumb_movdf_insn"
5148  [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5149	(match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5150  "TARGET_THUMB
5151   && (   register_operand (operands[0], DFmode)
5152       || register_operand (operands[1], DFmode))"
5153  "*
5154  switch (which_alternative)
5155    {
5156    default:
5157    case 0:
5158      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5159	return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5160      return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5161    case 1:
5162      return \"ldmia\\t%1, {%0, %H0}\";
5163    case 2:
5164      return \"stmia\\t%0, {%1, %H1}\";
5165    case 3:
5166      return thumb_load_double_from_address (operands);
5167    case 4:
5168      operands[2] = gen_rtx (MEM, SImode,
5169			     plus_constant (XEXP (operands[0], 0), 4));
5170      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5171      return \"\";
5172    case 5:
5173      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5174	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5175      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5176    }
5177  "
5178  [(set_attr "length" "4,2,2,6,4,4")
5179   (set_attr "type" "*,load,store2,load,store2,*")
5180   (set_attr "pool_range" "*,*,*,1020,*,*")]
5181)
5182
5183
5184(define_expand "movxf"
5185  [(set (match_operand:XF 0 "general_operand" "")
5186	(match_operand:XF 1 "general_operand" ""))]
5187  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5188  "")
5189
5190;; Even when the XFmode patterns aren't enabled, we enable this after
5191;; reloading so that we can push floating point registers in the prologue.
5192
5193(define_insn "*movxf_hard_insn"
5194  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5195	(match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5196  "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5197  "*
5198  switch (which_alternative)
5199    {
5200    default:
5201    case 0: return \"mvf%?e\\t%0, %1\";
5202    case 1: return \"mnf%?e\\t%0, #%N1\";
5203    case 2: return \"ldf%?e\\t%0, %1\";
5204    case 3: return \"stf%?e\\t%1, %0\";
5205    case 4: return output_mov_long_double_fpu_from_arm (operands);
5206    case 5: return output_mov_long_double_arm_from_fpu (operands);
5207    case 6: return output_mov_long_double_arm_from_arm (operands);
5208    }
5209  "
5210  [(set_attr "length" "4,4,4,4,8,8,12")
5211   (set_attr "predicable" "yes")
5212   (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5213   (set_attr "pool_range" "*,*,1024,*,*,*,*")
5214   (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5215)
5216
5217
5218;; load- and store-multiple insns
5219;; The arm can load/store any set of registers, provided that they are in
5220;; ascending order; but that is beyond GCC so stick with what it knows.
5221
5222(define_expand "load_multiple"
5223  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5224                          (match_operand:SI 1 "" ""))
5225                     (use (match_operand:SI 2 "" ""))])]
5226  "TARGET_ARM"
5227  "
5228  /* Support only fixed point registers.  */
5229  if (GET_CODE (operands[2]) != CONST_INT
5230      || INTVAL (operands[2]) > 14
5231      || INTVAL (operands[2]) < 2
5232      || GET_CODE (operands[1]) != MEM
5233      || GET_CODE (operands[0]) != REG
5234      || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5235      || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5236    FAIL;
5237
5238  operands[3]
5239    = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5240			     force_reg (SImode, XEXP (operands[1], 0)),
5241			     TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5242			     MEM_IN_STRUCT_P(operands[1]),
5243	                     MEM_SCALAR_P (operands[1]));
5244  "
5245)
5246
5247;; Load multiple with write-back
5248
5249(define_insn "*ldmsi_postinc4"
5250  [(match_parallel 0 "load_multiple_operation"
5251    [(set (match_operand:SI 1 "s_register_operand" "=r")
5252	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5253		   (const_int 16)))
5254     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5255	  (mem:SI (match_dup 2)))
5256     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5257	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5258     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5259	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5260     (set (match_operand:SI 6 "arm_hard_register_operand" "")
5261	  (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5262  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5263  "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5264  [(set_attr "type" "load")
5265   (set_attr "predicable" "yes")]
5266)
5267
5268(define_insn "*ldmsi_postinc3"
5269  [(match_parallel 0 "load_multiple_operation"
5270    [(set (match_operand:SI 1 "s_register_operand" "=r")
5271	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5272		   (const_int 12)))
5273     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5274	  (mem:SI (match_dup 2)))
5275     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5276	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5277     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5278	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5279  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5280  "ldm%?ia\\t%1!, {%3, %4, %5}"
5281  [(set_attr "type" "load")
5282   (set_attr "predicable" "yes")]
5283)
5284
5285(define_insn "*ldmsi_postinc2"
5286  [(match_parallel 0 "load_multiple_operation"
5287    [(set (match_operand:SI 1 "s_register_operand" "=r")
5288	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5289		   (const_int 8)))
5290     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5291	  (mem:SI (match_dup 2)))
5292     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5293	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5294  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5295  "ldm%?ia\\t%1!, {%3, %4}"
5296  [(set_attr "type" "load")
5297   (set_attr "predicable" "yes")]
5298)
5299
5300;; Ordinary load multiple
5301
5302(define_insn "*ldmsi4"
5303  [(match_parallel 0 "load_multiple_operation"
5304    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5305	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5306     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5307	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5308     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5309	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5310     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5311	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5312  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5313  "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5314  [(set_attr "type" "load")
5315   (set_attr "predicable" "yes")]
5316)
5317
5318(define_insn "*ldmsi3"
5319  [(match_parallel 0 "load_multiple_operation"
5320    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5321	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5322     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5323	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5324     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5325	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5326  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5327  "ldm%?ia\\t%1, {%2, %3, %4}"
5328  [(set_attr "type" "load")
5329   (set_attr "predicable" "yes")]
5330)
5331
5332(define_insn "*ldmsi2"
5333  [(match_parallel 0 "load_multiple_operation"
5334    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5335	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5336     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5337	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5338  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5339  "ldm%?ia\\t%1, {%2, %3}"
5340  [(set_attr "type" "load")
5341   (set_attr "predicable" "yes")]
5342)
5343
5344(define_expand "store_multiple"
5345  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5346                          (match_operand:SI 1 "" ""))
5347                     (use (match_operand:SI 2 "" ""))])]
5348  "TARGET_ARM"
5349  "
5350  /* Support only fixed point registers */
5351  if (GET_CODE (operands[2]) != CONST_INT
5352      || INTVAL (operands[2]) > 14
5353      || INTVAL (operands[2]) < 2
5354      || GET_CODE (operands[1]) != REG
5355      || GET_CODE (operands[0]) != MEM
5356      || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5357      || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5358    FAIL;
5359
5360  operands[3]
5361    = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5362			      force_reg (SImode, XEXP (operands[0], 0)),
5363			      TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5364			      MEM_IN_STRUCT_P(operands[0]), 
5365	                      MEM_SCALAR_P (operands[0]));
5366  "
5367)
5368
5369;; Store multiple with write-back
5370
5371(define_insn "*stmsi_postinc4"
5372  [(match_parallel 0 "store_multiple_operation"
5373    [(set (match_operand:SI 1 "s_register_operand" "=r")
5374	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5375		   (const_int 16)))
5376     (set (mem:SI (match_dup 2))
5377	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5378     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5379	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5380     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5381	  (match_operand:SI 5 "arm_hard_register_operand" ""))
5382     (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5383	  (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5384  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5385  "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5386  [(set_attr "predicable" "yes")
5387   (set_attr "type" "store4")]
5388)
5389
5390(define_insn "*stmsi_postinc3"
5391  [(match_parallel 0 "store_multiple_operation"
5392    [(set (match_operand:SI 1 "s_register_operand" "=r")
5393	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5394		   (const_int 12)))
5395     (set (mem:SI (match_dup 2))
5396	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5397     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5398	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5399     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5400	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5401  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5402  "stm%?ia\\t%1!, {%3, %4, %5}"
5403  [(set_attr "predicable" "yes")
5404   (set_attr "type" "store3")]
5405)
5406
5407(define_insn "*stmsi_postinc2"
5408  [(match_parallel 0 "store_multiple_operation"
5409    [(set (match_operand:SI 1 "s_register_operand" "=r")
5410	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5411		   (const_int 8)))
5412     (set (mem:SI (match_dup 2))
5413	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5414     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5415	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5416  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5417  "stm%?ia\\t%1!, {%3, %4}"
5418  [(set_attr "predicable" "yes")
5419   (set_attr "type" "store2")]
5420)
5421
5422;; Ordinary store multiple
5423
5424(define_insn "*stmsi4"
5425  [(match_parallel 0 "store_multiple_operation"
5426    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5427	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5428     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5429	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5430     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5431	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5432     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5433	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5434  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5435  "stm%?ia\\t%1, {%2, %3, %4, %5}"
5436  [(set_attr "predicable" "yes")
5437   (set_attr "type" "store4")]
5438)
5439
5440(define_insn "*stmsi3"
5441  [(match_parallel 0 "store_multiple_operation"
5442    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5443	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5444     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5445	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5446     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5447	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5448  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5449  "stm%?ia\\t%1, {%2, %3, %4}"
5450  [(set_attr "predicable" "yes")
5451   (set_attr "type" "store3")]
5452)
5453
5454(define_insn "*stmsi2"
5455  [(match_parallel 0 "store_multiple_operation"
5456    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5457	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5458     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5459	  (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5460  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5461  "stm%?ia\\t%1, {%2, %3}"
5462  [(set_attr "predicable" "yes")
5463   (set_attr "type" "store2")]
5464)
5465
5466;; Move a block of memory if it is word aligned and MORE than 2 words long.
5467;; We could let this apply for blocks of less than this, but it clobbers so
5468;; many registers that there is then probably a better way.
5469
5470(define_expand "movstrqi"
5471  [(match_operand:BLK 0 "general_operand" "")
5472   (match_operand:BLK 1 "general_operand" "")
5473   (match_operand:SI 2 "const_int_operand" "")
5474   (match_operand:SI 3 "const_int_operand" "")]
5475  "TARGET_EITHER"
5476  "
5477  if (TARGET_ARM)
5478    {
5479      if (arm_gen_movstrqi (operands))
5480        DONE;
5481      FAIL;
5482    }
5483  else /* TARGET_THUMB */
5484    {
5485      if (   INTVAL (operands[3]) != 4
5486          || INTVAL (operands[2]) > 48)
5487        FAIL;
5488
5489      thumb_expand_movstrqi (operands);
5490      DONE;
5491    }
5492  "
5493)
5494
5495;; Thumb block-move insns
5496
5497(define_insn "movmem12b"
5498  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5499	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5500   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5501	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5502   (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5503	(mem:SI (plus:SI (match_dup 3) (const_int 8))))
5504   (set (match_operand:SI 0 "register_operand" "=l")
5505	(plus:SI (match_dup 2) (const_int 12)))
5506   (set (match_operand:SI 1 "register_operand" "=l")
5507	(plus:SI (match_dup 3) (const_int 12)))
5508   (clobber (match_scratch:SI 4 "=&l"))
5509   (clobber (match_scratch:SI 5 "=&l"))
5510   (clobber (match_scratch:SI 6 "=&l"))]
5511  "TARGET_THUMB"
5512  "* return thumb_output_move_mem_multiple (3, operands);"
5513  [(set_attr "length" "4")
5514   ; This isn't entirely accurate...  It loads as well, but in terms of
5515   ; scheduling the following insn it is better to consider it as a store
5516   (set_attr "type" "store3")]
5517)
5518
5519(define_insn "movmem8b"
5520  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5521	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5522   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5523	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5524   (set (match_operand:SI 0 "register_operand" "=l")
5525	(plus:SI (match_dup 2) (const_int 8)))
5526   (set (match_operand:SI 1 "register_operand" "=l")
5527	(plus:SI (match_dup 3) (const_int 8)))
5528   (clobber (match_scratch:SI 4 "=&l"))
5529   (clobber (match_scratch:SI 5 "=&l"))]
5530  "TARGET_THUMB"
5531  "* return thumb_output_move_mem_multiple (2, operands);"
5532  [(set_attr "length" "4")
5533   ; This isn't entirely accurate...  It loads as well, but in terms of
5534   ; scheduling the following insn it is better to consider it as a store
5535   (set_attr "type" "store2")]
5536)
5537
5538
5539
5540;; Compare & branch insns
5541;; The range calcualations are based as follows:
5542;; For forward branches, the address calculation returns the address of
5543;; the next instruction.  This is 2 beyond the branch instruction.
5544;; For backward branches, the address calculation returns the address of
5545;; the first instruction in this pattern (cmp).  This is 2 before the branch
5546;; instruction for the shortest sequence, and 4 before the branch instruction
5547;; if we have to jump around an unconditional branch.
5548;; To the basic branch range the PC offset must be added (this is +4).
5549;; So for forward branches we have 
5550;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5551;; And for backward branches we have 
5552;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5553;;
5554;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5555;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5556
5557(define_insn "cbranchsi4"
5558  [(set (pc)
5559	(if_then_else
5560	    (match_operator                    0 "arm_comparison_operator"
5561	                    [(match_operand:SI 1 "register_operand"   "l,r")
5562			     (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5563	    (label_ref       (match_operand    3 "" ""))
5564	    (pc)))]
5565  "TARGET_THUMB"
5566  "*
5567  output_asm_insn (\"cmp\\t%1, %2\", operands);
5568  switch (get_attr_length (insn))
5569    {
5570    case 4:  return \"b%d0\\t%l3\";
5571    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5572    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5573    }
5574  "
5575  [(set (attr "far_jump")
5576        (if_then_else
5577	    (eq_attr "length" "8")
5578	    (const_string "yes")
5579            (const_string "no")))
5580   (set (attr "length") 
5581        (if_then_else
5582	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5583	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5584	    (const_int 4)
5585	    (if_then_else
5586	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5587		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5588		(const_int 6)
5589		(const_int 8))))]
5590)
5591
5592(define_insn "*negated_cbranchsi4"
5593  [(set (pc)
5594	(if_then_else
5595	 (match_operator             0 "arm_comparison_operator"
5596	  [(match_operand:SI         1 "register_operand"  "l")
5597	   (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5598	 (label_ref (match_operand   3 "" ""))
5599	 (pc)))]
5600  "TARGET_THUMB"
5601  "*
5602  output_asm_insn (\"cmn\\t%1, %2\", operands);
5603  switch (get_attr_length (insn))
5604    {
5605    case 4:  return \"b%d0\\t%l3\";
5606    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5607    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5608    }
5609  "
5610  [(set (attr "far_jump")
5611        (if_then_else
5612	    (eq_attr "length" "8")
5613	    (const_string "yes")
5614            (const_string "no")))
5615   (set (attr "length") 
5616        (if_then_else
5617	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5618	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5619	    (const_int 4)
5620	    (if_then_else
5621	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5622		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5623		(const_int 6)
5624		(const_int 8))))]
5625)
5626
5627
5628;; Comparison and test insns
5629
5630(define_expand "cmpsi"
5631  [(match_operand:SI 0 "s_register_operand" "")
5632   (match_operand:SI 1 "arm_add_operand" "")]
5633  "TARGET_ARM"
5634  "{
5635    arm_compare_op0 = operands[0];
5636    arm_compare_op1 = operands[1];
5637    DONE;
5638  }"
5639)
5640
5641(define_expand "cmpsf"
5642  [(match_operand:SF 0 "s_register_operand" "")
5643   (match_operand:SF 1 "fpu_rhs_operand" "")]
5644  "TARGET_ARM && TARGET_HARD_FLOAT"
5645  "
5646  arm_compare_op0 = operands[0];
5647  arm_compare_op1 = operands[1];
5648  DONE;
5649  "
5650)
5651
5652(define_expand "cmpdf"
5653  [(match_operand:DF 0 "s_register_operand" "")
5654   (match_operand:DF 1 "fpu_rhs_operand" "")]
5655  "TARGET_ARM && TARGET_HARD_FLOAT"
5656  "
5657  arm_compare_op0 = operands[0];
5658  arm_compare_op1 = operands[1];
5659  DONE;
5660  "
5661)
5662
5663(define_expand "cmpxf"
5664  [(match_operand:XF 0 "s_register_operand" "")
5665   (match_operand:XF 1 "fpu_rhs_operand" "")]
5666  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5667  "
5668  arm_compare_op0 = operands[0];
5669  arm_compare_op1 = operands[1];
5670  DONE;
5671  "
5672)
5673
5674(define_insn "*arm_cmpsi_insn"
5675  [(set (reg:CC CC_REGNUM)
5676	(compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5677		    (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5678  "TARGET_ARM"
5679  "@
5680   cmp%?\\t%0, %1
5681   cmn%?\\t%0, #%n1"
5682  [(set_attr "conds" "set")]
5683)
5684
5685(define_insn "*cmpsi_shiftsi"
5686  [(set (reg:CC CC_REGNUM)
5687	(compare:CC (match_operand:SI   0 "s_register_operand" "r")
5688		    (match_operator:SI  3 "shift_operator"
5689		     [(match_operand:SI 1 "s_register_operand" "r")
5690		      (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5691  "TARGET_ARM"
5692  "cmp%?\\t%0, %1%S3"
5693  [(set_attr "conds" "set")
5694   (set_attr "shift" "1")
5695   ]
5696)
5697
5698(define_insn "*cmpsi_shiftsi_swp"
5699  [(set (reg:CC_SWP CC_REGNUM)
5700	(compare:CC_SWP (match_operator:SI 3 "shift_operator"
5701			 [(match_operand:SI 1 "s_register_operand" "r")
5702			  (match_operand:SI 2 "reg_or_int_operand" "rM")])
5703			(match_operand:SI 0 "s_register_operand" "r")))]
5704  "TARGET_ARM"
5705  "cmp%?\\t%0, %1%S3"
5706  [(set_attr "conds" "set")
5707   (set_attr "shift" "1")
5708   ]
5709)
5710
5711(define_insn "*cmpsi_neg_shiftsi"
5712  [(set (reg:CC CC_REGNUM)
5713	(compare:CC (match_operand:SI 0 "s_register_operand" "r")
5714		    (neg:SI (match_operator:SI 3 "shift_operator"
5715			     [(match_operand:SI 1 "s_register_operand" "r")
5716			      (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5717  "TARGET_ARM"
5718  "cmn%?\\t%0, %1%S3"
5719  [(set_attr "conds" "set")
5720   (set_attr "shift" "1")
5721   ]
5722)
5723
5724(define_insn "*cmpsf_insn"
5725  [(set (reg:CCFP CC_REGNUM)
5726	(compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5727		      (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5728  "TARGET_ARM && TARGET_HARD_FLOAT"
5729  "@
5730   cmf%?\\t%0, %1
5731   cnf%?\\t%0, #%N1"
5732  [(set_attr "conds" "set")
5733   (set_attr "type" "f_2_r")]
5734)
5735
5736(define_insn "*cmpdf_insn"
5737  [(set (reg:CCFP CC_REGNUM)
5738	(compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5739		      (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5740  "TARGET_ARM && TARGET_HARD_FLOAT"
5741  "@
5742   cmf%?\\t%0, %1
5743   cnf%?\\t%0, #%N1"
5744  [(set_attr "conds" "set")
5745   (set_attr "type" "f_2_r")]
5746)
5747
5748(define_insn "*cmpesfdf_df"
5749  [(set (reg:CCFP CC_REGNUM)
5750	(compare:CCFP (float_extend:DF
5751		       (match_operand:SF 0 "s_register_operand" "f,f"))
5752		      (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5753  "TARGET_ARM && TARGET_HARD_FLOAT"
5754  "@
5755   cmf%?\\t%0, %1
5756   cnf%?\\t%0, #%N1"
5757  [(set_attr "conds" "set")
5758   (set_attr "type" "f_2_r")]
5759)
5760
5761(define_insn "*cmpdf_esfdf"
5762  [(set (reg:CCFP CC_REGNUM)
5763	(compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5764		      (float_extend:DF
5765		       (match_operand:SF 1 "s_register_operand" "f"))))]
5766  "TARGET_ARM && TARGET_HARD_FLOAT"
5767  "cmf%?\\t%0, %1"
5768  [(set_attr "conds" "set")
5769   (set_attr "type" "f_2_r")]
5770)
5771
5772(define_insn "*cmpxf_insn"
5773  [(set (reg:CCFP CC_REGNUM)
5774	(compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5775		      (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5776  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5777  "@
5778   cmf%?\\t%0, %1
5779   cnf%?\\t%0, #%N1"
5780  [(set_attr "conds" "set")
5781   (set_attr "type" "f_2_r")]
5782)
5783
5784(define_insn "*cmpsf_trap"
5785  [(set (reg:CCFPE CC_REGNUM)
5786	(compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5787		       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5788  "TARGET_ARM && TARGET_HARD_FLOAT"
5789  "@
5790   cmf%?e\\t%0, %1
5791   cnf%?e\\t%0, #%N1"
5792  [(set_attr "conds" "set")
5793   (set_attr "type" "f_2_r")]
5794)
5795
5796(define_insn "*cmpdf_trap"
5797  [(set (reg:CCFPE CC_REGNUM)
5798	(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5799		       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5800  "TARGET_ARM && TARGET_HARD_FLOAT"
5801  "@
5802   cmf%?e\\t%0, %1
5803   cnf%?e\\t%0, #%N1"
5804  [(set_attr "conds" "set")
5805   (set_attr "type" "f_2_r")]
5806)
5807
5808(define_insn "*cmp_esfdf_df_trap"
5809  [(set (reg:CCFPE CC_REGNUM)
5810	(compare:CCFPE (float_extend:DF
5811			(match_operand:SF 0 "s_register_operand" "f,f"))
5812		       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5813  "TARGET_ARM && TARGET_HARD_FLOAT"
5814  "@
5815   cmf%?e\\t%0, %1
5816   cnf%?e\\t%0, #%N1"
5817  [(set_attr "conds" "set")
5818   (set_attr "type" "f_2_r")]
5819)
5820
5821(define_insn "*cmp_df_esfdf_trap"
5822  [(set (reg:CCFPE CC_REGNUM)
5823	(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5824		       (float_extend:DF
5825			(match_operand:SF 1 "s_register_operand" "f"))))]
5826  "TARGET_ARM && TARGET_HARD_FLOAT"
5827  "cmf%?e\\t%0, %1"
5828  [(set_attr "conds" "set")
5829   (set_attr "type" "f_2_r")]
5830)
5831
5832(define_insn "*cmpxf_trap"
5833  [(set (reg:CCFPE CC_REGNUM)
5834	(compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5835		       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5836  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5837  "@
5838   cmf%?e\\t%0, %1
5839   cnf%?e\\t%0, #%N1"
5840  [(set_attr "conds" "set")
5841   (set_attr "type" "f_2_r")]
5842)
5843
5844; This insn allows redundant compares to be removed by cse, nothing should
5845; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5846; is deleted later on. The match_dup will match the mode here, so that
5847; mode changes of the condition codes aren't lost by this even though we don't
5848; specify what they are.
5849
5850(define_insn "*deleted_compare"
5851  [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5852  "TARGET_ARM"
5853  "\\t%@ deleted compare"
5854  [(set_attr "conds" "set")
5855   (set_attr "length" "0")]
5856)
5857
5858
5859;; Conditional branch insns
5860
5861(define_expand "beq"
5862  [(set (pc)
5863	(if_then_else (eq (match_dup 1) (const_int 0))
5864		      (label_ref (match_operand 0 "" ""))
5865		      (pc)))]
5866  "TARGET_ARM"
5867  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5868)
5869
5870(define_expand "bne"
5871  [(set (pc)
5872	(if_then_else (ne (match_dup 1) (const_int 0))
5873		      (label_ref (match_operand 0 "" ""))
5874		      (pc)))]
5875  "TARGET_ARM"
5876  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5877)
5878
5879(define_expand "bgt"
5880  [(set (pc)
5881	(if_then_else (gt (match_dup 1) (const_int 0))
5882		      (label_ref (match_operand 0 "" ""))
5883		      (pc)))]
5884  "TARGET_ARM"
5885  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5886)
5887
5888(define_expand "ble"
5889  [(set (pc)
5890	(if_then_else (le (match_dup 1) (const_int 0))
5891		      (label_ref (match_operand 0 "" ""))
5892		      (pc)))]
5893  "TARGET_ARM"
5894  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5895)
5896
5897(define_expand "bge"
5898  [(set (pc)
5899	(if_then_else (ge (match_dup 1) (const_int 0))
5900		      (label_ref (match_operand 0 "" ""))
5901		      (pc)))]
5902  "TARGET_ARM"
5903  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5904)
5905
5906(define_expand "blt"
5907  [(set (pc)
5908	(if_then_else (lt (match_dup 1) (const_int 0))
5909		      (label_ref (match_operand 0 "" ""))
5910		      (pc)))]
5911  "TARGET_ARM"
5912  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5913)
5914
5915(define_expand "bgtu"
5916  [(set (pc)
5917	(if_then_else (gtu (match_dup 1) (const_int 0))
5918		      (label_ref (match_operand 0 "" ""))
5919		      (pc)))]
5920  "TARGET_ARM"
5921  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5922)
5923
5924(define_expand "bleu"
5925  [(set (pc)
5926	(if_then_else (leu (match_dup 1) (const_int 0))
5927		      (label_ref (match_operand 0 "" ""))
5928		      (pc)))]
5929  "TARGET_ARM"
5930  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5931)
5932
5933(define_expand "bgeu"
5934  [(set (pc)
5935	(if_then_else (geu (match_dup 1) (const_int 0))
5936		      (label_ref (match_operand 0 "" ""))
5937		      (pc)))]
5938  "TARGET_ARM"
5939  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5940)
5941
5942(define_expand "bltu"
5943  [(set (pc)
5944	(if_then_else (ltu (match_dup 1) (const_int 0))
5945		      (label_ref (match_operand 0 "" ""))
5946		      (pc)))]
5947  "TARGET_ARM"
5948  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5949)
5950
5951(define_expand "bunordered"
5952  [(set (pc)
5953	(if_then_else (unordered (match_dup 1) (const_int 0))
5954		      (label_ref (match_operand 0 "" ""))
5955		      (pc)))]
5956  "TARGET_ARM && TARGET_HARD_FLOAT"
5957  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5958				      arm_compare_op1);"
5959)
5960
5961(define_expand "bordered"
5962  [(set (pc)
5963	(if_then_else (ordered (match_dup 1) (const_int 0))
5964		      (label_ref (match_operand 0 "" ""))
5965		      (pc)))]
5966  "TARGET_ARM && TARGET_HARD_FLOAT"
5967  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5968				      arm_compare_op1);"
5969)
5970
5971(define_expand "bungt"
5972  [(set (pc)
5973	(if_then_else (ungt (match_dup 1) (const_int 0))
5974		      (label_ref (match_operand 0 "" ""))
5975		      (pc)))]
5976  "TARGET_ARM && TARGET_HARD_FLOAT"
5977  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5978)
5979
5980(define_expand "bunlt"
5981  [(set (pc)
5982	(if_then_else (unlt (match_dup 1) (const_int 0))
5983		      (label_ref (match_operand 0 "" ""))
5984		      (pc)))]
5985  "TARGET_ARM && TARGET_HARD_FLOAT"
5986  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5987)
5988
5989(define_expand "bunge"
5990  [(set (pc)
5991	(if_then_else (unge (match_dup 1) (const_int 0))
5992		      (label_ref (match_operand 0 "" ""))
5993		      (pc)))]
5994  "TARGET_ARM && TARGET_HARD_FLOAT"
5995  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5996)
5997
5998(define_expand "bunle"
5999  [(set (pc)
6000	(if_then_else (unle (match_dup 1) (const_int 0))
6001		      (label_ref (match_operand 0 "" ""))
6002		      (pc)))]
6003  "TARGET_ARM && TARGET_HARD_FLOAT"
6004  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6005)
6006
6007;; The following two patterns need two branch instructions, since there is
6008;; no single instruction that will handle all cases.
6009(define_expand "buneq"
6010  [(set (pc)
6011	(if_then_else (uneq (match_dup 1) (const_int 0))
6012		      (label_ref (match_operand 0 "" ""))
6013		      (pc)))]
6014  "TARGET_ARM && TARGET_HARD_FLOAT"
6015  "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6016)
6017
6018(define_expand "bltgt"
6019  [(set (pc)
6020	(if_then_else (ltgt (match_dup 1) (const_int 0))
6021		      (label_ref (match_operand 0 "" ""))
6022		      (pc)))]
6023  "TARGET_ARM && TARGET_HARD_FLOAT"
6024  "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6025)
6026
6027;;
6028;; Patterns to match conditional branch insns.
6029;;
6030
6031; Special pattern to match UNEQ.
6032(define_insn "*arm_buneq"
6033  [(set (pc)
6034	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6035		      (label_ref (match_operand 0 "" ""))
6036		      (pc)))]
6037  "TARGET_ARM && TARGET_HARD_FLOAT"
6038  "*
6039  if (arm_ccfsm_state != 0)
6040    abort ();
6041
6042  return \"bvs\\t%l0\;beq\\t%l0\";
6043  "
6044  [(set_attr "conds" "jump_clob")
6045   (set_attr "length" "8")]
6046)
6047
6048; Special pattern to match LTGT.
6049(define_insn "*arm_bltgt"
6050  [(set (pc)
6051	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6052		      (label_ref (match_operand 0 "" ""))
6053		      (pc)))]
6054  "TARGET_ARM && TARGET_HARD_FLOAT"
6055  "*
6056  if (arm_ccfsm_state != 0)
6057    abort ();
6058
6059  return \"bmi\\t%l0\;bgt\\t%l0\";
6060  "
6061  [(set_attr "conds" "jump_clob")
6062   (set_attr "length" "8")]
6063)
6064
6065(define_insn "*arm_cond_branch"
6066  [(set (pc)
6067	(if_then_else (match_operator 1 "arm_comparison_operator"
6068		       [(match_operand 2 "cc_register" "") (const_int 0)])
6069		      (label_ref (match_operand 0 "" ""))
6070		      (pc)))]
6071  "TARGET_ARM"
6072  "*
6073  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6074    {
6075      arm_ccfsm_state += 2;
6076      return \"\";
6077    }
6078  return \"b%d1\\t%l0\";
6079  "
6080  [(set_attr "conds" "use")]
6081)
6082
6083; Special pattern to match reversed UNEQ.
6084(define_insn "*arm_buneq_reversed"
6085  [(set (pc)
6086	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6087		      (pc)
6088		      (label_ref (match_operand 0 "" ""))))]
6089  "TARGET_ARM && TARGET_HARD_FLOAT"
6090  "*
6091  if (arm_ccfsm_state != 0)
6092    abort ();
6093
6094  return \"bmi\\t%l0\;bgt\\t%l0\";
6095  "
6096  [(set_attr "conds" "jump_clob")
6097   (set_attr "length" "8")]
6098)
6099
6100; Special pattern to match reversed LTGT.
6101(define_insn "*arm_bltgt_reversed"
6102  [(set (pc)
6103	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6104		      (pc)
6105		      (label_ref (match_operand 0 "" ""))))]
6106  "TARGET_ARM && TARGET_HARD_FLOAT"
6107  "*
6108  if (arm_ccfsm_state != 0)
6109    abort ();
6110
6111  return \"bvs\\t%l0\;beq\\t%l0\";
6112  "
6113  [(set_attr "conds" "jump_clob")
6114   (set_attr "length" "8")]
6115)
6116
6117(define_insn "*arm_cond_branch_reversed"
6118  [(set (pc)
6119	(if_then_else (match_operator 1 "arm_comparison_operator"
6120		       [(match_operand 2 "cc_register" "") (const_int 0)])
6121		      (pc)
6122		      (label_ref (match_operand 0 "" ""))))]
6123  "TARGET_ARM"
6124  "*
6125  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6126    {
6127      arm_ccfsm_state += 2;
6128      return \"\";
6129    }
6130  return \"b%D1\\t%l0\";
6131  "
6132  [(set_attr "conds" "use")]
6133)
6134
6135
6136
6137; scc insns
6138
6139(define_expand "seq"
6140  [(set (match_operand:SI 0 "s_register_operand" "=r")
6141	(eq:SI (match_dup 1) (const_int 0)))]
6142  "TARGET_ARM"
6143  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6144)
6145
6146(define_expand "sne"
6147  [(set (match_operand:SI 0 "s_register_operand" "=r")
6148	(ne:SI (match_dup 1) (const_int 0)))]
6149  "TARGET_ARM"
6150  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6151)
6152
6153(define_expand "sgt"
6154  [(set (match_operand:SI 0 "s_register_operand" "=r")
6155	(gt:SI (match_dup 1) (const_int 0)))]
6156  "TARGET_ARM"
6157  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6158)
6159
6160(define_expand "sle"
6161  [(set (match_operand:SI 0 "s_register_operand" "=r")
6162	(le:SI (match_dup 1) (const_int 0)))]
6163  "TARGET_ARM"
6164  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6165)
6166
6167(define_expand "sge"
6168  [(set (match_operand:SI 0 "s_register_operand" "=r")
6169	(ge:SI (match_dup 1) (const_int 0)))]
6170  "TARGET_ARM"
6171  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6172)
6173
6174(define_expand "slt"
6175  [(set (match_operand:SI 0 "s_register_operand" "=r")
6176	(lt:SI (match_dup 1) (const_int 0)))]
6177  "TARGET_ARM"
6178  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6179)
6180
6181(define_expand "sgtu"
6182  [(set (match_operand:SI 0 "s_register_operand" "=r")
6183	(gtu:SI (match_dup 1) (const_int 0)))]
6184  "TARGET_ARM"
6185  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6186)
6187
6188(define_expand "sleu"
6189  [(set (match_operand:SI 0 "s_register_operand" "=r")
6190	(leu:SI (match_dup 1) (const_int 0)))]
6191  "TARGET_ARM"
6192  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6193)
6194
6195(define_expand "sgeu"
6196  [(set (match_operand:SI 0 "s_register_operand" "=r")
6197	(geu:SI (match_dup 1) (const_int 0)))]
6198  "TARGET_ARM"
6199  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6200)
6201
6202(define_expand "sltu"
6203  [(set (match_operand:SI 0 "s_register_operand" "=r")
6204	(ltu:SI (match_dup 1) (const_int 0)))]
6205  "TARGET_ARM"
6206  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6207)
6208
6209(define_expand "sunordered"
6210  [(set (match_operand:SI 0 "s_register_operand" "=r")
6211	(unordered:SI (match_dup 1) (const_int 0)))]
6212  "TARGET_ARM && TARGET_HARD_FLOAT"
6213  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6214				      arm_compare_op1);"
6215)
6216
6217(define_expand "sordered"
6218  [(set (match_operand:SI 0 "s_register_operand" "=r")
6219	(ordered:SI (match_dup 1) (const_int 0)))]
6220  "TARGET_ARM && TARGET_HARD_FLOAT"
6221  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6222				      arm_compare_op1);"
6223)
6224
6225(define_expand "sungt"
6226  [(set (match_operand:SI 0 "s_register_operand" "=r")
6227	(ungt:SI (match_dup 1) (const_int 0)))]
6228  "TARGET_ARM && TARGET_HARD_FLOAT"
6229  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6230				      arm_compare_op1);"
6231)
6232
6233(define_expand "sunge"
6234  [(set (match_operand:SI 0 "s_register_operand" "=r")
6235	(unge:SI (match_dup 1) (const_int 0)))]
6236  "TARGET_ARM && TARGET_HARD_FLOAT"
6237  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6238				      arm_compare_op1);"
6239)
6240
6241(define_expand "sunlt"
6242  [(set (match_operand:SI 0 "s_register_operand" "=r")
6243	(unlt:SI (match_dup 1) (const_int 0)))]
6244  "TARGET_ARM && TARGET_HARD_FLOAT"
6245  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6246				      arm_compare_op1);"
6247)
6248
6249(define_expand "sunle"
6250  [(set (match_operand:SI 0 "s_register_operand" "=r")
6251	(unle:SI (match_dup 1) (const_int 0)))]
6252  "TARGET_ARM && TARGET_HARD_FLOAT"
6253  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6254				      arm_compare_op1);"
6255)
6256
6257;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6258;;; simple ARM instructions. 
6259;
6260; (define_expand "suneq"
6261;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6262; 	(uneq:SI (match_dup 1) (const_int 0)))]
6263;   "TARGET_ARM && TARGET_HARD_FLOAT"
6264;   "abort ();"
6265; )
6266;
6267; (define_expand "sltgt"
6268;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6269; 	(ltgt:SI (match_dup 1) (const_int 0)))]
6270;   "TARGET_ARM && TARGET_HARD_FLOAT"
6271;   "abort ();"
6272; )
6273
6274(define_insn "*mov_scc"
6275  [(set (match_operand:SI 0 "s_register_operand" "=r")
6276	(match_operator:SI 1 "arm_comparison_operator"
6277	 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6278  "TARGET_ARM"
6279  "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6280  [(set_attr "conds" "use")
6281   (set_attr "length" "8")]
6282)
6283
6284(define_insn "*mov_negscc"
6285  [(set (match_operand:SI 0 "s_register_operand" "=r")
6286	(neg:SI (match_operator:SI 1 "arm_comparison_operator"
6287		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6288  "TARGET_ARM"
6289  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6290  [(set_attr "conds" "use")
6291   (set_attr "length" "8")]
6292)
6293
6294(define_insn "*mov_notscc"
6295  [(set (match_operand:SI 0 "s_register_operand" "=r")
6296	(not:SI (match_operator:SI 1 "arm_comparison_operator"
6297		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6298  "TARGET_ARM"
6299  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6300  [(set_attr "conds" "use")
6301   (set_attr "length" "8")]
6302)
6303
6304
6305;; Conditional move insns
6306
6307(define_expand "movsicc"
6308  [(set (match_operand:SI 0 "s_register_operand" "")
6309	(if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6310			 (match_operand:SI 2 "arm_not_operand" "")
6311			 (match_operand:SI 3 "arm_not_operand" "")))]
6312  "TARGET_ARM"
6313  "
6314  {
6315    enum rtx_code code = GET_CODE (operands[1]);
6316    rtx ccreg;
6317
6318    if (code == UNEQ || code == LTGT)
6319      FAIL;
6320
6321    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6322    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6323  }"
6324)
6325
6326(define_expand "movsfcc"
6327  [(set (match_operand:SF 0 "s_register_operand" "")
6328	(if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6329			 (match_operand:SF 2 "s_register_operand" "")
6330			 (match_operand:SF 3 "nonmemory_operand" "")))]
6331  "TARGET_ARM"
6332  "
6333  {
6334    enum rtx_code code = GET_CODE (operands[1]);
6335    rtx ccreg;
6336
6337    if (code == UNEQ || code == LTGT)
6338      FAIL;
6339
6340    /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6341       Otherwise, ensure it is a valid FP add operand */
6342    if ((!TARGET_HARD_FLOAT)
6343        || (!fpu_add_operand (operands[3], SFmode)))
6344      operands[3] = force_reg (SFmode, operands[3]);
6345
6346    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6347    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6348  }"
6349)
6350
6351(define_expand "movdfcc"
6352  [(set (match_operand:DF 0 "s_register_operand" "")
6353	(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6354			 (match_operand:DF 2 "s_register_operand" "")
6355			 (match_operand:DF 3 "fpu_add_operand" "")))]
6356  "TARGET_ARM && TARGET_HARD_FLOAT"
6357  "
6358  {
6359    enum rtx_code code = GET_CODE (operands[1]);
6360    rtx ccreg;
6361
6362    if (code == UNEQ || code == LTGT)
6363      FAIL;
6364
6365    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6366    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6367  }"
6368)
6369
6370(define_insn "*movsicc_insn"
6371  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6372	(if_then_else:SI
6373	 (match_operator 3 "arm_comparison_operator"
6374	  [(match_operand 4 "cc_register" "") (const_int 0)])
6375	 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6376	 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6377  "TARGET_ARM"
6378  "@
6379   mov%D3\\t%0, %2
6380   mvn%D3\\t%0, #%B2
6381   mov%d3\\t%0, %1
6382   mvn%d3\\t%0, #%B1
6383   mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6384   mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6385   mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6386   mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6387  [(set_attr "length" "4,4,4,4,8,8,8,8")
6388   (set_attr "conds" "use")]
6389)
6390
6391(define_insn "*movsfcc_hard_insn"
6392  [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6393	(if_then_else:SF
6394	 (match_operator 3 "arm_comparison_operator" 
6395	  [(match_operand 4 "cc_register" "") (const_int 0)])
6396	 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6397	 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6398  "TARGET_ARM && TARGET_HARD_FLOAT"
6399  "@
6400   mvf%D3s\\t%0, %2
6401   mnf%D3s\\t%0, #%N2
6402   mvf%d3s\\t%0, %1
6403   mnf%d3s\\t%0, #%N1
6404   mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6405   mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6406   mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6407   mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6408  [(set_attr "length" "4,4,4,4,8,8,8,8")
6409   (set_attr "type" "ffarith")
6410   (set_attr "conds" "use")]
6411)
6412
6413(define_insn "*movsfcc_soft_insn"
6414  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6415	(if_then_else:SF (match_operator 3 "arm_comparison_operator"
6416			  [(match_operand 4 "cc_register" "") (const_int 0)])
6417			 (match_operand:SF 1 "s_register_operand" "0,r")
6418			 (match_operand:SF 2 "s_register_operand" "r,0")))]
6419  "TARGET_ARM && TARGET_SOFT_FLOAT"
6420  "@
6421   mov%D3\\t%0, %2
6422   mov%d3\\t%0, %1"
6423  [(set_attr "conds" "use")]
6424)
6425
6426(define_insn "*movdfcc_insn"
6427  [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6428	(if_then_else:DF
6429	 (match_operator 3 "arm_comparison_operator"
6430	  [(match_operand 4 "cc_register" "") (const_int 0)])
6431	 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6432	 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6433  "TARGET_ARM && TARGET_HARD_FLOAT"
6434  "@
6435   mvf%D3d\\t%0, %2
6436   mnf%D3d\\t%0, #%N2
6437   mvf%d3d\\t%0, %1
6438   mnf%d3d\\t%0, #%N1
6439   mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6440   mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6441   mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6442   mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6443  [(set_attr "length" "4,4,4,4,8,8,8,8")
6444   (set_attr "type" "ffarith")
6445   (set_attr "conds" "use")]
6446)
6447
6448
6449;; Jump and linkage insns
6450
6451(define_expand "jump"
6452  [(set (pc)
6453	(label_ref (match_operand 0 "" "")))]
6454  "TARGET_EITHER"
6455  ""
6456)
6457
6458(define_insn "*arm_jump"
6459  [(set (pc)
6460	(label_ref (match_operand 0 "" "")))]
6461  "TARGET_ARM"
6462  "*
6463  {
6464    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6465      {
6466        arm_ccfsm_state += 2;
6467        return \"\";
6468      }
6469    return \"b%?\\t%l0\";
6470  }
6471  "
6472  [(set_attr "predicable" "yes")]
6473)
6474
6475(define_insn "*thumb_jump"
6476  [(set (pc)
6477	(label_ref (match_operand 0 "" "")))]
6478  "TARGET_THUMB"
6479  "*
6480  if (get_attr_length (insn) == 2)
6481    return \"b\\t%l0\";
6482  return \"bl\\t%l0\\t%@ far jump\";
6483  "
6484  [(set (attr "far_jump")
6485        (if_then_else
6486	    (eq_attr "length" "4")
6487	    (const_string "yes")
6488	    (const_string "no")))
6489   (set (attr "length") 
6490        (if_then_else
6491	    (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6492		 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6493  	    (const_int 2)
6494	    (const_int 4)))]
6495)
6496
6497(define_expand "call"
6498  [(parallel [(call (match_operand 0 "memory_operand" "")
6499	            (match_operand 1 "general_operand" ""))
6500	      (use (match_operand 2 "" ""))
6501	      (clobber (reg:SI LR_REGNUM))])]
6502  "TARGET_EITHER"
6503  "
6504  {
6505    rtx callee;
6506    
6507    /* In an untyped call, we can get NULL for operand 2.  */
6508    if (operands[2] == NULL_RTX)
6509      operands[2] = const0_rtx;
6510      
6511    /* This is to decide if we should generate indirect calls by loading the
6512       32 bit address of the callee into a register before performing the
6513       branch and link.  operand[2] encodes the long_call/short_call
6514       attribute of the function being called.  This attribute is set whenever
6515       __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6516       is used, and the short_call attribute can also be set if function is
6517       declared as static or if it has already been defined in the current
6518       compilation unit.  See arm.c and arm.h for info about this.  The third
6519       parameter to arm_is_longcall_p is used to tell it which pattern
6520       invoked it.  */
6521    callee  = XEXP (operands[0], 0);
6522    
6523    if (GET_CODE (callee) != REG
6524       && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6525      XEXP (operands[0], 0) = force_reg (Pmode, callee);
6526  }"
6527)
6528
6529(define_insn "*call_reg"
6530  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6531         (match_operand 1 "" ""))
6532   (use (match_operand 2 "" ""))
6533   (clobber (reg:SI LR_REGNUM))]
6534  "TARGET_ARM"
6535  "*
6536  return output_call (operands);
6537  "
6538  ;; length is worst case, normally it is only two
6539  [(set_attr "length" "12")
6540   (set_attr "type" "call")]
6541)
6542
6543(define_insn "*call_mem"
6544  [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6545	 (match_operand 1 "" ""))
6546   (use (match_operand 2 "" ""))
6547   (clobber (reg:SI LR_REGNUM))]
6548  "TARGET_ARM"
6549  "*
6550  return output_call_mem (operands);
6551  "
6552  [(set_attr "length" "12")
6553   (set_attr "type" "call")]
6554)
6555
6556(define_insn "*call_indirect"
6557  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6558	 (match_operand 1 "" ""))
6559   (use (match_operand 2 "" ""))
6560   (clobber (reg:SI LR_REGNUM))]
6561  "TARGET_THUMB"
6562  "*
6563  {
6564    if (TARGET_CALLER_INTERWORKING)
6565      return \"bl\\t%__interwork_call_via_%0\";
6566    else
6567      return \"bl\\t%__call_via_%0\";
6568  }"
6569  [(set_attr "type" "call")]
6570)
6571
6572(define_insn "*call_value_indirect"
6573  [(set (match_operand 0 "" "=l")
6574	(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6575	      (match_operand 2 "" "")))
6576   (use (match_operand 3 "" ""))
6577   (clobber (reg:SI LR_REGNUM))]
6578  "TARGET_THUMB"
6579  "*
6580  {
6581    if (TARGET_CALLER_INTERWORKING)
6582      return \"bl\\t%__interwork_call_via_%1\";
6583    else
6584      return \"bl\\t%__call_via_%1\";
6585  }"
6586  [(set_attr "type" "call")]
6587)
6588
6589(define_expand "call_value"
6590  [(parallel [(set (match_operand       0 "" "")
6591	           (call (match_operand 1 "memory_operand" "")
6592		         (match_operand 2 "general_operand" "")))
6593	      (use (match_operand 3 "" ""))
6594	      (clobber (reg:SI LR_REGNUM))])]
6595  "TARGET_EITHER"
6596  "
6597  {
6598    rtx callee = XEXP (operands[1], 0);
6599    
6600    /* In an untyped call, we can get NULL for operand 2.  */
6601    if (operands[3] == 0)
6602      operands[3] = const0_rtx;
6603      
6604    /* See the comment in define_expand \"call\".  */
6605    if (GET_CODE (callee) != REG
6606	&& arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6607      XEXP (operands[1], 0) = force_reg (Pmode, callee);
6608  }"
6609)
6610
6611(define_insn "*call_value_reg"
6612  [(set (match_operand 0 "" "=r,f")
6613        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6614	      (match_operand 2 "" "")))
6615   (use (match_operand 3 "" ""))
6616   (clobber (reg:SI LR_REGNUM))]
6617  "TARGET_ARM"
6618  "*
6619  return output_call (&operands[1]);
6620  "
6621  [(set_attr "length" "12")
6622   (set_attr "type" "call")]
6623)
6624
6625(define_insn "*call_value_mem"
6626  [(set (match_operand 0 "" "=r,f")
6627	(call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6628	      (match_operand 2 "" "")))
6629   (use (match_operand 3 "" ""))
6630   (clobber (reg:SI LR_REGNUM))]
6631  "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6632  "*
6633  return output_call_mem (&operands[1]);
6634  "
6635  [(set_attr "length" "12")
6636   (set_attr "type" "call")]
6637)
6638
6639;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6640;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6641
6642(define_insn "*call_symbol"
6643  [(call (mem:SI (match_operand:SI 0 "" "X"))
6644	 (match_operand 1 "" ""))
6645   (use (match_operand 2 "" ""))
6646   (clobber (reg:SI LR_REGNUM))]
6647  "TARGET_ARM
6648   && (GET_CODE (operands[0]) == SYMBOL_REF)
6649   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6650  "*
6651  {
6652    return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6653  }"
6654  [(set_attr "type" "call")]
6655)
6656
6657(define_insn "*call_value_symbol"
6658  [(set (match_operand 0 "s_register_operand" "=r,f")
6659	(call (mem:SI (match_operand:SI 1 "" "X,X"))
6660	(match_operand:SI 2 "" "")))
6661   (use (match_operand 3 "" ""))
6662   (clobber (reg:SI LR_REGNUM))]
6663  "TARGET_ARM
6664   && (GET_CODE (operands[1]) == SYMBOL_REF)
6665   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6666  "*
6667  {
6668    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6669  }"
6670  [(set_attr "type" "call")]
6671)
6672
6673(define_insn "*call_insn"
6674  [(call (mem:SI (match_operand:SI 0 "" "X"))
6675	 (match_operand:SI 1 "" ""))
6676   (use (match_operand 2 "" ""))
6677   (clobber (reg:SI LR_REGNUM))]
6678  "TARGET_THUMB
6679   && GET_CODE (operands[0]) == SYMBOL_REF
6680   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6681  "bl\\t%a0"
6682  [(set_attr "length" "4")
6683   (set_attr "type" "call")]
6684)
6685
6686(define_insn "*call_value_insn"
6687  [(set (match_operand 0 "register_operand" "=l")
6688	(call (mem:SI (match_operand 1 "" "X"))
6689	      (match_operand 2 "" "")))
6690   (use (match_operand 3 "" ""))
6691   (clobber (reg:SI LR_REGNUM))]
6692  "TARGET_THUMB
6693   && GET_CODE (operands[1]) == SYMBOL_REF
6694   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6695  "bl\\t%a1"
6696  [(set_attr "length" "4")
6697   (set_attr "type" "call")]
6698)
6699
6700;; We may also be able to do sibcalls for Thumb, but it's much harder...
6701(define_expand "sibcall"
6702  [(parallel [(call (match_operand 0 "memory_operand" "")
6703		    (match_operand 1 "general_operand" ""))
6704	      (return)
6705	      (use (match_operand 2 "" ""))])]
6706  "TARGET_ARM"
6707  "
6708  {
6709    if (operands[2] == NULL_RTX)
6710      operands[2] = const0_rtx;
6711  }"
6712)
6713
6714(define_expand "sibcall_value"
6715  [(parallel [(set (match_operand 0 "register_operand" "")
6716		   (call (match_operand 1 "memory_operand" "")
6717			 (match_operand 2 "general_operand" "")))
6718	      (return)
6719	      (use (match_operand 3 "" ""))])]
6720  "TARGET_ARM"
6721  "
6722  {
6723    if (operands[3] == NULL_RTX)
6724      operands[3] = const0_rtx;
6725  }"
6726)
6727
6728(define_insn "*sibcall_insn"
6729 [(call (mem:SI (match_operand:SI 0 "" "X"))
6730	(match_operand 1 "" ""))
6731  (return)
6732  (use (match_operand 2 "" ""))]
6733  "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6734  "*
6735  return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6736  "
6737  [(set_attr "type" "call")]
6738)
6739
6740(define_insn "*sibcall_value_insn"
6741 [(set (match_operand 0 "s_register_operand" "=r,f")
6742       (call (mem:SI (match_operand:SI 1 "" "X,X"))
6743	     (match_operand 2 "" "")))
6744  (return)
6745  (use (match_operand 3 "" ""))]
6746  "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6747  "*
6748  return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6749  "
6750  [(set_attr "type" "call")]
6751)
6752
6753;; Often the return insn will be the same as loading from memory, so set attr
6754(define_insn "return"
6755  [(return)]
6756  "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6757  "*
6758  {
6759    if (arm_ccfsm_state == 2)
6760      {
6761        arm_ccfsm_state += 2;
6762        return \"\";
6763      }
6764    return output_return_instruction (const_true_rtx, TRUE, FALSE);
6765  }"
6766  [(set_attr "type" "load")
6767   (set_attr "predicable" "yes")]
6768)
6769
6770(define_insn "*cond_return"
6771  [(set (pc)
6772        (if_then_else (match_operator 0 "arm_comparison_operator"
6773		       [(match_operand 1 "cc_register" "") (const_int 0)])
6774                      (return)
6775                      (pc)))]
6776  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6777  "*
6778  {
6779    if (arm_ccfsm_state == 2)
6780      {
6781        arm_ccfsm_state += 2;
6782        return \"\";
6783      }
6784    return output_return_instruction (operands[0], TRUE, FALSE);
6785  }"
6786  [(set_attr "conds" "use")
6787   (set_attr "type" "load")]
6788)
6789
6790(define_insn "*cond_return_inverted"
6791  [(set (pc)
6792        (if_then_else (match_operator 0 "arm_comparison_operator"
6793		       [(match_operand 1 "cc_register" "") (const_int 0)])
6794                      (pc)
6795		      (return)))]
6796  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6797  "*
6798  {
6799    if (arm_ccfsm_state == 2)
6800      {
6801        arm_ccfsm_state += 2;
6802        return \"\";
6803      }
6804    return output_return_instruction (operands[0], TRUE, TRUE);
6805  }"
6806  [(set_attr "conds" "use")
6807   (set_attr "type" "load")]
6808)
6809
6810;; Generate a sequence of instructions to determine if the processor is
6811;; in 26-bit or 32-bit mode, and return the appropriate return address
6812;; mask.
6813
6814(define_expand "return_addr_mask"
6815  [(set (match_dup 1)
6816      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6817		       (const_int 0)))
6818   (set (match_operand:SI 0 "s_register_operand" "")
6819      (if_then_else:SI (eq (match_dup 1) (const_int 0))
6820		       (const_int -1)
6821		       (const_int 67108860)))] ; 0x03fffffc
6822  "TARGET_ARM"
6823  "
6824  operands[1] = gen_rtx_REG (CC_NOOVmode, 24);
6825  ")
6826
6827(define_insn "*check_arch2"
6828  [(set (match_operand:CC_NOOV 0 "cc_register" "")
6829      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6830		       (const_int 0)))]
6831  "TARGET_ARM"
6832  "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6833  [(set_attr "length" "8")
6834   (set_attr "conds" "set")]
6835)
6836
6837;; Call subroutine returning any type.
6838
6839(define_expand "untyped_call"
6840  [(parallel [(call (match_operand 0 "" "")
6841		    (const_int 0))
6842	      (match_operand 1 "" "")
6843	      (match_operand 2 "" "")])]
6844  "TARGET_ARM"
6845  "
6846  {
6847    int i;
6848
6849    emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6850
6851    for (i = 0; i < XVECLEN (operands[2], 0); i++)
6852      {
6853	rtx set = XVECEXP (operands[2], 0, i);
6854
6855	emit_move_insn (SET_DEST (set), SET_SRC (set));
6856      }
6857
6858    /* The optimizer does not know that the call sets the function value
6859       registers we stored in the result block.  We avoid problems by
6860       claiming that all hard registers are used and clobbered at this
6861       point.  */
6862    emit_insn (gen_blockage ());
6863
6864    DONE;
6865  }"
6866)
6867
6868;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6869;; all of memory.  This blocks insns from being moved across this point.
6870
6871(define_insn "blockage"
6872  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6873  "TARGET_EITHER"
6874  ""
6875  [(set_attr "length" "0")
6876   (set_attr "type" "block")]
6877)
6878
6879(define_expand "casesi"
6880  [(match_operand:SI 0 "s_register_operand" "")	; index to jump on
6881   (match_operand:SI 1 "const_int_operand" "")	; lower bound
6882   (match_operand:SI 2 "const_int_operand" "")	; total range
6883   (match_operand:SI 3 "" "")			; table label
6884   (match_operand:SI 4 "" "")]			; Out of range label
6885  "TARGET_ARM"
6886  "
6887  {
6888    rtx reg;
6889    if (operands[1] != const0_rtx)
6890      {
6891	reg = gen_reg_rtx (SImode);
6892
6893	emit_insn (gen_addsi3 (reg, operands[0],
6894			       GEN_INT (-INTVAL (operands[1]))));
6895	operands[0] = reg;
6896      }
6897
6898    if (!const_ok_for_arm (INTVAL (operands[2])))
6899      operands[2] = force_reg (SImode, operands[2]);
6900
6901    emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6902					 operands[4]));
6903    DONE;
6904  }"
6905)
6906
6907;; The USE in this pattern is needed to tell flow analysis that this is
6908;; a CASESI insn.  It has no other purpose.
6909(define_insn "casesi_internal"
6910  [(parallel [(set (pc)
6911	       (if_then_else
6912		(leu (match_operand:SI 0 "s_register_operand" "r")
6913		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
6914		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6915				 (label_ref (match_operand 2 "" ""))))
6916		(label_ref (match_operand 3 "" ""))))
6917	      (clobber (reg:CC CC_REGNUM))
6918	      (use (label_ref (match_dup 2)))])]
6919  "TARGET_ARM"
6920  "*
6921    if (flag_pic)
6922      return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6923    return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6924  "
6925  [(set_attr "conds" "clob")
6926   (set_attr "length" "12")]
6927)
6928
6929(define_expand "indirect_jump"
6930  [(set (pc)
6931	(match_operand:SI 0 "s_register_operand" ""))]
6932  "TARGET_EITHER"
6933  ""
6934)
6935
6936(define_insn "*arm_indirect_jump"
6937  [(set (pc)
6938	(match_operand:SI 0 "s_register_operand" "r"))]
6939  "TARGET_ARM"
6940  "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6941  [(set_attr "predicable" "yes")]
6942)
6943
6944;; Although not supported by the define_expand above,
6945;; cse/combine may generate this form.
6946(define_insn "*load_indirect_jump"
6947  [(set (pc)
6948	(match_operand:SI 0 "memory_operand" "m"))]
6949  "TARGET_ARM"
6950  "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6951  [(set_attr "type" "load")
6952   (set_attr "pool_range" "4096")
6953   (set_attr "neg_pool_range" "4084")
6954   (set_attr "predicable" "yes")]
6955)
6956
6957(define_insn "*thumb_indirect_jump"
6958  [(set (pc)
6959	(match_operand:SI 0 "register_operand" "l*r"))]
6960  "TARGET_THUMB"
6961  "mov\\tpc, %0"
6962  [(set_attr "conds" "clob")
6963   (set_attr "length" "2")]
6964)
6965
6966
6967;; Misc insns
6968
6969(define_insn "nop"
6970  [(const_int 0)]
6971  "TARGET_EITHER"
6972  "*
6973  if (TARGET_ARM)
6974    return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6975  return  \"mov\\tr8, r8\";
6976  "
6977  [(set (attr "length")
6978	(if_then_else (eq_attr "is_thumb" "yes")
6979		      (const_int 2)
6980		      (const_int 4)))]
6981)
6982
6983
6984;; Patterns to allow combination of arithmetic, cond code and shifts
6985
6986(define_insn "*arith_shiftsi"
6987  [(set (match_operand:SI 0 "s_register_operand" "=r")
6988        (match_operator:SI 1 "shiftable_operator"
6989          [(match_operator:SI 3 "shift_operator"
6990             [(match_operand:SI 4 "s_register_operand" "r")
6991              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6992           (match_operand:SI 2 "s_register_operand" "r")]))]
6993  "TARGET_ARM"
6994  "%i1%?\\t%0, %2, %4%S3"
6995  [(set_attr "predicable" "yes")
6996   (set_attr "shift" "4")
6997   ]
6998)
6999
7000(define_insn "*arith_shiftsi_compare0"
7001  [(set (reg:CC_NOOV CC_REGNUM)
7002        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7003		          [(match_operator:SI 3 "shift_operator"
7004		            [(match_operand:SI 4 "s_register_operand" "r")
7005		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
7006		           (match_operand:SI 2 "s_register_operand" "r")])
7007			 (const_int 0)))
7008   (set (match_operand:SI 0 "s_register_operand" "=r")
7009	(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7010			 (match_dup 2)]))]
7011  "TARGET_ARM"
7012  "%i1%?s\\t%0, %2, %4%S3"
7013  [(set_attr "conds" "set")
7014   (set_attr "shift" "4")
7015   ]
7016)
7017
7018(define_insn "*arith_shiftsi_compare0_scratch"
7019  [(set (reg:CC_NOOV CC_REGNUM)
7020        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7021		          [(match_operator:SI 3 "shift_operator"
7022		            [(match_operand:SI 4 "s_register_operand" "r")
7023		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
7024		           (match_operand:SI 2 "s_register_operand" "r")])
7025			 (const_int 0)))
7026   (clobber (match_scratch:SI 0 "=r"))]
7027  "TARGET_ARM"
7028  "%i1%?s\\t%0, %2, %4%S3"
7029  [(set_attr "conds" "set")
7030   (set_attr "shift" "4")
7031   ]
7032)
7033
7034(define_insn "*sub_shiftsi"
7035  [(set (match_operand:SI 0 "s_register_operand" "=r")
7036	(minus:SI (match_operand:SI 1 "s_register_operand" "r")
7037		  (match_operator:SI 2 "shift_operator"
7038		   [(match_operand:SI 3 "s_register_operand" "r")
7039		    (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7040  "TARGET_ARM"
7041  "sub%?\\t%0, %1, %3%S2"
7042  [(set_attr "predicable" "yes")
7043   (set_attr "shift" "3")
7044   ]
7045)
7046
7047(define_insn "*sub_shiftsi_compare0"
7048  [(set (reg:CC_NOOV CC_REGNUM)
7049	(compare:CC_NOOV
7050	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7051		   (match_operator:SI 2 "shift_operator"
7052		    [(match_operand:SI 3 "s_register_operand" "r")
7053		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7054	 (const_int 0)))
7055   (set (match_operand:SI 0 "s_register_operand" "=r")
7056	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7057						 (match_dup 4)])))]
7058  "TARGET_ARM"
7059  "sub%?s\\t%0, %1, %3%S2"
7060  [(set_attr "conds" "set")
7061   (set_attr "shift" "3") 
7062   ]
7063)
7064
7065(define_insn "*sub_shiftsi_compare0_scratch"
7066  [(set (reg:CC_NOOV CC_REGNUM)
7067	(compare:CC_NOOV
7068	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7069		   (match_operator:SI 2 "shift_operator"
7070		    [(match_operand:SI 3 "s_register_operand" "r")
7071		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7072	 (const_int 0)))
7073   (clobber (match_scratch:SI 0 "=r"))]
7074  "TARGET_ARM"
7075  "sub%?s\\t%0, %1, %3%S2"
7076  [(set_attr "conds" "set")
7077   (set_attr "shift" "3") 
7078   ]
7079)
7080
7081
7082
7083(define_insn "*and_scc"
7084  [(set (match_operand:SI 0 "s_register_operand" "=r")
7085	(and:SI (match_operator:SI 1 "arm_comparison_operator"
7086		 [(match_operand 3 "cc_register" "") (const_int 0)])
7087		(match_operand:SI 2 "s_register_operand" "r")))]
7088  "TARGET_ARM"
7089  "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7090  [(set_attr "conds" "use")
7091   (set_attr "length" "8")]
7092)
7093
7094(define_insn "*ior_scc"
7095  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7096	(ior:SI (match_operator:SI 2 "arm_comparison_operator"
7097		 [(match_operand 3 "cc_register" "") (const_int 0)])
7098		(match_operand:SI 1 "s_register_operand" "0,?r")))]
7099  "TARGET_ARM"
7100  "@
7101   orr%d2\\t%0, %1, #1
7102   mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7103  [(set_attr "conds" "use")
7104   (set_attr "length" "4,8")]
7105)
7106
7107(define_insn "*compare_scc"
7108  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7109	(match_operator:SI 1 "arm_comparison_operator"
7110	 [(match_operand:SI 2 "s_register_operand" "r,r")
7111	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7112   (clobber (reg:CC CC_REGNUM))]
7113  "TARGET_ARM"
7114  "*
7115    if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7116      return \"mov\\t%0, %2, lsr #31\";
7117
7118    if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7119      return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7120
7121    if (GET_CODE (operands[1]) == NE)
7122      {
7123        if (which_alternative == 1)
7124	  return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7125        return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7126      }
7127    if (which_alternative == 1)
7128      output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7129    else
7130      output_asm_insn (\"cmp\\t%2, %3\", operands);
7131    return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7132  "
7133  [(set_attr "conds" "clob")
7134   (set_attr "length" "12")]
7135)
7136
7137(define_insn "*cond_move"
7138  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7139	(if_then_else:SI (match_operator 3 "equality_operator"
7140			  [(match_operator 4 "arm_comparison_operator"
7141			    [(match_operand 5 "cc_register" "") (const_int 0)])
7142			   (const_int 0)])
7143			 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7144			 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7145  "TARGET_ARM"
7146  "*
7147    if (GET_CODE (operands[3]) == NE)
7148      {
7149        if (which_alternative != 1)
7150	  output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7151        if (which_alternative != 0)
7152	  output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7153        return \"\";
7154      }
7155    if (which_alternative != 0)
7156      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7157    if (which_alternative != 1)
7158      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7159    return \"\";
7160  "
7161  [(set_attr "conds" "use")
7162   (set_attr "length" "4,4,8")]
7163)
7164
7165(define_insn "*cond_arith"
7166  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7167        (match_operator:SI 5 "shiftable_operator" 
7168	 [(match_operator:SI 4 "arm_comparison_operator"
7169           [(match_operand:SI 2 "s_register_operand" "r,r")
7170	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7171          (match_operand:SI 1 "s_register_operand" "0,?r")]))
7172   (clobber (reg:CC CC_REGNUM))]
7173  "TARGET_ARM"
7174  "*
7175    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7176      return \"%i5\\t%0, %1, %2, lsr #31\";
7177
7178    output_asm_insn (\"cmp\\t%2, %3\", operands);
7179    if (GET_CODE (operands[5]) == AND)
7180      output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7181    else if (GET_CODE (operands[5]) == MINUS)
7182      output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7183    else if (which_alternative != 0)
7184      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7185    return \"%i5%d4\\t%0, %1, #1\";
7186  "
7187  [(set_attr "conds" "clob")
7188   (set_attr "length" "12")]
7189)
7190
7191(define_insn "*cond_sub"
7192  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7193        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7194		  (match_operator:SI 4 "arm_comparison_operator"
7195                   [(match_operand:SI 2 "s_register_operand" "r,r")
7196		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7197   (clobber (reg:CC CC_REGNUM))]
7198  "TARGET_ARM"
7199  "*
7200    output_asm_insn (\"cmp\\t%2, %3\", operands);
7201    if (which_alternative != 0)
7202      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7203    return \"sub%d4\\t%0, %1, #1\";
7204  "
7205  [(set_attr "conds" "clob")
7206   (set_attr "length" "8,12")]
7207)
7208
7209(define_insn "*cmp_ite0"
7210  [(set (match_operand 6 "dominant_cc_register" "")
7211	(compare
7212	 (if_then_else:SI
7213	  (match_operator 4 "arm_comparison_operator"
7214	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7215	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7216	  (match_operator:SI 5 "arm_comparison_operator"
7217	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7218	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7219	  (const_int 0))
7220	 (const_int 0)))]
7221  "TARGET_ARM"
7222  "*
7223  {
7224    static const char * const opcodes[4][2] =
7225    {
7226      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7227       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7228      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7229       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7230      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7231       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7232      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7233       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7234    };
7235    int swap =
7236      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7237
7238    return opcodes[which_alternative][swap];
7239  }"
7240  [(set_attr "conds" "set")
7241   (set_attr "length" "8")]
7242)
7243
7244(define_insn "*cmp_ite1"
7245  [(set (match_operand 6 "dominant_cc_register" "")
7246	(compare
7247	 (if_then_else:SI
7248	  (match_operator 4 "arm_comparison_operator"
7249	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7250	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7251	  (match_operator:SI 5 "arm_comparison_operator"
7252	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7253	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7254	  (const_int 1))
7255	 (const_int 0)))]
7256  "TARGET_ARM"
7257  "*
7258  {
7259    static const char * const opcodes[4][2] =
7260    {
7261      {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7262       \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7263      {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7264       \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7265      {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7266       \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7267      {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7268       \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7269    };
7270    int swap =
7271      comparison_dominates_p (GET_CODE (operands[5]),
7272			      reverse_condition (GET_CODE (operands[4])));
7273
7274    return opcodes[which_alternative][swap];
7275  }"
7276  [(set_attr "conds" "set")
7277   (set_attr "length" "8")]
7278)
7279
7280(define_insn "*cmp_and"
7281  [(set (match_operand 6 "dominant_cc_register" "")
7282	(compare
7283	 (and:SI
7284	  (match_operator 4 "arm_comparison_operator"
7285	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7286	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7287	  (match_operator:SI 5 "arm_comparison_operator"
7288	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7289	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7290	 (const_int 0)))]
7291  "TARGET_ARM"
7292  "*
7293  {
7294    static const char *const opcodes[4][2] =
7295    {
7296      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7297       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7298      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7299       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7300      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7301       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7302      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7303       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7304    };
7305    int swap =
7306      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7307
7308    return opcodes[which_alternative][swap];
7309  }"
7310  [(set_attr "conds" "set")
7311   (set_attr "predicable" "no")
7312   (set_attr "length" "8")]
7313)
7314
7315(define_insn "*cmp_ior"
7316  [(set (match_operand 6 "dominant_cc_register" "")
7317	(compare
7318	 (ior:SI
7319	  (match_operator 4 "arm_comparison_operator"
7320	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7321	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7322	  (match_operator:SI 5 "arm_comparison_operator"
7323	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7324	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7325	 (const_int 0)))]
7326  "TARGET_ARM"
7327  "*
7328{
7329  static const char *const opcodes[4][2] =
7330  {
7331    {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7332     \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7333    {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7334     \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7335    {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7336     \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7337    {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7338     \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7339  };
7340  int swap =
7341    comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7342
7343  return opcodes[which_alternative][swap];
7344}
7345"
7346  [(set_attr "conds" "set")
7347   (set_attr "length" "8")]
7348)
7349
7350(define_insn "*negscc"
7351  [(set (match_operand:SI 0 "s_register_operand" "=r")
7352	(neg:SI (match_operator 3 "arm_comparison_operator"
7353		 [(match_operand:SI 1 "s_register_operand" "r")
7354		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7355   (clobber (reg:CC CC_REGNUM))]
7356  "TARGET_ARM"
7357  "*
7358  if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7359    return \"mov\\t%0, %1, asr #31\";
7360
7361  if (GET_CODE (operands[3]) == NE)
7362    return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7363
7364  if (GET_CODE (operands[3]) == GT)
7365    return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7366
7367  output_asm_insn (\"cmp\\t%1, %2\", operands);
7368  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7369  return \"mvn%d3\\t%0, #0\";
7370  "
7371  [(set_attr "conds" "clob")
7372   (set_attr "length" "12")]
7373)
7374
7375(define_insn "movcond"
7376  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7377	(if_then_else:SI
7378	 (match_operator 5 "arm_comparison_operator"
7379	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
7380	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7381	 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7382	 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7383   (clobber (reg:CC CC_REGNUM))]
7384  "TARGET_ARM"
7385  "*
7386  if (GET_CODE (operands[5]) == LT
7387      && (operands[4] == const0_rtx))
7388    {
7389      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7390	{
7391	  if (operands[2] == const0_rtx)
7392	    return \"and\\t%0, %1, %3, asr #31\";
7393	  return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7394	}
7395      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7396	{
7397	  if (operands[1] == const0_rtx)
7398	    return \"bic\\t%0, %2, %3, asr #31\";
7399	  return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7400	}
7401      /* The only case that falls through to here is when both ops 1 & 2
7402	 are constants */
7403    }
7404
7405  if (GET_CODE (operands[5]) == GE
7406      && (operands[4] == const0_rtx))
7407    {
7408      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7409	{
7410	  if (operands[2] == const0_rtx)
7411	    return \"bic\\t%0, %1, %3, asr #31\";
7412	  return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7413	}
7414      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7415	{
7416	  if (operands[1] == const0_rtx)
7417	    return \"and\\t%0, %2, %3, asr #31\";
7418	  return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7419	}
7420      /* The only case that falls through to here is when both ops 1 & 2
7421	 are constants */
7422    }
7423  if (GET_CODE (operands[4]) == CONST_INT
7424      && !const_ok_for_arm (INTVAL (operands[4])))
7425    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7426  else
7427    output_asm_insn (\"cmp\\t%3, %4\", operands);
7428  if (which_alternative != 0)
7429    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7430  if (which_alternative != 1)
7431    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7432  return \"\";
7433  "
7434  [(set_attr "conds" "clob")
7435   (set_attr "length" "8,8,12")]
7436)
7437
7438(define_insn "*ifcompare_plus_move"
7439  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7440	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7441			  [(match_operand:SI 4 "s_register_operand" "r,r")
7442			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7443			 (plus:SI
7444			  (match_operand:SI 2 "s_register_operand" "r,r")
7445			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7446			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7447   (clobber (reg:CC CC_REGNUM))]
7448  "TARGET_ARM"
7449  "#"
7450  [(set_attr "conds" "clob")
7451   (set_attr "length" "8,12")]
7452)
7453
7454(define_insn "*if_plus_move"
7455  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7456	(if_then_else:SI
7457	 (match_operator 4 "arm_comparison_operator"
7458	  [(match_operand 5 "cc_register" "") (const_int 0)])
7459	 (plus:SI
7460	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7461	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7462	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7463  "TARGET_ARM"
7464  "@
7465   add%d4\\t%0, %2, %3
7466   sub%d4\\t%0, %2, #%n3
7467   add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7468   sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7469  [(set_attr "conds" "use")
7470   (set_attr "length" "4,4,8,8")
7471   (set_attr "type" "*,*,*,*")]
7472)
7473
7474(define_insn "*ifcompare_move_plus"
7475  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7476	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7477			  [(match_operand:SI 4 "s_register_operand" "r,r")
7478			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7479			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7480			 (plus:SI
7481			  (match_operand:SI 2 "s_register_operand" "r,r")
7482			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7483   (clobber (reg:CC CC_REGNUM))]
7484  "TARGET_ARM"
7485  "#"
7486  [(set_attr "conds" "clob")
7487   (set_attr "length" "8,12")]
7488)
7489
7490(define_insn "*if_move_plus"
7491  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7492	(if_then_else:SI
7493	 (match_operator 4 "arm_comparison_operator"
7494	  [(match_operand 5 "cc_register" "") (const_int 0)])
7495	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7496	 (plus:SI
7497	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7498	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7499  "TARGET_ARM"
7500  "@
7501   add%D4\\t%0, %2, %3
7502   sub%D4\\t%0, %2, #%n3
7503   add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7504   sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7505  [(set_attr "conds" "use")
7506   (set_attr "length" "4,4,8,8")
7507   (set_attr "type" "*,*,*,*")]
7508)
7509
7510(define_insn "*ifcompare_arith_arith"
7511  [(set (match_operand:SI 0 "s_register_operand" "=r")
7512	(if_then_else:SI (match_operator 9 "arm_comparison_operator"
7513			  [(match_operand:SI 5 "s_register_operand" "r")
7514			   (match_operand:SI 6 "arm_add_operand" "rIL")])
7515			 (match_operator:SI 8 "shiftable_operator"
7516			  [(match_operand:SI 1 "s_register_operand" "r")
7517			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
7518			 (match_operator:SI 7 "shiftable_operator"
7519			  [(match_operand:SI 3 "s_register_operand" "r")
7520			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7521   (clobber (reg:CC CC_REGNUM))]
7522  "TARGET_ARM"
7523  "#"
7524  [(set_attr "conds" "clob")
7525   (set_attr "length" "12")]
7526)
7527
7528(define_insn "*if_arith_arith"
7529  [(set (match_operand:SI 0 "s_register_operand" "=r")
7530	(if_then_else:SI (match_operator 5 "arm_comparison_operator"
7531			  [(match_operand 8 "cc_register" "") (const_int 0)])
7532			 (match_operator:SI 6 "shiftable_operator"
7533			  [(match_operand:SI 1 "s_register_operand" "r")
7534			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
7535			 (match_operator:SI 7 "shiftable_operator"
7536			  [(match_operand:SI 3 "s_register_operand" "r")
7537			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7538  "TARGET_ARM"
7539  "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7540  [(set_attr "conds" "use")
7541   (set_attr "length" "8")]
7542)
7543
7544(define_insn "*ifcompare_arith_move"
7545  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7546	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7547			  [(match_operand:SI 2 "s_register_operand" "r,r")
7548			   (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7549			 (match_operator:SI 7 "shiftable_operator"
7550			  [(match_operand:SI 4 "s_register_operand" "r,r")
7551			   (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7552			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7553   (clobber (reg:CC CC_REGNUM))]
7554  "TARGET_ARM"
7555  "*
7556  /* If we have an operation where (op x 0) is the identity operation and
7557     the conditional operator is LT or GE and we are comparing against zero and
7558     everything is in registers then we can do this in two instructions */
7559  if (operands[3] == const0_rtx
7560      && GET_CODE (operands[7]) != AND
7561      && GET_CODE (operands[5]) == REG
7562      && GET_CODE (operands[1]) == REG 
7563      && REGNO (operands[1]) == REGNO (operands[4])
7564      && REGNO (operands[4]) != REGNO (operands[0]))
7565    {
7566      if (GET_CODE (operands[6]) == LT)
7567	return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7568      else if (GET_CODE (operands[6]) == GE)
7569	return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7570    }
7571  if (GET_CODE (operands[3]) == CONST_INT
7572      && !const_ok_for_arm (INTVAL (operands[3])))
7573    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7574  else
7575    output_asm_insn (\"cmp\\t%2, %3\", operands);
7576  output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7577  if (which_alternative != 0)
7578    return \"mov%D6\\t%0, %1\";
7579  return \"\";
7580  "
7581  [(set_attr "conds" "clob")
7582   (set_attr "length" "8,12")]
7583)
7584
7585(define_insn "*if_arith_move"
7586  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7587	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
7588			  [(match_operand 6 "cc_register" "") (const_int 0)])
7589			 (match_operator:SI 5 "shiftable_operator"
7590			  [(match_operand:SI 2 "s_register_operand" "r,r")
7591			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7592			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7593  "TARGET_ARM"
7594  "@
7595   %I5%d4\\t%0, %2, %3
7596   %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7597  [(set_attr "conds" "use")
7598   (set_attr "length" "4,8")
7599   (set_attr "type" "*,*")]
7600)
7601
7602(define_insn "*ifcompare_move_arith"
7603  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7604	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7605			  [(match_operand:SI 4 "s_register_operand" "r,r")
7606			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7607			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7608			 (match_operator:SI 7 "shiftable_operator"
7609			  [(match_operand:SI 2 "s_register_operand" "r,r")
7610			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7611   (clobber (reg:CC CC_REGNUM))]
7612  "TARGET_ARM"
7613  "*
7614  /* If we have an operation where (op x 0) is the identity operation and
7615     the conditional operator is LT or GE and we are comparing against zero and
7616     everything is in registers then we can do this in two instructions */
7617  if (operands[5] == const0_rtx
7618      && GET_CODE (operands[7]) != AND
7619      && GET_CODE (operands[3]) == REG
7620      && GET_CODE (operands[1]) == REG 
7621      && REGNO (operands[1]) == REGNO (operands[2])
7622      && REGNO (operands[2]) != REGNO (operands[0]))
7623    {
7624      if (GET_CODE (operands[6]) == GE)
7625	return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7626      else if (GET_CODE (operands[6]) == LT)
7627	return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7628    }
7629
7630  if (GET_CODE (operands[5]) == CONST_INT
7631      && !const_ok_for_arm (INTVAL (operands[5])))
7632    output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7633  else
7634    output_asm_insn (\"cmp\\t%4, %5\", operands);
7635
7636  if (which_alternative != 0)
7637    output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7638  return \"%I7%D6\\t%0, %2, %3\";
7639  "
7640  [(set_attr "conds" "clob")
7641   (set_attr "length" "8,12")]
7642)
7643
7644(define_insn "*if_move_arith"
7645  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7646	(if_then_else:SI
7647	 (match_operator 4 "arm_comparison_operator"
7648	  [(match_operand 6 "cc_register" "") (const_int 0)])
7649	 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7650	 (match_operator:SI 5 "shiftable_operator"
7651	  [(match_operand:SI 2 "s_register_operand" "r,r")
7652	   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7653  "TARGET_ARM"
7654  "@
7655   %I5%D4\\t%0, %2, %3
7656   %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7657  [(set_attr "conds" "use")
7658   (set_attr "length" "4,8")
7659   (set_attr "type" "*,*")]
7660)
7661
7662(define_insn "*ifcompare_move_not"
7663  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7664	(if_then_else:SI
7665	 (match_operator 5 "arm_comparison_operator"
7666	  [(match_operand:SI 3 "s_register_operand" "r,r")
7667	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7668	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7669	 (not:SI
7670	  (match_operand:SI 2 "s_register_operand" "r,r"))))
7671   (clobber (reg:CC CC_REGNUM))]
7672  "TARGET_ARM"
7673  "#"
7674  [(set_attr "conds" "clob")
7675   (set_attr "length" "8,12")]
7676)
7677
7678(define_insn "*if_move_not"
7679  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7680	(if_then_else:SI
7681	 (match_operator 4 "arm_comparison_operator"
7682	  [(match_operand 3 "cc_register" "") (const_int 0)])
7683	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7684	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7685  "TARGET_ARM"
7686  "@
7687   mvn%D4\\t%0, %2
7688   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7689   mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7690  [(set_attr "conds" "use")
7691   (set_attr "length" "4,8,8")]
7692)
7693
7694(define_insn "*ifcompare_not_move"
7695  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7696	(if_then_else:SI 
7697	 (match_operator 5 "arm_comparison_operator"
7698	  [(match_operand:SI 3 "s_register_operand" "r,r")
7699	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7700	 (not:SI
7701	  (match_operand:SI 2 "s_register_operand" "r,r"))
7702	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7703   (clobber (reg:CC CC_REGNUM))]
7704  "TARGET_ARM"
7705  "#"
7706  [(set_attr "conds" "clob")
7707   (set_attr "length" "8,12")]
7708)
7709
7710(define_insn "*if_not_move"
7711  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7712	(if_then_else:SI
7713	 (match_operator 4 "arm_comparison_operator"
7714	  [(match_operand 3 "cc_register" "") (const_int 0)])
7715	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7716	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7717  "TARGET_ARM"
7718  "@
7719   mvn%d4\\t%0, %2
7720   mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7721   mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7722  [(set_attr "conds" "use")
7723   (set_attr "length" "4,8,8")]
7724)
7725
7726(define_insn "*ifcompare_shift_move"
7727  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7728	(if_then_else:SI
7729	 (match_operator 6 "arm_comparison_operator"
7730	  [(match_operand:SI 4 "s_register_operand" "r,r")
7731	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7732	 (match_operator:SI 7 "shift_operator"
7733	  [(match_operand:SI 2 "s_register_operand" "r,r")
7734	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7735	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7736   (clobber (reg:CC CC_REGNUM))]
7737  "TARGET_ARM"
7738  "#"
7739  [(set_attr "conds" "clob")
7740   (set_attr "length" "8,12")]
7741)
7742
7743(define_insn "*if_shift_move"
7744  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7745	(if_then_else:SI
7746	 (match_operator 5 "arm_comparison_operator"
7747	  [(match_operand 6 "cc_register" "") (const_int 0)])
7748	 (match_operator:SI 4 "shift_operator"
7749	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
7750	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7751	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7752  "TARGET_ARM"
7753  "@
7754   mov%d5\\t%0, %2%S4
7755   mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7756   mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7757  [(set_attr "conds" "use")
7758   (set_attr "shift" "2")
7759   (set_attr "length" "4,8,8")]
7760)
7761
7762(define_insn "*ifcompare_move_shift"
7763  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7764	(if_then_else:SI
7765	 (match_operator 6 "arm_comparison_operator"
7766	  [(match_operand:SI 4 "s_register_operand" "r,r")
7767	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7768	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7769	 (match_operator:SI 7 "shift_operator"
7770	  [(match_operand:SI 2 "s_register_operand" "r,r")
7771	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7772   (clobber (reg:CC CC_REGNUM))]
7773  "TARGET_ARM"
7774  "#"
7775  [(set_attr "conds" "clob")
7776   (set_attr "length" "8,12")]
7777)
7778
7779(define_insn "*if_move_shift"
7780  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7781	(if_then_else:SI
7782	 (match_operator 5 "arm_comparison_operator"
7783	  [(match_operand 6 "cc_register" "") (const_int 0)])
7784	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7785	 (match_operator:SI 4 "shift_operator"
7786	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
7787	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7788  "TARGET_ARM"
7789  "@
7790   mov%D5\\t%0, %2%S4
7791   mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7792   mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7793  [(set_attr "conds" "use")
7794   (set_attr "shift" "2")
7795   (set_attr "length" "4,8,8")]
7796)
7797
7798(define_insn "*ifcompare_shift_shift"
7799  [(set (match_operand:SI 0 "s_register_operand" "=r")
7800	(if_then_else:SI
7801	 (match_operator 7 "arm_comparison_operator"
7802	  [(match_operand:SI 5 "s_register_operand" "r")
7803	   (match_operand:SI 6 "arm_add_operand" "rIL")])
7804	 (match_operator:SI 8 "shift_operator"
7805	  [(match_operand:SI 1 "s_register_operand" "r")
7806	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
7807	 (match_operator:SI 9 "shift_operator"
7808	  [(match_operand:SI 3 "s_register_operand" "r")
7809	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7810   (clobber (reg:CC CC_REGNUM))]
7811  "TARGET_ARM"
7812  "#"
7813  [(set_attr "conds" "clob")
7814   (set_attr "length" "12")]
7815)
7816
7817(define_insn "*if_shift_shift"
7818  [(set (match_operand:SI 0 "s_register_operand" "=r")
7819	(if_then_else:SI
7820	 (match_operator 5 "arm_comparison_operator"
7821	  [(match_operand 8 "cc_register" "") (const_int 0)])
7822	 (match_operator:SI 6 "shift_operator"
7823	  [(match_operand:SI 1 "s_register_operand" "r")
7824	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
7825	 (match_operator:SI 7 "shift_operator"
7826	  [(match_operand:SI 3 "s_register_operand" "r")
7827	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7828  "TARGET_ARM"
7829  "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7830  [(set_attr "conds" "use")
7831   (set_attr "shift" "1")
7832   (set_attr "length" "8")]
7833)
7834
7835(define_insn "*ifcompare_not_arith"
7836  [(set (match_operand:SI 0 "s_register_operand" "=r")
7837	(if_then_else:SI
7838	 (match_operator 6 "arm_comparison_operator"
7839	  [(match_operand:SI 4 "s_register_operand" "r")
7840	   (match_operand:SI 5 "arm_add_operand" "rIL")])
7841	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7842	 (match_operator:SI 7 "shiftable_operator"
7843	  [(match_operand:SI 2 "s_register_operand" "r")
7844	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7845   (clobber (reg:CC CC_REGNUM))]
7846  "TARGET_ARM"
7847  "#"
7848  [(set_attr "conds" "clob")
7849   (set_attr "length" "12")]
7850)
7851
7852(define_insn "*if_not_arith"
7853  [(set (match_operand:SI 0 "s_register_operand" "=r")
7854	(if_then_else:SI
7855	 (match_operator 5 "arm_comparison_operator"
7856	  [(match_operand 4 "cc_register" "") (const_int 0)])
7857	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7858	 (match_operator:SI 6 "shiftable_operator"
7859	  [(match_operand:SI 2 "s_register_operand" "r")
7860	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7861  "TARGET_ARM"
7862  "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7863  [(set_attr "conds" "use")
7864   (set_attr "length" "8")]
7865)
7866
7867(define_insn "*ifcompare_arith_not"
7868  [(set (match_operand:SI 0 "s_register_operand" "=r")
7869	(if_then_else:SI
7870	 (match_operator 6 "arm_comparison_operator"
7871	  [(match_operand:SI 4 "s_register_operand" "r")
7872	   (match_operand:SI 5 "arm_add_operand" "rIL")])
7873	 (match_operator:SI 7 "shiftable_operator"
7874	  [(match_operand:SI 2 "s_register_operand" "r")
7875	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
7876	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7877   (clobber (reg:CC CC_REGNUM))]
7878  "TARGET_ARM"
7879  "#"
7880  [(set_attr "conds" "clob")
7881   (set_attr "length" "12")]
7882)
7883
7884(define_insn "*if_arith_not"
7885  [(set (match_operand:SI 0 "s_register_operand" "=r")
7886	(if_then_else:SI
7887	 (match_operator 5 "arm_comparison_operator"
7888	  [(match_operand 4 "cc_register" "") (const_int 0)])
7889	 (match_operator:SI 6 "shiftable_operator"
7890	  [(match_operand:SI 2 "s_register_operand" "r")
7891	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
7892	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7893  "TARGET_ARM"
7894  "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7895  [(set_attr "conds" "use")
7896   (set_attr "length" "8")]
7897)
7898
7899(define_insn "*ifcompare_neg_move"
7900  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7901	(if_then_else:SI
7902	 (match_operator 5 "arm_comparison_operator"
7903	  [(match_operand:SI 3 "s_register_operand" "r,r")
7904	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7905	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7906	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7907   (clobber (reg:CC CC_REGNUM))]
7908  "TARGET_ARM"
7909  "#"
7910  [(set_attr "conds" "clob")
7911   (set_attr "length" "8,12")]
7912)
7913
7914(define_insn "*if_neg_move"
7915  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7916	(if_then_else:SI
7917	 (match_operator 4 "arm_comparison_operator"
7918	  [(match_operand 3 "cc_register" "") (const_int 0)])
7919	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7920	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7921  "TARGET_ARM"
7922  "@
7923   rsb%d4\\t%0, %2, #0
7924   mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7925   mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7926  [(set_attr "conds" "use")
7927   (set_attr "length" "4,8,8")]
7928)
7929
7930(define_insn "*ifcompare_move_neg"
7931  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7932	(if_then_else:SI
7933	 (match_operator 5 "arm_comparison_operator"
7934	  [(match_operand:SI 3 "s_register_operand" "r,r")
7935	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7936	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7937	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7938   (clobber (reg:CC CC_REGNUM))]
7939  "TARGET_ARM"
7940  "#"
7941  [(set_attr "conds" "clob")
7942   (set_attr "length" "8,12")]
7943)
7944
7945(define_insn "*if_move_neg"
7946  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7947	(if_then_else:SI
7948	 (match_operator 4 "arm_comparison_operator"
7949	  [(match_operand 3 "cc_register" "") (const_int 0)])
7950	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7951	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7952  "TARGET_ARM"
7953  "@
7954   rsb%D4\\t%0, %2, #0
7955   mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7956   mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7957  [(set_attr "conds" "use")
7958   (set_attr "length" "4,8,8")]
7959)
7960
7961(define_insn "*arith_adjacentmem"
7962  [(set (match_operand:SI 0 "s_register_operand" "=r")
7963	(match_operator:SI 1 "shiftable_operator"
7964	 [(match_operand:SI 2 "memory_operand" "m")
7965	  (match_operand:SI 3 "memory_operand" "m")]))
7966   (clobber (match_scratch:SI 4 "=r"))]
7967  "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7968  "*
7969  {
7970    rtx ldm[3];
7971    rtx arith[4];
7972    int val1 = 0, val2 = 0;
7973
7974    if (REGNO (operands[0]) > REGNO (operands[4]))
7975      {
7976	ldm[1] = operands[4];
7977	ldm[2] = operands[0];
7978      }
7979    else
7980      {
7981	ldm[1] = operands[0];
7982	ldm[2] = operands[4];
7983      }
7984    if (GET_CODE (XEXP (operands[2], 0)) != REG)
7985      val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7986    if (GET_CODE (XEXP (operands[3], 0)) != REG)
7987      val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7988    arith[0] = operands[0];
7989    arith[3] = operands[1];
7990    if (val1 < val2)
7991      {
7992	arith[1] = ldm[1];
7993	arith[2] = ldm[2];
7994      }
7995    else
7996      {
7997	arith[1] = ldm[2];
7998	arith[2] = ldm[1];
7999      }
8000   if (val1 && val2)
8001      {
8002	rtx ops[3];
8003	ldm[0] = ops[0] = operands[4];
8004	ops[1] = XEXP (XEXP (operands[2], 0), 0);
8005	ops[2] = XEXP (XEXP (operands[2], 0), 1);
8006	output_add_immediate (ops);
8007	if (val1 < val2)
8008	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8009	else
8010	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8011      }
8012    else if (val1)
8013      {
8014	ldm[0] = XEXP (operands[3], 0);
8015	if (val1 < val2)
8016	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8017	else
8018	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8019      }
8020    else
8021      {
8022	ldm[0] = XEXP (operands[2], 0);
8023	if (val1 < val2)
8024	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8025	else
8026	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8027      }
8028    output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8029    return \"\";
8030  }"
8031  [(set_attr "length" "12")
8032   (set_attr "predicable" "yes")
8033   (set_attr "type" "load")]
8034)
8035
8036;; the arm can support extended pre-inc instructions
8037
8038;; In all these cases, we use operands 0 and 1 for the register being
8039;; incremented because those are the operands that local-alloc will
8040;; tie and these are the pair most likely to be tieable (and the ones
8041;; that will benefit the most).
8042
8043;; We reject the frame pointer if it occurs anywhere in these patterns since
8044;; elimination will cause too many headaches.
8045
8046(define_insn "*strqi_preinc"
8047  [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8048			 (match_operand:SI 2 "index_operand" "rJ")))
8049	(match_operand:QI 3 "s_register_operand" "r"))
8050   (set (match_operand:SI 0 "s_register_operand" "=r")
8051	(plus:SI (match_dup 1) (match_dup 2)))]
8052  "TARGET_ARM
8053   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8054   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8055   && (GET_CODE (operands[2]) != REG
8056       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8057  "str%?b\\t%3, [%0, %2]!"
8058  [(set_attr "type" "store1")
8059   (set_attr "predicable" "yes")]
8060)
8061
8062(define_insn "*strqi_predec"
8063  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8064			  (match_operand:SI 2 "s_register_operand" "r")))
8065	(match_operand:QI 3 "s_register_operand" "r"))
8066   (set (match_operand:SI 0 "s_register_operand" "=r")
8067	(minus:SI (match_dup 1) (match_dup 2)))]
8068  "TARGET_ARM
8069   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8070   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8071   && (GET_CODE (operands[2]) != REG
8072       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8073  "str%?b\\t%3, [%0, -%2]!"
8074  [(set_attr "type" "store1")
8075   (set_attr "predicable" "yes")]
8076)
8077
8078(define_insn "*loadqi_preinc"
8079  [(set (match_operand:QI 3 "s_register_operand" "=r")
8080	(mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8081			 (match_operand:SI 2 "index_operand" "rJ"))))
8082   (set (match_operand:SI 0 "s_register_operand" "=r")
8083	(plus:SI (match_dup 1) (match_dup 2)))]
8084  "TARGET_ARM
8085   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8086   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8087   && (GET_CODE (operands[2]) != REG
8088       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8089  "ldr%?b\\t%3, [%0, %2]!"
8090  [(set_attr "type" "load")
8091   (set_attr "predicable" "yes")]
8092)
8093
8094(define_insn "*loadqi_predec"
8095  [(set (match_operand:QI 3 "s_register_operand" "=r")
8096	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8097			  (match_operand:SI 2 "s_register_operand" "r"))))
8098   (set (match_operand:SI 0 "s_register_operand" "=r")
8099	(minus:SI (match_dup 1) (match_dup 2)))]
8100  "TARGET_ARM
8101   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8102   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8103   && (GET_CODE (operands[2]) != REG
8104       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8105  "ldr%?b\\t%3, [%0, -%2]!"
8106  [(set_attr "type" "load")
8107   (set_attr "predicable" "yes")]
8108)
8109
8110(define_insn "*loadqisi_preinc"
8111  [(set (match_operand:SI 3 "s_register_operand" "=r")
8112	(zero_extend:SI
8113	 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8114			  (match_operand:SI 2 "index_operand" "rJ")))))
8115   (set (match_operand:SI 0 "s_register_operand" "=r")
8116	(plus:SI (match_dup 1) (match_dup 2)))]
8117  "TARGET_ARM
8118   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8119   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8120   && (GET_CODE (operands[2]) != REG
8121       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8122  "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8123  [(set_attr "type" "load")
8124   (set_attr "predicable" "yes")]
8125)
8126
8127(define_insn "*loadqisi_predec"
8128  [(set (match_operand:SI 3 "s_register_operand" "=r")
8129	(zero_extend:SI
8130	 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8131			   (match_operand:SI 2 "s_register_operand" "r")))))
8132   (set (match_operand:SI 0 "s_register_operand" "=r")
8133	(minus:SI (match_dup 1) (match_dup 2)))]
8134  "TARGET_ARM
8135   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8136   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8137   && (GET_CODE (operands[2]) != REG
8138       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8139  "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8140  [(set_attr "type" "load")
8141   (set_attr "predicable" "yes")]
8142)
8143
8144(define_insn "*strsi_preinc"
8145  [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8146			 (match_operand:SI 2 "index_operand" "rJ")))
8147	(match_operand:SI 3 "s_register_operand" "r"))
8148   (set (match_operand:SI 0 "s_register_operand" "=r")
8149	(plus:SI (match_dup 1) (match_dup 2)))]
8150  "TARGET_ARM
8151   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8152   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8153   && (GET_CODE (operands[2]) != REG
8154       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8155  "str%?\\t%3, [%0, %2]!"
8156  [(set_attr "type" "store1")
8157   (set_attr "predicable" "yes")]
8158)
8159
8160(define_insn "*strsi_predec"
8161  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8162			  (match_operand:SI 2 "s_register_operand" "r")))
8163	(match_operand:SI 3 "s_register_operand" "r"))
8164   (set (match_operand:SI 0 "s_register_operand" "=r")
8165	(minus:SI (match_dup 1) (match_dup 2)))]
8166  "TARGET_ARM
8167   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8168   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8169   && (GET_CODE (operands[2]) != REG
8170       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8171  "str%?\\t%3, [%0, -%2]!"
8172  [(set_attr "type" "store1")
8173   (set_attr "predicable" "yes")]
8174)
8175
8176(define_insn "*loadsi_preinc"
8177  [(set (match_operand:SI 3 "s_register_operand" "=r")
8178	(mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8179			 (match_operand:SI 2 "index_operand" "rJ"))))
8180   (set (match_operand:SI 0 "s_register_operand" "=r")
8181	(plus:SI (match_dup 1) (match_dup 2)))]
8182  "TARGET_ARM
8183   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8184   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8185   && (GET_CODE (operands[2]) != REG
8186       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8187  "ldr%?\\t%3, [%0, %2]!"
8188  [(set_attr "type" "load")
8189   (set_attr "predicable" "yes")]
8190)
8191
8192(define_insn "*loadsi_predec"
8193  [(set (match_operand:SI 3 "s_register_operand" "=r")
8194	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8195			  (match_operand:SI 2 "s_register_operand" "r"))))
8196   (set (match_operand:SI 0 "s_register_operand" "=r")
8197	(minus:SI (match_dup 1) (match_dup 2)))]
8198  "TARGET_ARM
8199   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8200   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8201   && (GET_CODE (operands[2]) != REG
8202       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8203  "ldr%?\\t%3, [%0, -%2]!"
8204  [(set_attr "type" "load")
8205   (set_attr "predicable" "yes")]
8206)
8207
8208(define_insn "*loadhi_preinc"
8209  [(set (match_operand:HI 3 "s_register_operand" "=r")
8210	(mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8211			 (match_operand:SI 2 "index_operand" "rJ"))))
8212   (set (match_operand:SI 0 "s_register_operand" "=r")
8213	(plus:SI (match_dup 1) (match_dup 2)))]
8214  "TARGET_ARM
8215   && !BYTES_BIG_ENDIAN
8216   && !TARGET_MMU_TRAPS
8217   && !arm_arch4
8218   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8219   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8220   && (GET_CODE (operands[2]) != REG
8221       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8222  "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8223  [(set_attr "type" "load")
8224   (set_attr "predicable" "yes")]
8225)
8226
8227(define_insn "*loadhi_predec"
8228  [(set (match_operand:HI 3 "s_register_operand" "=r")
8229	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8230			  (match_operand:SI 2 "s_register_operand" "r"))))
8231   (set (match_operand:SI 0 "s_register_operand" "=r")
8232	(minus:SI (match_dup 1) (match_dup 2)))]
8233  "TARGET_ARM
8234   && !BYTES_BIG_ENDIAN
8235   && !TARGET_MMU_TRAPS
8236   && !arm_arch4
8237   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8238   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8239   && (GET_CODE (operands[2]) != REG
8240       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8241  "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8242  [(set_attr "type" "load")
8243   (set_attr "predicable" "yes")]
8244)
8245
8246(define_insn "*strqi_shiftpreinc"
8247  [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8248			  [(match_operand:SI 3 "s_register_operand" "r")
8249			   (match_operand:SI 4 "const_shift_operand" "n")])
8250			 (match_operand:SI 1 "s_register_operand" "0")))
8251	(match_operand:QI 5 "s_register_operand" "r"))
8252   (set (match_operand:SI 0 "s_register_operand" "=r")
8253	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8254		 (match_dup 1)))]
8255  "TARGET_ARM
8256   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8257   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8258   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8259  "str%?b\\t%5, [%0, %3%S2]!"
8260  [(set_attr "type" "store1")
8261   (set_attr "predicable" "yes")]
8262)
8263
8264(define_insn "*strqi_shiftpredec"
8265  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8266			  (match_operator:SI 2 "shift_operator"
8267			   [(match_operand:SI 3 "s_register_operand" "r")
8268			    (match_operand:SI 4 "const_shift_operand" "n")])))
8269	(match_operand:QI 5 "s_register_operand" "r"))
8270   (set (match_operand:SI 0 "s_register_operand" "=r")
8271	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8272						 (match_dup 4)])))]
8273  "TARGET_ARM
8274   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8275   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8276   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8277  "str%?b\\t%5, [%0, -%3%S2]!"
8278  [(set_attr "type" "store1")
8279   (set_attr "predicable" "yes")]
8280)
8281
8282(define_insn "*loadqi_shiftpreinc"
8283  [(set (match_operand:QI 5 "s_register_operand" "=r")
8284	(mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8285			  [(match_operand:SI 3 "s_register_operand" "r")
8286			   (match_operand:SI 4 "const_shift_operand" "n")])
8287			 (match_operand:SI 1 "s_register_operand" "0"))))
8288   (set (match_operand:SI 0 "s_register_operand" "=r")
8289	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8290		 (match_dup 1)))]
8291  "TARGET_ARM
8292   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8293   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8294   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8295  "ldr%?b\\t%5, [%0, %3%S2]!"
8296  [(set_attr "type" "load")
8297   (set_attr "predicable" "yes")]
8298)
8299
8300(define_insn "*loadqi_shiftpredec"
8301  [(set (match_operand:QI 5 "s_register_operand" "=r")
8302	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8303			  (match_operator:SI 2 "shift_operator"
8304			   [(match_operand:SI 3 "s_register_operand" "r")
8305			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8306   (set (match_operand:SI 0 "s_register_operand" "=r")
8307	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8308						 (match_dup 4)])))]
8309  "TARGET_ARM
8310   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8311   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8312   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8313  "ldr%?b\\t%5, [%0, -%3%S2]!"
8314  [(set_attr "type" "load")
8315   (set_attr "predicable" "yes")]
8316)
8317
8318(define_insn "*strsi_shiftpreinc"
8319  [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8320			  [(match_operand:SI 3 "s_register_operand" "r")
8321			   (match_operand:SI 4 "const_shift_operand" "n")])
8322			 (match_operand:SI 1 "s_register_operand" "0")))
8323	(match_operand:SI 5 "s_register_operand" "r"))
8324   (set (match_operand:SI 0 "s_register_operand" "=r")
8325	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8326		 (match_dup 1)))]
8327  "TARGET_ARM
8328   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8329   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8330   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8331  "str%?\\t%5, [%0, %3%S2]!"
8332  [(set_attr "type" "store1")
8333   (set_attr "predicable" "yes")]
8334)
8335
8336(define_insn "*strsi_shiftpredec"
8337  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8338			  (match_operator:SI 2 "shift_operator"
8339			   [(match_operand:SI 3 "s_register_operand" "r")
8340			    (match_operand:SI 4 "const_shift_operand" "n")])))
8341	(match_operand:SI 5 "s_register_operand" "r"))
8342   (set (match_operand:SI 0 "s_register_operand" "=r")
8343	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8344						 (match_dup 4)])))]
8345  "TARGET_ARM
8346   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8347   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8348   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8349  "str%?\\t%5, [%0, -%3%S2]!"
8350  [(set_attr "type" "store1")
8351   (set_attr "predicable" "yes")]
8352)
8353
8354(define_insn "*loadsi_shiftpreinc"
8355  [(set (match_operand:SI 5 "s_register_operand" "=r")
8356	(mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8357			  [(match_operand:SI 3 "s_register_operand" "r")
8358			   (match_operand:SI 4 "const_shift_operand" "n")])
8359			 (match_operand:SI 1 "s_register_operand" "0"))))
8360   (set (match_operand:SI 0 "s_register_operand" "=r")
8361	(plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8362		 (match_dup 1)))]
8363  "TARGET_ARM
8364   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8365   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8366   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8367  "ldr%?\\t%5, [%0, %3%S2]!"
8368  [(set_attr "type" "load")
8369   (set_attr "predicable" "yes")]
8370)
8371
8372(define_insn "*loadsi_shiftpredec"
8373  [(set (match_operand:SI 5 "s_register_operand" "=r")
8374	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8375			  (match_operator:SI 2 "shift_operator"
8376			   [(match_operand:SI 3 "s_register_operand" "r")
8377			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8378   (set (match_operand:SI 0 "s_register_operand" "=r")
8379	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8380						 (match_dup 4)])))]
8381  "TARGET_ARM
8382   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8383   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8384   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8385  "ldr%?\\t%5, [%0, -%3%S2]!"
8386  [(set_attr "type" "load")
8387   (set_attr "predicable" "yes")])
8388
8389(define_insn "*loadhi_shiftpreinc"
8390  [(set (match_operand:HI 5 "s_register_operand" "=r")
8391	(mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8392			  [(match_operand:SI 3 "s_register_operand" "r")
8393			   (match_operand:SI 4 "const_shift_operand" "n")])
8394			 (match_operand:SI 1 "s_register_operand" "0"))))
8395   (set (match_operand:SI 0 "s_register_operand" "=r")
8396	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8397		 (match_dup 1)))]
8398  "TARGET_ARM
8399   && !BYTES_BIG_ENDIAN
8400   && !TARGET_MMU_TRAPS
8401   && !arm_arch4
8402   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8403   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8404   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8405  "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8406  [(set_attr "type" "load")
8407   (set_attr "predicable" "yes")]
8408)
8409
8410(define_insn "*loadhi_shiftpredec"
8411  [(set (match_operand:HI 5 "s_register_operand" "=r")
8412	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8413			  (match_operator:SI 2 "shift_operator"
8414			   [(match_operand:SI 3 "s_register_operand" "r")
8415			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8416   (set (match_operand:SI 0 "s_register_operand" "=r")
8417	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8418						 (match_dup 4)])))]
8419  "TARGET_ARM
8420   && !BYTES_BIG_ENDIAN
8421   && !TARGET_MMU_TRAPS
8422   && !arm_arch4
8423   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8424   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8425   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8426  "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8427  [(set_attr "type" "load")
8428   (set_attr "predicable" "yes")]
8429)
8430
8431; It can also support extended post-inc expressions, but combine doesn't
8432; try these....
8433; It doesn't seem worth adding peepholes for anything but the most common
8434; cases since, unlike combine, the increment must immediately follow the load
8435; for this pattern to match.
8436; We must watch to see that the source/destination register isn't also the
8437; same as the base address register, and that if the index is a register,
8438; that it is not the same as the base address register.  In such cases the
8439; instruction that we would generate would have UNPREDICTABLE behavior so 
8440; we cannot use it.
8441
8442(define_peephole
8443  [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8444	(match_operand:QI 2 "s_register_operand" "r"))
8445   (set (match_dup 0)
8446	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8447  "TARGET_ARM
8448   && (REGNO (operands[2]) != REGNO (operands[0]))
8449   && (GET_CODE (operands[1]) != REG
8450       || (REGNO (operands[1]) != REGNO (operands[0])))"
8451  "str%?b\\t%2, [%0], %1"
8452)
8453
8454(define_peephole
8455  [(set (match_operand:QI 0 "s_register_operand" "=r")
8456	(mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8457   (set (match_dup 1)
8458	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8459  "TARGET_ARM
8460   && REGNO (operands[0]) != REGNO(operands[1])
8461   && (GET_CODE (operands[2]) != REG
8462       || REGNO(operands[0]) != REGNO (operands[2]))"
8463  "ldr%?b\\t%0, [%1], %2"
8464)
8465
8466(define_peephole
8467  [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8468	(match_operand:SI 2 "s_register_operand" "r"))
8469   (set (match_dup 0)
8470	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8471  "TARGET_ARM
8472   && (REGNO (operands[2]) != REGNO (operands[0]))
8473   && (GET_CODE (operands[1]) != REG
8474       || (REGNO (operands[1]) != REGNO (operands[0])))"
8475  "str%?\\t%2, [%0], %1"
8476)
8477
8478(define_peephole
8479  [(set (match_operand:HI 0 "s_register_operand" "=r")
8480	(mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8481   (set (match_dup 1)
8482	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8483  "TARGET_ARM
8484   && !BYTES_BIG_ENDIAN
8485   && !TARGET_MMU_TRAPS
8486   && !arm_arch4
8487   && REGNO (operands[0]) != REGNO(operands[1])
8488   && (GET_CODE (operands[2]) != REG
8489       || REGNO(operands[0]) != REGNO (operands[2]))"
8490  "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8491)
8492
8493(define_peephole
8494  [(set (match_operand:SI 0 "s_register_operand" "=r")
8495	(mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8496   (set (match_dup 1)
8497	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8498  "TARGET_ARM
8499   && REGNO (operands[0]) != REGNO(operands[1])
8500   && (GET_CODE (operands[2]) != REG
8501       || REGNO(operands[0]) != REGNO (operands[2]))"
8502  "ldr%?\\t%0, [%1], %2"
8503)
8504
8505(define_peephole
8506  [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8507			 (match_operand:SI 1 "index_operand" "rJ")))
8508	(match_operand:QI 2 "s_register_operand" "r"))
8509   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8510  "TARGET_ARM
8511   && (REGNO (operands[2]) != REGNO (operands[0]))
8512   && (GET_CODE (operands[1]) != REG
8513       || (REGNO (operands[1]) != REGNO (operands[0])))"
8514  "str%?b\\t%2, [%0, %1]!"
8515)
8516
8517(define_peephole
8518  [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8519			  [(match_operand:SI 0 "s_register_operand" "r")
8520			   (match_operand:SI 1 "const_int_operand" "n")])
8521			 (match_operand:SI 2 "s_register_operand" "+r")))
8522	(match_operand:QI 3 "s_register_operand" "r"))
8523   (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8524			       (match_dup 2)))]
8525  "TARGET_ARM
8526   && (REGNO (operands[3]) != REGNO (operands[2]))
8527   && (REGNO (operands[0]) != REGNO (operands[2]))"
8528  "str%?b\\t%3, [%2, %0%S4]!"
8529)
8530
8531; This pattern is never tried by combine, so do it as a peephole
8532
8533(define_peephole2
8534  [(set (match_operand:SI 0 "s_register_operand" "")
8535	(match_operand:SI 1 "s_register_operand" ""))
8536   (set (reg:CC CC_REGNUM)
8537	(compare:CC (match_dup 1) (const_int 0)))]
8538  "TARGET_ARM
8539  "
8540  [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8541	      (set (match_dup 0) (match_dup 1))])]
8542  ""
8543)
8544
8545; Peepholes to spot possible load- and store-multiples, if the ordering is
8546; reversed, check that the memory references aren't volatile.
8547
8548(define_peephole
8549  [(set (match_operand:SI 0 "s_register_operand" "=r")
8550        (match_operand:SI 4 "memory_operand" "m"))
8551   (set (match_operand:SI 1 "s_register_operand" "=r")
8552        (match_operand:SI 5 "memory_operand" "m"))
8553   (set (match_operand:SI 2 "s_register_operand" "=r")
8554        (match_operand:SI 6 "memory_operand" "m"))
8555   (set (match_operand:SI 3 "s_register_operand" "=r")
8556        (match_operand:SI 7 "memory_operand" "m"))]
8557  "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8558  "*
8559  return emit_ldm_seq (operands, 4);
8560  "
8561)
8562
8563(define_peephole
8564  [(set (match_operand:SI 0 "s_register_operand" "=r")
8565        (match_operand:SI 3 "memory_operand" "m"))
8566   (set (match_operand:SI 1 "s_register_operand" "=r")
8567        (match_operand:SI 4 "memory_operand" "m"))
8568   (set (match_operand:SI 2 "s_register_operand" "=r")
8569        (match_operand:SI 5 "memory_operand" "m"))]
8570  "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8571  "*
8572  return emit_ldm_seq (operands, 3);
8573  "
8574)
8575
8576(define_peephole
8577  [(set (match_operand:SI 0 "s_register_operand" "=r")
8578        (match_operand:SI 2 "memory_operand" "m"))
8579   (set (match_operand:SI 1 "s_register_operand" "=r")
8580        (match_operand:SI 3 "memory_operand" "m"))]
8581  "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8582  "*
8583  return emit_ldm_seq (operands, 2);
8584  "
8585)
8586
8587(define_peephole
8588  [(set (match_operand:SI 4 "memory_operand" "=m")
8589        (match_operand:SI 0 "s_register_operand" "r"))
8590   (set (match_operand:SI 5 "memory_operand" "=m")
8591        (match_operand:SI 1 "s_register_operand" "r"))
8592   (set (match_operand:SI 6 "memory_operand" "=m")
8593        (match_operand:SI 2 "s_register_operand" "r"))
8594   (set (match_operand:SI 7 "memory_operand" "=m")
8595        (match_operand:SI 3 "s_register_operand" "r"))]
8596  "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8597  "*
8598  return emit_stm_seq (operands, 4);
8599  "
8600)
8601
8602(define_peephole
8603  [(set (match_operand:SI 3 "memory_operand" "=m")
8604        (match_operand:SI 0 "s_register_operand" "r"))
8605   (set (match_operand:SI 4 "memory_operand" "=m")
8606        (match_operand:SI 1 "s_register_operand" "r"))
8607   (set (match_operand:SI 5 "memory_operand" "=m")
8608        (match_operand:SI 2 "s_register_operand" "r"))]
8609  "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8610  "*
8611  return emit_stm_seq (operands, 3);
8612  "
8613)
8614
8615(define_peephole
8616  [(set (match_operand:SI 2 "memory_operand" "=m")
8617        (match_operand:SI 0 "s_register_operand" "r"))
8618   (set (match_operand:SI 3 "memory_operand" "=m")
8619        (match_operand:SI 1 "s_register_operand" "r"))]
8620  "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8621  "*
8622  return emit_stm_seq (operands, 2);
8623  "
8624)
8625
8626(define_split
8627  [(set (match_operand:SI 0 "s_register_operand" "")
8628	(and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8629		       (const_int 0))
8630		(neg:SI (match_operator:SI 2 "arm_comparison_operator"
8631			 [(match_operand:SI 3 "s_register_operand" "")
8632			  (match_operand:SI 4 "arm_rhs_operand" "")]))))
8633   (clobber (match_operand:SI 5 "s_register_operand" ""))]
8634  "TARGET_ARM"
8635  [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8636   (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8637			      (match_dup 5)))]
8638  ""
8639)
8640
8641;; This split can be used because CC_Z mode implies that the following
8642;; branch will be an equality, or an unsigned inequality, so the sign
8643;; extension is not needed.
8644
8645(define_split
8646  [(set (reg:CC_Z CC_REGNUM)
8647	(compare:CC_Z
8648	 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8649		    (const_int 24))
8650	 (match_operand 1 "const_int_operand" "")))
8651   (clobber (match_scratch:SI 2 ""))]
8652  "TARGET_ARM
8653   && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8654       == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8655  [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8656   (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8657  "
8658  operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8659  "
8660)
8661
8662(define_expand "prologue"
8663  [(clobber (const_int 0))]
8664  "TARGET_EITHER"
8665  "if (TARGET_ARM)
8666     arm_expand_prologue ();
8667   else
8668     thumb_expand_prologue ();
8669  DONE;
8670  "
8671)
8672
8673(define_expand "epilogue"
8674  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8675  "TARGET_EITHER"
8676  "
8677  if (TARGET_THUMB)
8678    thumb_expand_epilogue ();
8679  else if (USE_RETURN_INSN (FALSE))
8680    {
8681      emit_jump_insn (gen_return ());
8682      DONE;
8683    }
8684  emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8685	gen_rtvec (1,
8686		gen_rtx_RETURN (VOIDmode)),
8687	VUNSPEC_EPILOGUE));
8688  DONE;
8689  "
8690)
8691
8692;; Note - although unspec_volatile's USE all hard registers,
8693;; USEs are ignored after relaod has completed.  Thus we need
8694;; to add an unspec of the link register to ensure that flow
8695;; does not think that it is unused by the sibcall branch that
8696;; will replace the standard function epilogue.
8697(define_insn "sibcall_epilogue"
8698  [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8699              (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8700  "TARGET_ARM"
8701  "*
8702  if (USE_RETURN_INSN (FALSE))
8703    return output_return_instruction (const_true_rtx, FALSE, FALSE);
8704  return arm_output_epilogue (FALSE);
8705  "
8706;; Length is absolute worst case
8707  [(set_attr "length" "44")
8708   (set_attr "type" "block")
8709   ;; We don't clobber the conditions, but the potential length of this
8710   ;; operation is sufficient to make conditionalizing the sequence 
8711   ;; unlikely to be profitable.
8712   (set_attr "conds" "clob")]
8713)
8714
8715(define_insn "*epilogue_insns"
8716  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8717  "TARGET_EITHER"
8718  "*
8719  if (TARGET_ARM)
8720    return arm_output_epilogue (TRUE);
8721  else /* TARGET_THUMB */
8722    return thumb_unexpanded_epilogue ();
8723  "
8724  ; Length is absolute worst case
8725  [(set_attr "length" "44")
8726   (set_attr "type" "block")
8727   ;; We don't clobber the conditions, but the potential length of this
8728   ;; operation is sufficient to make conditionalizing the sequence 
8729   ;; unlikely to be profitable.
8730   (set_attr "conds" "clob")]
8731)
8732
8733(define_expand "eh_epilogue"
8734  [(use (match_operand:SI 0 "register_operand" "r"))
8735   (use (match_operand:SI 1 "register_operand" "r"))
8736   (use (match_operand:SI 2 "register_operand" "r"))]
8737  "TARGET_EITHER"
8738  "
8739  {
8740    cfun->machine->eh_epilogue_sp_ofs = operands[1];
8741    if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8742      {
8743	rtx ra = gen_rtx_REG (Pmode, 2);
8744
8745	emit_move_insn (ra, operands[2]);
8746	operands[2] = ra;
8747      }
8748    /* This is a hack -- we may have crystalized the function type too
8749       early.  */
8750    cfun->machine->func_type = 0;
8751  }"
8752)
8753
8754;; This split is only used during output to reduce the number of patterns
8755;; that need assembler instructions adding to them.  We allowed the setting
8756;; of the conditions to be implicit during rtl generation so that
8757;; the conditional compare patterns would work.  However this conflicts to
8758;; some extent with the conditional data operations, so we have to split them
8759;; up again here.
8760
8761(define_split
8762  [(set (match_operand:SI 0 "s_register_operand" "")
8763	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8764			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8765			 (match_dup 0)
8766			 (match_operand 4 "" "")))
8767   (clobber (reg:CC CC_REGNUM))]
8768  "TARGET_ARM && reload_completed"
8769  [(set (match_dup 5) (match_dup 6))
8770   (cond_exec (match_dup 7)
8771	      (set (match_dup 0) (match_dup 4)))]
8772  "
8773  {
8774    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8775					     operands[2], operands[3]);
8776    enum rtx_code rc = GET_CODE (operands[1]);
8777
8778    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8779    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8780    if (mode == CCFPmode || mode == CCFPEmode)
8781      rc = reverse_condition_maybe_unordered (rc);
8782    else
8783      rc = reverse_condition (rc);
8784
8785    operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8786  }"
8787)
8788
8789(define_split
8790  [(set (match_operand:SI 0 "s_register_operand" "")
8791	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8792			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8793			 (match_operand 4 "" "")
8794			 (match_dup 0)))
8795   (clobber (reg:CC CC_REGNUM))]
8796  "TARGET_ARM && reload_completed"
8797  [(set (match_dup 5) (match_dup 6))
8798   (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8799	      (set (match_dup 0) (match_dup 4)))]
8800  "
8801  {
8802    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8803					     operands[2], operands[3]);
8804
8805    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8806    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8807  }"
8808)
8809
8810(define_split
8811  [(set (match_operand:SI 0 "s_register_operand" "")
8812	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8813			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8814			 (match_operand 4 "" "")
8815			 (match_operand 5 "" "")))
8816   (clobber (reg:CC CC_REGNUM))]
8817  "TARGET_ARM && reload_completed"
8818  [(set (match_dup 6) (match_dup 7))
8819   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8820	      (set (match_dup 0) (match_dup 4)))
8821   (cond_exec (match_dup 8)
8822	      (set (match_dup 0) (match_dup 5)))]
8823  "
8824  {
8825    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8826					     operands[2], operands[3]);
8827    enum rtx_code rc = GET_CODE (operands[1]);
8828
8829    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8830    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8831    if (mode == CCFPmode || mode == CCFPEmode)
8832      rc = reverse_condition_maybe_unordered (rc);
8833    else
8834      rc = reverse_condition (rc);
8835
8836    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8837  }"
8838)
8839
8840(define_split
8841  [(set (match_operand:SI 0 "s_register_operand" "")
8842	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8843			  [(match_operand:SI 2 "s_register_operand" "")
8844			   (match_operand:SI 3 "arm_add_operand" "")])
8845			 (match_operand:SI 4 "arm_rhs_operand" "")
8846			 (not:SI
8847			  (match_operand:SI 5 "s_register_operand" ""))))
8848   (clobber (reg:CC CC_REGNUM))]
8849  "TARGET_ARM && reload_completed"
8850  [(set (match_dup 6) (match_dup 7))
8851   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8852	      (set (match_dup 0) (match_dup 4)))
8853   (cond_exec (match_dup 8)
8854	      (set (match_dup 0) (not:SI (match_dup 5))))]
8855  "
8856  {
8857    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8858					     operands[2], operands[3]);
8859    enum rtx_code rc = GET_CODE (operands[1]);
8860
8861    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8862    operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8863    if (mode == CCFPmode || mode == CCFPEmode)
8864      rc = reverse_condition_maybe_unordered (rc);
8865    else
8866      rc = reverse_condition (rc);
8867
8868    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8869  }"
8870)
8871
8872(define_insn "*cond_move_not"
8873  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8874	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
8875			  [(match_operand 3 "cc_register" "") (const_int 0)])
8876			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8877			 (not:SI
8878			  (match_operand:SI 2 "s_register_operand" "r,r"))))]
8879  "TARGET_ARM"
8880  "@
8881   mvn%D4\\t%0, %2
8882   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8883  [(set_attr "conds" "use")
8884   (set_attr "length" "4,8")]
8885)
8886
8887;; The next two patterns occur when an AND operation is followed by a
8888;; scc insn sequence 
8889
8890(define_insn "*sign_extract_onebit"
8891  [(set (match_operand:SI 0 "s_register_operand" "=r")
8892	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8893			 (const_int 1)
8894			 (match_operand:SI 2 "const_int_operand" "n")))
8895    (clobber (reg:CC CC_REGNUM))]
8896  "TARGET_ARM"
8897  "*
8898    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8899    output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8900    return \"mvnne\\t%0, #0\";
8901  "
8902  [(set_attr "conds" "clob")
8903   (set_attr "length" "8")]
8904)
8905
8906(define_insn "*not_signextract_onebit"
8907  [(set (match_operand:SI 0 "s_register_operand" "=r")
8908	(not:SI
8909	 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8910			  (const_int 1)
8911			  (match_operand:SI 2 "const_int_operand" "n"))))
8912   (clobber (reg:CC CC_REGNUM))]
8913  "TARGET_ARM"
8914  "*
8915    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8916    output_asm_insn (\"tst\\t%1, %2\", operands);
8917    output_asm_insn (\"mvneq\\t%0, #0\", operands);
8918    return \"movne\\t%0, #0\";
8919  "
8920  [(set_attr "conds" "clob")
8921   (set_attr "length" "12")]
8922)
8923
8924;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8925;; expressions.  For simplicity, the first register is also in the unspec
8926;; part.
8927(define_insn "*push_multi"
8928  [(match_parallel 2 "multi_register_push"
8929    [(set (match_operand:BLK 0 "memory_operand" "=m")
8930	  (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8931		      UNSPEC_PUSH_MULT))])]
8932  "TARGET_ARM"
8933  "*
8934  {
8935    int num_saves = XVECLEN (operands[2], 0);
8936     
8937    /* For the StrongARM at least it is faster to
8938       use STR to store only a single register.  */
8939    if (num_saves == 1)
8940      output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8941    else
8942      {
8943	int i;
8944	char pattern[100];
8945
8946	strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8947
8948	for (i = 1; i < num_saves; i++)
8949	  {
8950	    strcat (pattern, \", %|\");
8951	    strcat (pattern,
8952		    reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8953	  }
8954
8955	strcat (pattern, \"}\");
8956	output_asm_insn (pattern, operands);
8957      }
8958
8959    return \"\";
8960  }"
8961  [(set_attr "type" "store4")]
8962)
8963
8964(define_insn "stack_tie"
8965  [(set (mem:BLK (scratch))
8966	(unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8967		     (match_operand:SI 1 "s_register_operand" "r")]
8968		    UNSPEC_PRLG_STK))]
8969  ""
8970  ""
8971  [(set_attr "length" "0")]
8972)
8973
8974;; Similarly for the floating point registers
8975(define_insn "*push_fp_multi"
8976  [(match_parallel 2 "multi_register_push"
8977    [(set (match_operand:BLK 0 "memory_operand" "=m")
8978	  (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8979		      UNSPEC_PUSH_MULT))])]
8980  "TARGET_ARM"
8981  "*
8982  {
8983    char pattern[100];
8984
8985    sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8986    output_asm_insn (pattern, operands);
8987    return \"\";
8988  }"
8989  [(set_attr "type" "f_store")]
8990)
8991
8992;; Special patterns for dealing with the constant pool
8993
8994(define_insn "align_4"
8995  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8996  "TARGET_EITHER"
8997  "*
8998  assemble_align (32);
8999  return \"\";
9000  "
9001)
9002
9003(define_insn "consttable_end"
9004  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9005  "TARGET_EITHER"
9006  "*
9007  making_const_table = FALSE;
9008  return \"\";
9009  "
9010)
9011
9012(define_insn "consttable_1"
9013  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9014  "TARGET_THUMB"
9015  "*
9016  making_const_table = TRUE;
9017  assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9018  assemble_zeros (3);
9019  return \"\";
9020  "
9021  [(set_attr "length" "4")]
9022)
9023
9024(define_insn "consttable_2"
9025  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9026  "TARGET_THUMB"
9027  "*
9028  making_const_table = TRUE;
9029  assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9030  assemble_zeros (2);
9031  return \"\";
9032  "
9033  [(set_attr "length" "4")]
9034)
9035
9036(define_insn "consttable_4"
9037  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9038  "TARGET_EITHER"
9039  "*
9040  {
9041    making_const_table = TRUE;
9042    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9043      {
9044      case MODE_FLOAT:
9045      {
9046        REAL_VALUE_TYPE r;
9047        REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9048        assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9049        break;
9050      }
9051      default:
9052        assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9053        break;
9054      }
9055    return \"\";
9056  }"
9057  [(set_attr "length" "4")]
9058)
9059
9060(define_insn "consttable_8"
9061  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9062  "TARGET_EITHER"
9063  "*
9064  {
9065    making_const_table = TRUE;
9066    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9067      {
9068       case MODE_FLOAT:
9069        {
9070          REAL_VALUE_TYPE r;
9071          REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9072          assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9073          break;
9074        }
9075      default:
9076        assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9077        break;
9078      }
9079    return \"\";
9080  }"
9081  [(set_attr "length" "8")]
9082)
9083
9084;; Miscellaneous Thumb patterns
9085
9086(define_expand "tablejump"
9087  [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9088	      (use (label_ref (match_operand 1 "" "")))])]
9089  "TARGET_THUMB"
9090  "
9091  if (flag_pic)
9092    {
9093      /* Hopefully, CSE will eliminate this copy.  */
9094      rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9095      rtx reg2 = gen_reg_rtx (SImode);
9096
9097      emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9098      operands[0] = reg2;
9099    }
9100  "
9101)
9102
9103(define_insn "*thumb_tablejump"
9104  [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9105   (use (label_ref (match_operand 1 "" "")))]
9106  "TARGET_THUMB"
9107  "mov\\t%|pc, %0"
9108  [(set_attr "length" "2")]
9109)
9110
9111;; V5 Instructions,
9112
9113(define_insn "clz"
9114  [(set (match_operand:SI             0 "s_register_operand" "=r")
9115	(unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9116		   UNSPEC_CLZ))]
9117  "TARGET_ARM && arm_arch5"
9118  "clz\\t%0, %1")
9119
9120(define_expand "ffssi2"
9121  [(set (match_operand:SI 0 "s_register_operand" "")
9122	(ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9123  "TARGET_ARM && arm_arch5"
9124  "
9125  {
9126    rtx t1, t2, t3;
9127
9128    t1 = gen_reg_rtx (SImode);
9129    t2 = gen_reg_rtx (SImode);
9130    t3 = gen_reg_rtx (SImode);
9131
9132    emit_insn (gen_negsi2 (t1, operands[1]));
9133    emit_insn (gen_andsi3 (t2, operands[1], t1));
9134    emit_insn (gen_clz (t3, t2));
9135    emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9136    DONE;
9137  }"
9138)
9139
9140;; V5E instructions.
9141
9142(define_insn "prefetch"
9143  [(prefetch (match_operand:SI 0 "address_operand" "p")
9144	     (match_operand:SI 1 "" "")
9145	     (match_operand:SI 2 "" ""))]
9146  "TARGET_ARM && arm_arch5e"
9147  "pld\\t%a0")
9148
9149;; General predication pattern
9150
9151(define_cond_exec
9152  [(match_operator 0 "arm_comparison_operator"
9153    [(match_operand 1 "cc_register" "")
9154     (const_int 0)])]
9155  "TARGET_ARM"
9156  ""
9157)
9158
9159(define_insn "prologue_use"
9160  [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9161  ""
9162  "%@ %0 needed for prologue"
9163)
9164