arm.md revision 146895
1;;- Machine description for ARM for GNU compiler
2;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3;;  2001, 2002, 2003 2004  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 GCC.
9
10;; GCC is free software; you can redistribute it and/or modify it
11;; under the terms of the GNU General Public License as published
12;; by the Free Software Foundation; either version 2, or (at your
13;; option) any later version.
14
15;; GCC is distributed in the hope that it will be useful, but WITHOUT
16;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18;; License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GCC; 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
28;;---------------------------------------------------------------------------
29;; Constants
30
31;; Register numbers
32(define_constants
33  [(IP_REGNUM	    12)		; Scratch register
34   (SP_REGNUM	    13)		; Stack pointer
35   (LR_REGNUM       14)		; Return address register
36   (PC_REGNUM	    15)		; Program counter
37   (CC_REGNUM       24)		; Condition code pseudo register
38   (LAST_ARM_REGNUM 15)
39  ]
40)
41;; 3rd operand to select_dominance_cc_mode
42(define_constants
43  [(DOM_CC_X_AND_Y  0)
44   (DOM_CC_NX_OR_Y  1)
45   (DOM_CC_X_OR_Y   2)
46  ]
47)
48
49;; UNSPEC Usage:
50;; Note: sin and cos are no-longer used.
51
52(define_constants
53  [(UNSPEC_SIN       0)	; `sin' operation (MODE_FLOAT):
54			;   operand 0 is the result,
55			;   operand 1 the parameter.
56   (UNPSEC_COS	     1)	; `cos' operation (MODE_FLOAT):
57			;   operand 0 is the result,
58			;   operand 1 the parameter.
59   (UNSPEC_PUSH_MULT 2)	; `push multiple' operation:
60			;   operand 0 is the first register,
61			;   subsequent registers are in parallel (use ...)
62			;   expressions.
63   (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
64			;   usage, that is, we will add the pic_register
65			;   value to it before trying to dereference it.
66   (UNSPEC_PIC_BASE  4)	; Adding the PC value to the offset to the
67			;   GLOBAL_OFFSET_TABLE.  The operation is fully
68			;   described by the RTL but must be wrapped to
69			;   prevent combine from trying to rip it apart.
70   (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
71			;   being scheduled before the stack adjustment insn.
72   (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73   			; this unspec is used to prevent the deletion of
74   			; instructions setting registers for EH handling
75   			; and stack frame generation.  Operand 0 is the
76   			; register to "use".
77   (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78   (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79   (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80   (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81   (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82   (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83   (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84   (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85   (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86   (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87   (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88   (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89   (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
90  ]
91)
92
93;; UNSPEC_VOLATILE Usage:
94
95(define_constants
96  [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
97			;   insn in the code.
98   (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99			;   instruction epilogue sequence that isn't expanded
100			;   into normal RTL.  Used for both normal and sibcall
101			;   epilogues.
102   (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
103			;   for inlined constants.
104   (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
105			;   table.
106   (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
107			;   an 8-bit object.
108   (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
109			;   a 16-bit object.
110   (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
111			;   a 32-bit object.
112   (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
113			;   a 64-bit object.
114   (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
115   (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
116   (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
117   (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
118   (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119   (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
120  ]
121)
122
123;;---------------------------------------------------------------------------
124;; Attributes
125
126; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127; generating ARM code.  This is used to control the length of some insn
128; patterns that share the same RTL in both ARM and Thumb code.
129(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
130
131; PROG_MODE attribute is used to determine whether condition codes are
132; clobbered by a call insn: they are if in prog32 mode.  This is controlled
133; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
135
136; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137; scheduling decisions for the load unit and the multiplier.
138(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
139
140;; Operand number of an input operand that is shifted.  Zero if the
141;; given instruction does not shift one of its input operands.
142(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143(define_attr "shift" "" (const_int 0))
144
145; Floating Point Unit.  If we only have floating point emulation, then there
146; is no point in scheduling the floating point insns.  (Well, for best
147; performance we should try and group them together).
148(define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
149  (const (symbol_ref "arm_fpu_attr")))
150
151; LENGTH of an instruction (in bytes)
152(define_attr "length" "" (const_int 4))
153
154; POOL_RANGE is how far away from a constant pool entry that this insn
155; can be placed.  If the distance is zero, then this insn will never
156; reference the pool.
157; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
158; before its address.
159(define_attr "pool_range" "" (const_int 0))
160(define_attr "neg_pool_range" "" (const_int 0))
161
162; An assembler sequence may clobber the condition codes without us knowing.
163; If such an insn references the pool, then we have no way of knowing how,
164; so use the most conservative value for pool_range.
165(define_asm_attributes
166 [(set_attr "conds" "clob")
167  (set_attr "length" "4")
168  (set_attr "pool_range" "250")])
169
170; TYPE attribute is used to detect floating point instructions which, if
171; running on a co-processor can run in parallel with other, basic instructions
172; If write-buffer scheduling is enabled then it can also be used in the
173; scheduling of writes.
174
175; Classification of each insn
176; normal	any data instruction that doesn't hit memory or fp regs
177; mult		a multiply instruction
178; block		blockage insn, this blocks all functional units
179; float		a floating point arithmetic operation (subject to expansion)
180; fdivd		DFmode floating point division
181; fdivs		SFmode floating point division
182; fmul		Floating point multiply
183; ffmul		Fast floating point multiply
184; farith	Floating point arithmetic (4 cycle)
185; ffarith	Fast floating point arithmetic (2 cycle)
186; float_em	a floating point arithmetic operation that is normally emulated
187;		even on a machine with an fpa.
188; f_load	a floating point load from memory
189; f_store	a floating point store to memory
190; f_mem_r	a transfer of a floating point register to a real reg via mem
191; r_mem_f	the reverse of f_mem_r
192; f_2_r		fast transfer float to arm (no memory needed)
193; r_2_f		fast transfer arm to float
194; call		a subroutine call
195; load		any load from memory
196; store1	store 1 word to memory from arm registers
197; store2	store 2 words
198; store3	store 3 words
199; store4	store 4 words
200;  Additions for Cirrus Maverick co-processor:
201; mav_farith	Floating point arithmetic (4 cycle)
202; mav_dmult	Double multiplies (7 cycle)
203;
204(define_attr "type"
205	"normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4,mav_farith,mav_dmult" 
206	(const_string "normal"))
207
208; Load scheduling, set from the arm_ld_sched variable
209; initialized by arm_override_options() 
210(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
211
212; condition codes: this one is used by final_prescan_insn to speed up
213; conditionalizing instructions.  It saves having to scan the rtl to see if
214; it uses or alters the condition codes.
215; 
216; USE means that the condition codes are used by the insn in the process of
217;   outputting code, this means (at present) that we can't use the insn in
218;   inlined branches
219;
220; SET means that the purpose of the insn is to set the condition codes in a
221;   well defined manner.
222;
223; CLOB means that the condition codes are altered in an undefined manner, if
224;   they are altered at all
225;
226; JUMP_CLOB is used when the condition cannot be represented by a single
227;   instruction (UNEQ and LTGT).  These cannot be predicated.
228;
229; NOCOND means that the condition codes are neither altered nor affect the
230;   output of this insn
231
232(define_attr "conds" "use,set,clob,jump_clob,nocond"
233	(if_then_else (eq_attr "type" "call")
234	 (if_then_else (eq_attr "prog_mode" "prog32")
235	  (const_string "clob") (const_string "nocond"))
236	 (const_string "nocond")))
237
238; Predicable means that the insn can be conditionally executed based on
239; an automatically added predicate (additional patterns are generated by 
240; gen...).  We default to 'no' because no Thumb patterns match this rule
241; and not all ARM patterns do.
242(define_attr "predicable" "no,yes" (const_string "no"))
243
244; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
245; have one.  Later ones, such as StrongARM, have write-back caches, so don't
246; suffer blockages enough to warrant modelling this (and it can adversely
247; affect the schedule).
248(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
249
250; WRITE_CONFLICT implies that a read following an unrelated write is likely
251; to stall the processor.  Used with model_wbuf above.
252(define_attr "write_conflict" "no,yes"
253  (if_then_else (eq_attr "type"
254		 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
255		(const_string "yes")
256		(const_string "no")))
257
258; Classify the insns into those that take one cycle and those that take more
259; than one on the main cpu execution unit.
260(define_attr "core_cycles" "single,multi"
261  (if_then_else (eq_attr "type"
262		 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
263		(const_string "single")
264	        (const_string "multi")))
265
266;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
267;; distant label.  Only applicable to Thumb code.
268(define_attr "far_jump" "yes,no" (const_string "no"))
269
270(define_automaton "arm")
271
272;; Write buffer
273;
274; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
275;
276; The write buffer on some of the arm6 processors is hard to model exactly.
277; There is room in the buffer for up to two addresses and up to eight words
278; of memory, but the two needn't be split evenly.  When writing the two
279; addresses are fully pipelined.  However, a read from memory that is not
280; currently in the cache will block until the writes have completed.
281; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
282; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
283; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
284; cycle to add as well.
285(define_cpu_unit "write_buf" "arm")
286
287;; Write blockage unit
288;
289; The write_blockage unit models (partially), the fact that reads will stall
290; until the write buffer empties.
291; The f_mem_r and r_mem_f could also block, but they are to the stack,
292; so we don't model them here
293(define_cpu_unit "write_blockage" "arm")
294
295;; Core
296;
297(define_cpu_unit "core" "arm")
298
299(define_insn_reservation "r_mem_f_wbuf" 5
300  (and (eq_attr "model_wbuf" "yes")
301       (eq_attr "type" "r_mem_f"))
302  "core+write_buf*3")
303
304(define_insn_reservation "store1_wbuf" 5
305  (and (eq_attr "model_wbuf" "yes")
306       (eq_attr "type" "store1"))
307  "core+write_buf*3+write_blockage*5")
308
309(define_insn_reservation "store2_wbuf" 7
310  (and (eq_attr "model_wbuf" "yes")
311       (eq_attr "type" "store2"))
312  "core+write_buf*4+write_blockage*7")
313
314(define_insn_reservation "store3_wbuf" 9
315  (and (eq_attr "model_wbuf" "yes")
316       (eq_attr "type" "store3"))
317  "core+write_buf*5+write_blockage*9")
318
319(define_insn_reservation "store4_wbuf" 11
320  (and (eq_attr "model_wbuf" "yes")
321       (eq_attr "type" "store4"))
322  "core+write_buf*6+write_blockage*11")
323
324(define_insn_reservation "store2" 3
325  (and (eq_attr "model_wbuf" "no")
326       (eq_attr "type" "store2"))
327  "core*3")
328
329(define_insn_reservation "store3" 4
330  (and (eq_attr "model_wbuf" "no")
331       (eq_attr "type" "store3"))
332  "core*4")
333
334(define_insn_reservation "store4" 5
335  (and (eq_attr "model_wbuf" "no")
336       (eq_attr "type" "store4"))
337  "core*5")
338
339(define_insn_reservation "store1_ldsched" 1
340  (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1"))
341  "core")
342
343(define_insn_reservation "load_ldsched_xscale" 3
344  (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
345       (eq_attr "is_xscale" "yes"))
346  "core")
347
348(define_insn_reservation "load_ldsched" 2
349  (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
350       (eq_attr "is_xscale" "no"))
351  "core")
352
353(define_insn_reservation "load_or_store" 2
354  (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1"))
355  "core*2")
356
357(define_insn_reservation "mult" 16
358  (and (eq_attr "ldsched" "no") (eq_attr "type" "mult"))
359  "core*16")
360
361(define_insn_reservation "mult_ldsched_strongarm" 3
362  (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
363       (eq_attr "type" "mult"))
364  "core*2")
365
366(define_insn_reservation "mult_ldsched" 4
367  (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
368       (eq_attr "type" "mult"))
369  "core*4")
370
371(define_insn_reservation "multi_cycle" 32
372  (and (eq_attr "core_cycles" "multi")
373       (eq_attr "type" "!mult,load,store1,store2,store3,store4"))
374  "core*32")
375
376(define_insn_reservation "single_cycle" 1
377  (eq_attr "core_cycles" "single")
378  "core")
379
380
381;;---------------------------------------------------------------------------
382;; Insn patterns
383;;
384;; Addition insns.
385
386;; Note: For DImode insns, there is normally no reason why operands should
387;; not be in the same register, what we don't want is for something being
388;; written to partially overlap something that is an input.
389;; Cirrus 64bit additions should not be split because we have a native
390;; 64bit addition instructions.
391
392(define_expand "adddi3"
393 [(parallel
394   [(set (match_operand:DI           0 "s_register_operand" "")
395	  (plus:DI (match_operand:DI 1 "s_register_operand" "")
396	           (match_operand:DI 2 "s_register_operand" "")))
397    (clobber (reg:CC CC_REGNUM))])]
398  "TARGET_EITHER"
399  "
400  if (TARGET_CIRRUS)
401    {
402      if (!cirrus_fp_register (operands[0], DImode))
403        operands[0] = force_reg (DImode, operands[0]);
404      if (!cirrus_fp_register (operands[1], DImode))
405        operands[1] = force_reg (DImode, operands[1]);
406      emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
407      DONE;
408    }
409
410  if (TARGET_THUMB)
411    {
412      if (GET_CODE (operands[1]) != REG)
413        operands[1] = force_reg (SImode, operands[1]);
414      if (GET_CODE (operands[2]) != REG)
415        operands[2] = force_reg (SImode, operands[2]);
416     }
417  "
418)
419
420(define_insn "*thumb_adddi3"
421  [(set (match_operand:DI          0 "register_operand" "=l")
422	(plus:DI (match_operand:DI 1 "register_operand" "%0")
423		 (match_operand:DI 2 "register_operand" "l")))
424   (clobber (reg:CC CC_REGNUM))
425  ]
426  "TARGET_THUMB"
427  "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
428  [(set_attr "length" "4")]
429)
430
431(define_insn_and_split "*arm_adddi3"
432  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
433	(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
434		 (match_operand:DI 2 "s_register_operand" "r,  0")))
435   (clobber (reg:CC CC_REGNUM))]
436  "TARGET_ARM && !TARGET_CIRRUS"
437  "#"
438  "TARGET_ARM && reload_completed"
439  [(parallel [(set (reg:CC_C CC_REGNUM)
440		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
441				 (match_dup 1)))
442	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
443   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
444			       (plus:SI (match_dup 4) (match_dup 5))))]
445  "
446  {
447    operands[3] = gen_highpart (SImode, operands[0]);
448    operands[0] = gen_lowpart (SImode, operands[0]);
449    operands[4] = gen_highpart (SImode, operands[1]);
450    operands[1] = gen_lowpart (SImode, operands[1]);
451    operands[5] = gen_highpart (SImode, operands[2]);
452    operands[2] = gen_lowpart (SImode, operands[2]);
453  }"
454  [(set_attr "conds" "clob")
455   (set_attr "length" "8")]
456)
457
458(define_insn_and_split "*adddi_sesidi_di"
459  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
460	(plus:DI (sign_extend:DI
461		  (match_operand:SI 2 "s_register_operand" "r,r"))
462		 (match_operand:DI 1 "s_register_operand" "r,0")))
463   (clobber (reg:CC CC_REGNUM))]
464  "TARGET_ARM && !TARGET_CIRRUS"
465  "#"
466  "TARGET_ARM && reload_completed"
467  [(parallel [(set (reg:CC_C CC_REGNUM)
468		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
469				 (match_dup 1)))
470	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
471   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
472			       (plus:SI (ashiftrt:SI (match_dup 2)
473						     (const_int 31))
474					(match_dup 4))))]
475  "
476  {
477    operands[3] = gen_highpart (SImode, operands[0]);
478    operands[0] = gen_lowpart (SImode, operands[0]);
479    operands[4] = gen_highpart (SImode, operands[1]);
480    operands[1] = gen_lowpart (SImode, operands[1]);
481    operands[2] = gen_lowpart (SImode, operands[2]);
482  }"
483  [(set_attr "conds" "clob")
484   (set_attr "length" "8")]
485)
486
487(define_insn_and_split "*adddi_zesidi_di"
488  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
489	(plus:DI (zero_extend:DI
490		  (match_operand:SI 2 "s_register_operand" "r,r"))
491		 (match_operand:DI 1 "s_register_operand" "r,0")))
492   (clobber (reg:CC CC_REGNUM))]
493  "TARGET_ARM && !TARGET_CIRRUS"
494  "#"
495  "TARGET_ARM && reload_completed"
496  [(parallel [(set (reg:CC_C CC_REGNUM)
497		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
498				 (match_dup 1)))
499	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
500   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
501			       (plus:SI (match_dup 4) (const_int 0))))]
502  "
503  {
504    operands[3] = gen_highpart (SImode, operands[0]);
505    operands[0] = gen_lowpart (SImode, operands[0]);
506    operands[4] = gen_highpart (SImode, operands[1]);
507    operands[1] = gen_lowpart (SImode, operands[1]);
508    operands[2] = gen_lowpart (SImode, operands[2]);
509  }"
510  [(set_attr "conds" "clob")
511   (set_attr "length" "8")]
512)
513
514(define_expand "addsi3"
515  [(set (match_operand:SI          0 "s_register_operand" "")
516	(plus:SI (match_operand:SI 1 "s_register_operand" "")
517		 (match_operand:SI 2 "reg_or_int_operand" "")))]
518  "TARGET_EITHER"
519  "
520  if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
521    {
522      arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
523			  operands[1],
524			  (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
525      DONE;
526    }
527  "
528)
529
530; If there is a scratch available, this will be faster than synthesizing the
531; addition.
532(define_peephole2
533  [(match_scratch:SI 3 "r")
534   (set (match_operand:SI          0 "s_register_operand" "")
535	(plus:SI (match_operand:SI 1 "s_register_operand" "")
536		 (match_operand:SI 2 "const_int_operand"  "")))]
537  "TARGET_ARM &&
538   !(const_ok_for_arm (INTVAL (operands[2]))
539     || const_ok_for_arm (-INTVAL (operands[2])))
540    && const_ok_for_arm (~INTVAL (operands[2]))"
541  [(set (match_dup 3) (match_dup 2))
542   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
543  ""
544)
545
546(define_insn_and_split "*arm_addsi3"
547  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
548	(plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
549		 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
550  "TARGET_ARM"
551  "@
552   add%?\\t%0, %1, %2
553   sub%?\\t%0, %1, #%n2
554   #"
555  "TARGET_ARM &&
556   GET_CODE (operands[2]) == CONST_INT
557   && !(const_ok_for_arm (INTVAL (operands[2]))
558        || const_ok_for_arm (-INTVAL (operands[2])))"
559  [(clobber (const_int 0))]
560  "
561  arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
562		      operands[1], 0);
563  DONE;
564  "
565  [(set_attr "length" "4,4,16")
566   (set_attr "predicable" "yes")]
567)
568
569;; Register group 'k' is a single register group containing only the stack
570;; register.  Trying to reload it will always fail catastrophically,
571;; so never allow those alternatives to match if reloading is needed.
572
573(define_insn "*thumb_addsi3"
574  [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
575	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
576		 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
577  "TARGET_THUMB"
578  "*
579   static const char * const asms[] = 
580   {
581     \"add\\t%0, %0, %2\",
582     \"sub\\t%0, %0, #%n2\",
583     \"add\\t%0, %1, %2\",
584     \"add\\t%0, %0, %2\",
585     \"add\\t%0, %0, %2\",
586     \"add\\t%0, %1, %2\",
587     \"add\\t%0, %1, %2\"
588   };
589   if ((which_alternative == 2 || which_alternative == 6)
590       && GET_CODE (operands[2]) == CONST_INT
591       && INTVAL (operands[2]) < 0)
592     return \"sub\\t%0, %1, #%n2\";
593   return asms[which_alternative];
594  "
595  [(set_attr "length" "2")]
596)
597
598;; Reloading and elimination of the frame pointer can
599;; sometimes cause this optimization to be missed.
600(define_peephole2
601  [(set (match_operand:SI 0 "register_operand" "")
602	(match_operand:SI 1 "const_int_operand" ""))
603   (set (match_dup 0)
604	(plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
605  "TARGET_THUMB
606   && REGNO (operands[2]) == STACK_POINTER_REGNUM 
607   && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
608   && (INTVAL (operands[1]) & 3) == 0"
609  [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
610  ""
611)
612
613(define_insn "*addsi3_compare0"
614  [(set (reg:CC_NOOV CC_REGNUM)
615	(compare:CC_NOOV
616	 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
617		  (match_operand:SI 2 "arm_add_operand"    "rI,L"))
618	 (const_int 0)))
619   (set (match_operand:SI 0 "s_register_operand" "=r,r")
620	(plus:SI (match_dup 1) (match_dup 2)))]
621  "TARGET_ARM"
622  "@
623   add%?s\\t%0, %1, %2
624   sub%?s\\t%0, %1, #%n2"
625  [(set_attr "conds" "set")]
626)
627
628(define_insn "*addsi3_compare0_scratch"
629  [(set (reg:CC_NOOV CC_REGNUM)
630	(compare:CC_NOOV
631	 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
632		  (match_operand:SI 1 "arm_add_operand"    "rI,L"))
633	 (const_int 0)))]
634  "TARGET_ARM"
635  "@
636   cmn%?\\t%0, %1
637   cmp%?\\t%0, #%n1"
638  [(set_attr "conds" "set")]
639)
640
641;; These patterns are the same ones as the two regular addsi3_compare0
642;; patterns, except we write them slightly different - the combiner
643;; tends to generate them this way.
644(define_insn "*addsi3_compare0_for_combiner"
645  [(set (reg:CC CC_REGNUM)
646	(compare:CC
647	 (match_operand:SI 1 "s_register_operand" "r,r")
648	 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
649   (set (match_operand:SI 0 "s_register_operand" "=r,r")
650	(plus:SI (match_dup 1) (match_dup 2)))]
651  "TARGET_ARM"
652  "@
653   add%?s\\t%0, %1, %2
654   sub%?s\\t%0, %1, #%n2"
655  [(set_attr "conds" "set")]
656)
657
658(define_insn "*addsi3_compare0_scratch_for_combiner"
659  [(set (reg:CC CC_REGNUM)
660	(compare:CC
661	 (match_operand:SI 0 "s_register_operand" "r,r")
662	 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
663  "TARGET_ARM"
664  "@
665   cmn%?\\t%0, %1
666   cmp%?\\t%0, #%n1"
667  [(set_attr "conds" "set")]
668)
669
670;; This is the canonicalization of addsi3_compare0_for_combiner when the
671;; addend is a constant.
672(define_insn "*cmpsi2_addneg"
673  [(set (reg:CC CC_REGNUM)
674	(compare:CC
675	 (match_operand:SI 1 "s_register_operand" "r,r")
676	 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
677   (set (match_operand:SI 0 "s_register_operand" "=r,r")
678	(plus:SI (match_dup 1)
679		 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
680  "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
681  "@
682   sub%?s\\t%0, %1, %2
683   add%?s\\t%0, %1, #%n2"
684  [(set_attr "conds" "set")]
685)
686
687;; Convert the sequence
688;;  sub  rd, rn, #1
689;;  cmn  rd, #1	(equivalent to cmp rd, #-1)
690;;  bne  dest
691;; into
692;;  subs rd, rn, #1
693;;  bcs  dest	((unsigned)rn >= 1)
694;; similarly for the beq variant using bcc.
695;; This is a common looping idiom (while (n--))
696(define_peephole2
697  [(set (match_operand:SI 0 "s_register_operand" "")
698	(plus:SI (match_operand:SI 1 "s_register_operand" "")
699		 (const_int -1)))
700   (set (match_operand 2 "cc_register" "")
701	(compare (match_dup 0) (const_int -1)))
702   (set (pc)
703	(if_then_else (match_operator 3 "equality_operator"
704		       [(match_dup 2) (const_int 0)])
705		      (match_operand 4 "" "")
706		      (match_operand 5 "" "")))]
707  "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
708  [(parallel[
709    (set (match_dup 2)
710	 (compare:CC
711	  (match_dup 1) (const_int 1)))
712    (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
713   (set (pc)
714	(if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
715		      (match_dup 4)
716		      (match_dup 5)))]
717  "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
718   operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
719				  ? GEU : LTU),
720				 VOIDmode, 
721				 operands[2], const0_rtx);"
722)
723
724;; The next four insns work because they compare the result with one of
725;; the operands, and we know that the use of the condition code is
726;; either GEU or LTU, so we can use the carry flag from the addition
727;; instead of doing the compare a second time.
728(define_insn "*addsi3_compare_op1"
729  [(set (reg:CC_C CC_REGNUM)
730	(compare:CC_C
731	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
732		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
733	 (match_dup 1)))
734   (set (match_operand:SI 0 "s_register_operand" "=r,r")
735	(plus:SI (match_dup 1) (match_dup 2)))]
736  "TARGET_ARM"
737  "@
738   add%?s\\t%0, %1, %2
739   sub%?s\\t%0, %1, #%n2"
740  [(set_attr "conds" "set")]
741)
742
743(define_insn "*addsi3_compare_op2"
744  [(set (reg:CC_C CC_REGNUM)
745	(compare:CC_C
746	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
747		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
748	 (match_dup 2)))
749   (set (match_operand:SI 0 "s_register_operand" "=r,r")
750	(plus:SI (match_dup 1) (match_dup 2)))]
751  "TARGET_ARM"
752  "@
753   add%?s\\t%0, %1, %2
754   sub%?s\\t%0, %1, #%n2"
755  [(set_attr "conds" "set")]
756)
757
758(define_insn "*compare_addsi2_op0"
759  [(set (reg:CC_C CC_REGNUM)
760	(compare:CC_C
761	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
762		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
763	 (match_dup 0)))]
764  "TARGET_ARM"
765  "@
766   cmn%?\\t%0, %1
767   cmp%?\\t%0, #%n1"
768  [(set_attr "conds" "set")]
769)
770
771(define_insn "*compare_addsi2_op1"
772  [(set (reg:CC_C CC_REGNUM)
773	(compare:CC_C
774	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
775		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
776	 (match_dup 1)))]
777  "TARGET_ARM"
778  "@
779   cmn%?\\t%0, %1
780   cmp%?\\t%0, #%n1"
781  [(set_attr "conds" "set")]
782)
783
784(define_insn "*addsi3_carryin"
785  [(set (match_operand:SI 0 "s_register_operand" "=r")
786	(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
787		 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
788			  (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
789  "TARGET_ARM"
790  "adc%?\\t%0, %1, %2"
791  [(set_attr "conds" "use")]
792)
793
794(define_insn "*addsi3_carryin_shift"
795  [(set (match_operand:SI 0 "s_register_operand" "=r")
796	(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
797		 (plus:SI
798		   (match_operator:SI 2 "shift_operator"
799		      [(match_operand:SI 3 "s_register_operand" "r")
800		       (match_operand:SI 4 "reg_or_int_operand" "rM")])
801		    (match_operand:SI 1 "s_register_operand" "r"))))]
802  "TARGET_ARM"
803  "adc%?\\t%0, %1, %3%S2"
804  [(set_attr "conds" "use")]
805)
806
807(define_insn "*addsi3_carryin_alt1"
808  [(set (match_operand:SI 0 "s_register_operand" "=r")
809	(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
810			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
811		 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
812  "TARGET_ARM"
813  "adc%?\\t%0, %1, %2"
814  [(set_attr "conds" "use")]
815)
816
817(define_insn "*addsi3_carryin_alt2"
818  [(set (match_operand:SI 0 "s_register_operand" "=r")
819	(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
820			  (match_operand:SI 1 "s_register_operand" "r"))
821		 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
822  "TARGET_ARM"
823  "adc%?\\t%0, %1, %2"
824  [(set_attr "conds" "use")]
825)
826
827(define_insn "*addsi3_carryin_alt3"
828  [(set (match_operand:SI 0 "s_register_operand" "=r")
829	(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
830			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
831		 (match_operand:SI 1 "s_register_operand" "r")))]
832  "TARGET_ARM"
833  "adc%?\\t%0, %1, %2"
834  [(set_attr "conds" "use")]
835)
836
837(define_insn "incscc"
838  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
839        (plus:SI (match_operator:SI 2 "arm_comparison_operator"
840                    [(match_operand:CC 3 "cc_register" "") (const_int 0)])
841                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
842  "TARGET_ARM"
843  "@
844  add%d2\\t%0, %1, #1
845  mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
846  [(set_attr "conds" "use")
847   (set_attr "length" "4,8")]
848)
849
850; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
851(define_split
852  [(set (match_operand:SI 0 "s_register_operand" "")
853	(plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
854			    (match_operand:SI 2 "s_register_operand" ""))
855		 (const_int -1)))
856   (clobber (match_operand:SI 3 "s_register_operand" ""))]
857  "TARGET_ARM"
858  [(set (match_dup 3) (match_dup 1))
859   (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
860  "
861  operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
862")
863
864(define_expand "addsf3"
865  [(set (match_operand:SF          0 "s_register_operand" "")
866	(plus:SF (match_operand:SF 1 "s_register_operand" "")
867		 (match_operand:SF 2 "fpa_add_operand" "")))]
868  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
869  "
870  if (TARGET_CIRRUS
871      && !cirrus_fp_register (operands[2], SFmode))
872    operands[2] = force_reg (SFmode, operands[2]);
873")
874
875(define_expand "adddf3"
876  [(set (match_operand:DF          0 "s_register_operand" "")
877	(plus:DF (match_operand:DF 1 "s_register_operand" "")
878		 (match_operand:DF 2 "fpa_add_operand" "")))]
879  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
880  "
881  if (TARGET_CIRRUS
882      && !cirrus_fp_register (operands[2], DFmode))
883    operands[2] = force_reg (DFmode, operands[2]);
884")
885
886(define_expand "subdi3"
887 [(parallel
888   [(set (match_operand:DI            0 "s_register_operand" "")
889	  (minus:DI (match_operand:DI 1 "s_register_operand" "")
890	            (match_operand:DI 2 "s_register_operand" "")))
891    (clobber (reg:CC CC_REGNUM))])]
892  "TARGET_EITHER"
893  "
894  if (TARGET_CIRRUS
895      && TARGET_ARM
896      && cirrus_fp_register (operands[0], DImode)
897      && cirrus_fp_register (operands[1], DImode))
898    {
899      emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
900      DONE;
901    }
902
903  if (TARGET_THUMB)
904    {
905      if (GET_CODE (operands[1]) != REG)
906        operands[1] = force_reg (SImode, operands[1]);
907      if (GET_CODE (operands[2]) != REG)
908        operands[2] = force_reg (SImode, operands[2]);
909     }	
910  "
911)
912
913(define_insn "*arm_subdi3"
914  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
915	(minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
916		  (match_operand:DI 2 "s_register_operand" "r,0,0")))
917   (clobber (reg:CC CC_REGNUM))]
918  "TARGET_ARM"
919  "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
920  [(set_attr "conds" "clob")
921   (set_attr "length" "8")]
922)
923
924(define_insn "*thumb_subdi3"
925  [(set (match_operand:DI           0 "register_operand" "=l")
926	(minus:DI (match_operand:DI 1 "register_operand"  "0")
927		  (match_operand:DI 2 "register_operand"  "l")))
928   (clobber (reg:CC CC_REGNUM))]
929  "TARGET_THUMB"
930  "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
931  [(set_attr "length" "4")]
932)
933
934(define_insn "*subdi_di_zesidi"
935  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
936	(minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
937		  (zero_extend:DI
938		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
939   (clobber (reg:CC CC_REGNUM))]
940  "TARGET_ARM"
941  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
942  [(set_attr "conds" "clob")
943   (set_attr "length" "8")]
944)
945
946(define_insn "*subdi_di_sesidi"
947  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
948	(minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
949		  (sign_extend:DI
950		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
951   (clobber (reg:CC CC_REGNUM))]
952  "TARGET_ARM"
953  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
954  [(set_attr "conds" "clob")
955   (set_attr "length" "8")]
956)
957
958(define_insn "*subdi_zesidi_di"
959  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
960	(minus:DI (zero_extend:DI
961		   (match_operand:SI 2 "s_register_operand"  "r,r"))
962		  (match_operand:DI  1 "s_register_operand" "?r,0")))
963   (clobber (reg:CC CC_REGNUM))]
964  "TARGET_ARM"
965  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
966  [(set_attr "conds" "clob")
967   (set_attr "length" "8")]
968)
969
970(define_insn "*subdi_sesidi_di"
971  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
972	(minus:DI (sign_extend:DI
973		   (match_operand:SI 2 "s_register_operand"   "r,r"))
974		  (match_operand:DI  1 "s_register_operand"  "?r,0")))
975   (clobber (reg:CC CC_REGNUM))]
976  "TARGET_ARM"
977  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
978  [(set_attr "conds" "clob")
979   (set_attr "length" "8")]
980)
981
982(define_insn "*subdi_zesidi_zesidi"
983  [(set (match_operand:DI            0 "s_register_operand" "=r")
984	(minus:DI (zero_extend:DI
985		   (match_operand:SI 1 "s_register_operand"  "r"))
986		  (zero_extend:DI
987		   (match_operand:SI 2 "s_register_operand"  "r"))))
988   (clobber (reg:CC CC_REGNUM))]
989  "TARGET_ARM"
990  "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
991  [(set_attr "conds" "clob")
992   (set_attr "length" "8")]
993)
994
995(define_expand "subsi3"
996  [(set (match_operand:SI           0 "s_register_operand" "")
997	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
998		  (match_operand:SI 2 "s_register_operand" "")))]
999  "TARGET_EITHER"
1000  "
1001  if (GET_CODE (operands[1]) == CONST_INT)
1002    {
1003      if (TARGET_ARM)
1004        {
1005          arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1006	  		      operands[2],
1007			      (no_new_pseudos ? 0
1008			       :  preserve_subexpressions_p ()));
1009          DONE;
1010	}
1011      else /* TARGET_THUMB */
1012        operands[1] = force_reg (SImode, operands[1]);
1013    }
1014  "
1015)
1016
1017(define_insn "*thumb_subsi3_insn"
1018  [(set (match_operand:SI           0 "register_operand" "=l")
1019	(minus:SI (match_operand:SI 1 "register_operand" "l")
1020		  (match_operand:SI 2 "register_operand" "l")))]
1021  "TARGET_THUMB"
1022  "sub\\t%0, %1, %2"
1023  [(set_attr "length" "2")]
1024)
1025
1026(define_insn_and_split "*arm_subsi3_insn"
1027  [(set (match_operand:SI           0 "s_register_operand" "=r,r")
1028	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1029		  (match_operand:SI 2 "s_register_operand" "r,r")))]
1030  "TARGET_ARM"
1031  "@
1032   rsb%?\\t%0, %2, %1
1033   #"
1034  "TARGET_ARM
1035   && GET_CODE (operands[1]) == CONST_INT
1036   && !const_ok_for_arm (INTVAL (operands[1]))"
1037  [(clobber (const_int 0))]
1038  "
1039  arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1040		      operands[2], 0);
1041  DONE;
1042  "
1043  [(set_attr "length" "4,16")
1044   (set_attr "predicable" "yes")]
1045)
1046
1047(define_peephole2
1048  [(match_scratch:SI 3 "r")
1049   (set (match_operand:SI           0 "s_register_operand" "")
1050	(minus:SI (match_operand:SI 1 "const_int_operand" "")
1051		  (match_operand:SI 2 "s_register_operand" "")))]
1052  "TARGET_ARM
1053   && !const_ok_for_arm (INTVAL (operands[1]))
1054   && const_ok_for_arm (~INTVAL (operands[1]))"
1055  [(set (match_dup 3) (match_dup 1))
1056   (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1057  ""
1058)
1059
1060(define_insn "*subsi3_compare0"
1061  [(set (reg:CC_NOOV CC_REGNUM)
1062	(compare:CC_NOOV
1063	 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1064		   (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1065	 (const_int 0)))
1066   (set (match_operand:SI 0 "s_register_operand" "=r,r")
1067	(minus:SI (match_dup 1) (match_dup 2)))]
1068  "TARGET_ARM"
1069  "@
1070   sub%?s\\t%0, %1, %2
1071   rsb%?s\\t%0, %2, %1"
1072  [(set_attr "conds" "set")]
1073)
1074
1075(define_insn "decscc"
1076  [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1077        (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1078		  (match_operator:SI 2 "arm_comparison_operator"
1079                   [(match_operand   3 "cc_register" "") (const_int 0)])))]
1080  "TARGET_ARM"
1081  "@
1082   sub%d2\\t%0, %1, #1
1083   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1084  [(set_attr "conds" "use")
1085   (set_attr "length" "*,8")]
1086)
1087
1088(define_expand "subsf3"
1089  [(set (match_operand:SF           0 "s_register_operand" "")
1090	(minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1091		  (match_operand:SF 2 "fpa_rhs_operand" "")))]
1092  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1093  "
1094  if (TARGET_CIRRUS)
1095    {
1096      if (!cirrus_fp_register (operands[1], SFmode))
1097        operands[1] = force_reg (SFmode, operands[1]);
1098      if (!cirrus_fp_register (operands[2], SFmode))
1099        operands[2] = force_reg (SFmode, operands[2]);
1100    }
1101")
1102
1103(define_expand "subdf3"
1104  [(set (match_operand:DF           0 "s_register_operand" "")
1105	(minus:DF (match_operand:DF 1 "fpa_rhs_operand"     "")
1106		  (match_operand:DF 2 "fpa_rhs_operand"    "")))]
1107  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1108  "
1109  if (TARGET_CIRRUS)
1110    {
1111       if (!cirrus_fp_register (operands[1], DFmode))
1112         operands[1] = force_reg (DFmode, operands[1]);
1113       if (!cirrus_fp_register (operands[2], DFmode))
1114         operands[2] = force_reg (DFmode, operands[2]);
1115    }
1116")
1117
1118
1119;; Multiplication insns
1120
1121(define_expand "mulsi3"
1122  [(set (match_operand:SI          0 "s_register_operand" "")
1123	(mult:SI (match_operand:SI 2 "s_register_operand" "")
1124		 (match_operand:SI 1 "s_register_operand" "")))]
1125  "TARGET_EITHER"
1126  ""
1127)
1128
1129;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1130(define_insn "*arm_mulsi3"
1131  [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1132	(mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1133		 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1134  "TARGET_ARM"
1135  "mul%?\\t%0, %2, %1"
1136  [(set_attr "type" "mult")
1137   (set_attr "predicable" "yes")]
1138)
1139
1140; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1141; 1 and 2; are the same, because reload will make operand 0 match 
1142; operand 1 without realizing that this conflicts with operand 2.  We fix 
1143; this by adding another alternative to match this case, and then `reload' 
1144; it ourselves.  This alternative must come first.
1145(define_insn "*thumb_mulsi3"
1146  [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1147	(mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1148		 (match_operand:SI 2 "register_operand" "l,l,l")))]
1149  "TARGET_THUMB"
1150  "*
1151  if (which_alternative < 2)
1152    return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1153  else
1154    return \"mul\\t%0, %0, %2\";
1155  "
1156  [(set_attr "length" "4,4,2")
1157   (set_attr "type" "mult")]
1158)
1159
1160(define_insn "*mulsi3_compare0"
1161  [(set (reg:CC_NOOV CC_REGNUM)
1162	(compare:CC_NOOV (mult:SI
1163			  (match_operand:SI 2 "s_register_operand" "r,r")
1164			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
1165			 (const_int 0)))
1166   (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1167	(mult:SI (match_dup 2) (match_dup 1)))]
1168  "TARGET_ARM && !arm_arch_xscale"
1169  "mul%?s\\t%0, %2, %1"
1170  [(set_attr "conds" "set")
1171   (set_attr "type" "mult")]
1172)
1173
1174(define_insn "*mulsi_compare0_scratch"
1175  [(set (reg:CC_NOOV CC_REGNUM)
1176	(compare:CC_NOOV (mult:SI
1177			  (match_operand:SI 2 "s_register_operand" "r,r")
1178			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
1179			 (const_int 0)))
1180   (clobber (match_scratch:SI 0 "=&r,&r"))]
1181  "TARGET_ARM && !arm_arch_xscale"
1182  "mul%?s\\t%0, %2, %1"
1183  [(set_attr "conds" "set")
1184   (set_attr "type" "mult")]
1185)
1186
1187;; Unnamed templates to match MLA instruction.
1188
1189(define_insn "*mulsi3addsi"
1190  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1191	(plus:SI
1192	  (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1193		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1194	  (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1195  "TARGET_ARM"
1196  "mla%?\\t%0, %2, %1, %3"
1197  [(set_attr "type" "mult")
1198   (set_attr "predicable" "yes")]
1199)
1200
1201(define_insn "*mulsi3addsi_compare0"
1202  [(set (reg:CC_NOOV CC_REGNUM)
1203	(compare:CC_NOOV
1204	 (plus:SI (mult:SI
1205		   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1206		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1207		  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1208	 (const_int 0)))
1209   (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1210	(plus:SI (mult:SI (match_dup 2) (match_dup 1))
1211		 (match_dup 3)))]
1212  "TARGET_ARM && !arm_arch_xscale"
1213  "mla%?s\\t%0, %2, %1, %3"
1214  [(set_attr "conds" "set")
1215   (set_attr "type" "mult")]
1216)
1217
1218(define_insn "*mulsi3addsi_compare0_scratch"
1219  [(set (reg:CC_NOOV CC_REGNUM)
1220	(compare:CC_NOOV
1221	 (plus:SI (mult:SI
1222		   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1223		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1224		  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1225	 (const_int 0)))
1226   (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1227  "TARGET_ARM && !arm_arch_xscale"
1228  "mla%?s\\t%0, %2, %1, %3"
1229  [(set_attr "conds" "set")
1230   (set_attr "type" "mult")]
1231)
1232
1233;; Unnamed template to match long long multiply-accumulate (smlal)
1234
1235(define_insn "*mulsidi3adddi"
1236  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1237	(plus:DI
1238	 (mult:DI
1239	  (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1240	  (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1241	 (match_operand:DI 1 "s_register_operand" "0")))]
1242  "TARGET_ARM && arm_fast_multiply"
1243  "smlal%?\\t%Q0, %R0, %3, %2"
1244  [(set_attr "type" "mult")
1245   (set_attr "predicable" "yes")]
1246)
1247
1248(define_insn "mulsidi3"
1249  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1250	(mult:DI
1251	 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1252	 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1253  "TARGET_ARM && arm_fast_multiply"
1254  "smull%?\\t%Q0, %R0, %1, %2"
1255  [(set_attr "type" "mult")
1256   (set_attr "predicable" "yes")]
1257)
1258
1259(define_insn "umulsidi3"
1260  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1261	(mult:DI
1262	 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1263	 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1264  "TARGET_ARM && arm_fast_multiply"
1265  "umull%?\\t%Q0, %R0, %1, %2"
1266  [(set_attr "type" "mult")
1267   (set_attr "predicable" "yes")]
1268)
1269
1270;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1271
1272(define_insn "*umulsidi3adddi"
1273  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1274	(plus:DI
1275	 (mult:DI
1276	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1277	  (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1278	 (match_operand:DI 1 "s_register_operand" "0")))]
1279  "TARGET_ARM && arm_fast_multiply"
1280  "umlal%?\\t%Q0, %R0, %3, %2"
1281  [(set_attr "type" "mult")
1282   (set_attr "predicable" "yes")]
1283)
1284
1285(define_insn "smulsi3_highpart"
1286  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1287	(truncate:SI
1288	 (lshiftrt:DI
1289	  (mult:DI
1290	   (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1291	   (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1292	  (const_int 32))))
1293   (clobber (match_scratch:SI 3 "=&r,&r"))]
1294  "TARGET_ARM && arm_fast_multiply"
1295  "smull%?\\t%3, %0, %2, %1"
1296  [(set_attr "type" "mult")
1297   (set_attr "predicable" "yes")]
1298)
1299
1300(define_insn "umulsi3_highpart"
1301  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1302	(truncate:SI
1303	 (lshiftrt:DI
1304	  (mult:DI
1305	   (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1306	   (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1307	  (const_int 32))))
1308   (clobber (match_scratch:SI 3 "=&r,&r"))]
1309  "TARGET_ARM && arm_fast_multiply"
1310  "umull%?\\t%3, %0, %2, %1"
1311  [(set_attr "type" "mult")
1312   (set_attr "predicable" "yes")]
1313)
1314
1315(define_insn "mulhisi3"
1316  [(set (match_operand:SI 0 "s_register_operand" "=r")
1317	(mult:SI (sign_extend:SI
1318		  (match_operand:HI 1 "s_register_operand" "%r"))
1319		 (sign_extend:SI
1320		  (match_operand:HI 2 "s_register_operand" "r"))))]
1321  "TARGET_ARM && arm_arch5e"
1322  "smulbb%?\\t%0, %1, %2"
1323  [(set_attr "type" "mult")
1324   (set_attr "predicable" "yes")]
1325)
1326
1327(define_insn "*mulhisi3tb"
1328  [(set (match_operand:SI 0 "s_register_operand" "=r")
1329	(mult:SI (ashiftrt:SI
1330		  (match_operand:SI 1 "s_register_operand" "r")
1331		  (const_int 16))
1332		 (sign_extend:SI
1333		  (match_operand:HI 2 "s_register_operand" "r"))))]
1334  "TARGET_ARM && arm_arch5e"
1335  "smultb%?\\t%0, %1, %2"
1336  [(set_attr "type" "mult")
1337   (set_attr "predicable" "yes")]
1338)
1339
1340(define_insn "*mulhisi3bt"
1341  [(set (match_operand:SI 0 "s_register_operand" "=r")
1342	(mult:SI (sign_extend:SI
1343		  (match_operand:HI 1 "s_register_operand" "r"))
1344		 (ashiftrt:SI
1345		  (match_operand:SI 2 "s_register_operand" "r")
1346		  (const_int 16))))]
1347  "TARGET_ARM && arm_arch5e"
1348  "smulbt%?\\t%0, %1, %2"
1349  [(set_attr "type" "mult")
1350   (set_attr "predicable" "yes")]
1351)
1352
1353(define_insn "*mulhisi3tt"
1354  [(set (match_operand:SI 0 "s_register_operand" "=r")
1355	(mult:SI (ashiftrt:SI
1356		  (match_operand:SI 1 "s_register_operand" "r")
1357		  (const_int 16))
1358		 (ashiftrt:SI
1359		  (match_operand:SI 2 "s_register_operand" "r")
1360		  (const_int 16))))]
1361  "TARGET_ARM && arm_arch5e"
1362  "smultt%?\\t%0, %1, %2"
1363  [(set_attr "type" "mult")
1364   (set_attr "predicable" "yes")]
1365)
1366
1367(define_insn "*mulhisi3addsi"
1368  [(set (match_operand:SI 0 "s_register_operand" "=r")
1369	(plus:SI (match_operand:SI 1 "s_register_operand" "r")
1370		 (mult:SI (sign_extend:SI
1371			   (match_operand:HI 2 "s_register_operand" "%r"))
1372			  (sign_extend:SI
1373			   (match_operand:HI 3 "s_register_operand" "r")))))]
1374  "TARGET_ARM && arm_arch5e"
1375  "smlabb%?\\t%0, %2, %3, %1"
1376  [(set_attr "type" "mult")
1377   (set_attr "predicable" "yes")]
1378)
1379
1380(define_insn "*mulhidi3adddi"
1381  [(set (match_operand:DI 0 "s_register_operand" "=r")
1382	(plus:DI
1383	  (match_operand:DI 1 "s_register_operand" "0")
1384	  (mult:DI (sign_extend:DI
1385	 	    (match_operand:HI 2 "s_register_operand" "%r"))
1386		   (sign_extend:DI
1387		    (match_operand:HI 3 "s_register_operand" "r")))))]
1388  "TARGET_ARM && arm_arch5e"
1389  "smlalbb%?\\t%Q0, %R0, %2, %3"
1390  [(set_attr "type" "mult")
1391   (set_attr "predicable" "yes")])
1392
1393(define_expand "mulsf3"
1394  [(set (match_operand:SF          0 "s_register_operand" "")
1395	(mult:SF (match_operand:SF 1 "s_register_operand" "")
1396		 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1397  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1398  "
1399  if (TARGET_CIRRUS
1400      && !cirrus_fp_register (operands[2], SFmode))
1401    operands[2] = force_reg (SFmode, operands[2]);
1402")
1403
1404(define_expand "muldf3"
1405  [(set (match_operand:DF          0 "s_register_operand" "")
1406	(mult:DF (match_operand:DF 1 "s_register_operand" "")
1407		 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1408  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1409  "
1410  if (TARGET_CIRRUS
1411      && !cirrus_fp_register (operands[2], DFmode))
1412    operands[2] = force_reg (DFmode, operands[2]);
1413")
1414
1415;; Division insns
1416
1417(define_expand "divsf3"
1418  [(set (match_operand:SF 0 "s_register_operand" "")
1419	(div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1420		(match_operand:SF 2 "fpa_rhs_operand" "")))]
1421  "TARGET_ARM && TARGET_HARD_FLOAT"
1422  "")
1423
1424(define_expand "divdf3"
1425  [(set (match_operand:DF 0 "s_register_operand" "")
1426	(div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1427		(match_operand:DF 2 "fpa_rhs_operand" "")))]
1428  "TARGET_ARM && TARGET_HARD_FLOAT"
1429  "")
1430
1431;; Modulo insns
1432
1433(define_expand "modsf3"
1434  [(set (match_operand:SF 0 "s_register_operand" "")
1435	(mod:SF (match_operand:SF 1 "s_register_operand" "")
1436		(match_operand:SF 2 "fpa_rhs_operand" "")))]
1437  "TARGET_ARM && TARGET_HARD_FLOAT"
1438  "")
1439
1440(define_expand "moddf3"
1441  [(set (match_operand:DF 0 "s_register_operand" "")
1442	(mod:DF (match_operand:DF 1 "s_register_operand" "")
1443		(match_operand:DF 2 "fpa_rhs_operand" "")))]
1444  "TARGET_ARM && TARGET_HARD_FLOAT"
1445  "")
1446
1447;; Boolean and,ior,xor insns
1448
1449;; Split up double word logical operations
1450
1451;; Split up simple DImode logical operations.  Simply perform the logical
1452;; operation on the upper and lower halves of the registers.
1453(define_split
1454  [(set (match_operand:DI 0 "s_register_operand" "")
1455	(match_operator:DI 6 "logical_binary_operator"
1456	  [(match_operand:DI 1 "s_register_operand" "")
1457	   (match_operand:DI 2 "s_register_operand" "")]))]
1458  "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1459  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1460   (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1461  "
1462  {
1463    operands[3] = gen_highpart (SImode, operands[0]);
1464    operands[0] = gen_lowpart (SImode, operands[0]);
1465    operands[4] = gen_highpart (SImode, operands[1]);
1466    operands[1] = gen_lowpart (SImode, operands[1]);
1467    operands[5] = gen_highpart (SImode, operands[2]);
1468    operands[2] = gen_lowpart (SImode, operands[2]);
1469  }"
1470)
1471
1472(define_split
1473  [(set (match_operand:DI 0 "s_register_operand" "")
1474	(match_operator:DI 6 "logical_binary_operator"
1475	  [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1476	   (match_operand:DI 1 "s_register_operand" "")]))]
1477  "TARGET_ARM && reload_completed"
1478  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1479   (set (match_dup 3) (match_op_dup:SI 6
1480			[(ashiftrt:SI (match_dup 2) (const_int 31))
1481			 (match_dup 4)]))]
1482  "
1483  {
1484    operands[3] = gen_highpart (SImode, operands[0]);
1485    operands[0] = gen_lowpart (SImode, operands[0]);
1486    operands[4] = gen_highpart (SImode, operands[1]);
1487    operands[1] = gen_lowpart (SImode, operands[1]);
1488    operands[5] = gen_highpart (SImode, operands[2]);
1489    operands[2] = gen_lowpart (SImode, operands[2]);
1490  }"
1491)
1492
1493;; The zero extend of operand 2 means we can just copy the high part of
1494;; operand1 into operand0.
1495(define_split
1496  [(set (match_operand:DI 0 "s_register_operand" "")
1497	(ior:DI
1498	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1499	  (match_operand:DI 1 "s_register_operand" "")))]
1500  "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1501  [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1502   (set (match_dup 3) (match_dup 4))]
1503  "
1504  {
1505    operands[4] = gen_highpart (SImode, operands[1]);
1506    operands[3] = gen_highpart (SImode, operands[0]);
1507    operands[0] = gen_lowpart (SImode, operands[0]);
1508    operands[1] = gen_lowpart (SImode, operands[1]);
1509  }"
1510)
1511
1512;; The zero extend of operand 2 means we can just copy the high part of
1513;; operand1 into operand0.
1514(define_split
1515  [(set (match_operand:DI 0 "s_register_operand" "")
1516	(xor:DI
1517	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1518	  (match_operand:DI 1 "s_register_operand" "")))]
1519  "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1520  [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1521   (set (match_dup 3) (match_dup 4))]
1522  "
1523  {
1524    operands[4] = gen_highpart (SImode, operands[1]);
1525    operands[3] = gen_highpart (SImode, operands[0]);
1526    operands[0] = gen_lowpart (SImode, operands[0]);
1527    operands[1] = gen_lowpart (SImode, operands[1]);
1528  }"
1529)
1530
1531(define_insn "anddi3"
1532  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1533	(and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1534		(match_operand:DI 2 "s_register_operand"   "r,r")))]
1535  "TARGET_ARM && ! TARGET_IWMMXT"
1536  "#"
1537  [(set_attr "length" "8")]
1538)
1539
1540(define_insn_and_split "*anddi_zesidi_di"
1541  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1542	(and:DI (zero_extend:DI
1543		 (match_operand:SI 2 "s_register_operand" "r,r"))
1544		(match_operand:DI 1 "s_register_operand" "?r,0")))]
1545  "TARGET_ARM"
1546  "#"
1547  "TARGET_ARM && reload_completed"
1548  ; The zero extend of operand 2 clears the high word of the output
1549  ; operand.
1550  [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1551   (set (match_dup 3) (const_int 0))]
1552  "
1553  {
1554    operands[3] = gen_highpart (SImode, operands[0]);
1555    operands[0] = gen_lowpart (SImode, operands[0]);
1556    operands[1] = gen_lowpart (SImode, operands[1]);
1557  }"
1558  [(set_attr "length" "8")]
1559)
1560
1561(define_insn "*anddi_sesdi_di"
1562  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1563	(and:DI (sign_extend:DI
1564		 (match_operand:SI 2 "s_register_operand" "r,r"))
1565		(match_operand:DI  1 "s_register_operand" "?r,0")))]
1566  "TARGET_ARM"
1567  "#"
1568  [(set_attr "length" "8")]
1569)
1570
1571(define_expand "andsi3"
1572  [(set (match_operand:SI         0 "s_register_operand" "")
1573	(and:SI (match_operand:SI 1 "s_register_operand" "")
1574		(match_operand:SI 2 "reg_or_int_operand" "")))]
1575  "TARGET_EITHER"
1576  "
1577  if (TARGET_ARM)
1578    {
1579      if (GET_CODE (operands[2]) == CONST_INT)
1580        {
1581          arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1582			      operands[1],
1583			      (no_new_pseudos
1584			       ? 0 : preserve_subexpressions_p ()));
1585          DONE;
1586        }
1587    }
1588  else /* TARGET_THUMB */
1589    {
1590      if (GET_CODE (operands[2]) != CONST_INT)
1591        operands[2] = force_reg (SImode, operands[2]);
1592      else
1593        {
1594          int i;
1595	  
1596          if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1597  	    {
1598	      operands[2] = force_reg (SImode,
1599				       GEN_INT (~INTVAL (operands[2])));
1600	      
1601	      emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1602	      
1603	      DONE;
1604	    }
1605
1606          for (i = 9; i <= 31; i++)
1607	    {
1608	      if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1609	        {
1610	          emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1611			 	        const0_rtx));
1612	          DONE;
1613	        }
1614	      else if ((((HOST_WIDE_INT) 1) << i) - 1
1615		       == ~INTVAL (operands[2]))
1616	        {
1617	          rtx shift = GEN_INT (i);
1618	          rtx reg = gen_reg_rtx (SImode);
1619		
1620	          emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1621	          emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1622		  
1623	          DONE;
1624	        }
1625	    }
1626
1627          operands[2] = force_reg (SImode, operands[2]);
1628        }
1629    }
1630  "
1631)
1632
1633(define_insn_and_split "*arm_andsi3_insn"
1634  [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1635	(and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1636		(match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1637  "TARGET_ARM"
1638  "@
1639   and%?\\t%0, %1, %2
1640   bic%?\\t%0, %1, #%B2
1641   #"
1642  "TARGET_ARM
1643   && GET_CODE (operands[2]) == CONST_INT
1644   && !(const_ok_for_arm (INTVAL (operands[2]))
1645	|| const_ok_for_arm (~INTVAL (operands[2])))"
1646  [(clobber (const_int 0))]
1647  "
1648  arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1649		       operands[1], 0);
1650  DONE;
1651  "
1652  [(set_attr "length" "4,4,16")
1653   (set_attr "predicable" "yes")]
1654)
1655
1656(define_insn "*thumb_andsi3_insn"
1657  [(set (match_operand:SI         0 "register_operand" "=l")
1658	(and:SI (match_operand:SI 1 "register_operand" "%0")
1659		(match_operand:SI 2 "register_operand" "l")))]
1660  "TARGET_THUMB"
1661  "and\\t%0, %0, %2"
1662  [(set_attr "length" "2")]
1663)
1664
1665(define_insn "*andsi3_compare0"
1666  [(set (reg:CC_NOOV CC_REGNUM)
1667	(compare:CC_NOOV
1668	 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1669		 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1670	 (const_int 0)))
1671   (set (match_operand:SI          0 "s_register_operand" "=r,r")
1672	(and:SI (match_dup 1) (match_dup 2)))]
1673  "TARGET_ARM"
1674  "@
1675   and%?s\\t%0, %1, %2
1676   bic%?s\\t%0, %1, #%B2"
1677  [(set_attr "conds" "set")]
1678)
1679
1680(define_insn "*andsi3_compare0_scratch"
1681  [(set (reg:CC_NOOV CC_REGNUM)
1682	(compare:CC_NOOV
1683	 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1684		 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1685	 (const_int 0)))
1686   (clobber (match_scratch:SI 2 "=X,r"))]
1687  "TARGET_ARM"
1688  "@
1689   tst%?\\t%0, %1
1690   bic%?s\\t%2, %0, #%B1"
1691  [(set_attr "conds" "set")]
1692)
1693
1694(define_insn "*zeroextractsi_compare0_scratch"
1695  [(set (reg:CC_NOOV CC_REGNUM)
1696	(compare:CC_NOOV (zero_extract:SI
1697			  (match_operand:SI 0 "s_register_operand" "r")
1698		 	  (match_operand 1 "const_int_operand" "n")
1699			  (match_operand 2 "const_int_operand" "n"))
1700			 (const_int 0)))]
1701  "TARGET_ARM
1702  && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1703      && INTVAL (operands[1]) > 0 
1704      && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1705      && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1706  "*
1707  operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1708			 << INTVAL (operands[2]));
1709  output_asm_insn (\"tst%?\\t%0, %1\", operands);
1710  return \"\";
1711  "
1712  [(set_attr "conds" "set")]
1713)
1714
1715(define_insn "*ne_zeroextractsi"
1716  [(set (match_operand:SI 0 "s_register_operand" "=r")
1717	(ne:SI (zero_extract:SI
1718		(match_operand:SI 1 "s_register_operand" "r")
1719		(match_operand:SI 2 "const_int_operand" "n")
1720		(match_operand:SI 3 "const_int_operand" "n"))
1721	       (const_int 0)))
1722   (clobber (reg:CC CC_REGNUM))]
1723  "TARGET_ARM
1724   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1725       && INTVAL (operands[2]) > 0 
1726       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1727       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1728  "*
1729  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1730			 << INTVAL (operands[3]));
1731  output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1732  return \"movne\\t%0, #1\";
1733  "
1734  [(set_attr "conds" "clob")
1735   (set_attr "length" "8")]
1736)
1737
1738(define_split
1739  [(set (match_operand:SI 0 "s_register_operand" "")
1740	(zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1741			 (match_operand:SI 2 "const_int_operand" "")
1742			 (match_operand:SI 3 "const_int_operand" "")))
1743   (clobber (match_operand:SI 4 "s_register_operand" ""))]
1744  "TARGET_THUMB"
1745  [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1746   (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1747  "{
1748     HOST_WIDE_INT temp = INTVAL (operands[2]);
1749
1750     operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1751     operands[3] = GEN_INT (32 - temp);
1752   }"
1753)
1754
1755(define_split
1756  [(set (match_operand:SI 0 "s_register_operand" "")
1757	(match_operator:SI 1 "shiftable_operator"
1758	 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1759			   (match_operand:SI 3 "const_int_operand" "")
1760			   (match_operand:SI 4 "const_int_operand" ""))
1761	  (match_operand:SI 5 "s_register_operand" "")]))
1762   (clobber (match_operand:SI 6 "s_register_operand" ""))]
1763  "TARGET_ARM"
1764  [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1765   (set (match_dup 0)
1766	(match_op_dup 1
1767	 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1768	  (match_dup 5)]))]
1769  "{
1770     HOST_WIDE_INT temp = INTVAL (operands[3]);
1771
1772     operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1773     operands[4] = GEN_INT (32 - temp);
1774   }"
1775)
1776  
1777(define_split
1778  [(set (match_operand:SI 0 "s_register_operand" "")
1779	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1780			 (match_operand:SI 2 "const_int_operand" "")
1781			 (match_operand:SI 3 "const_int_operand" "")))]
1782  "TARGET_THUMB"
1783  [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1784   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1785  "{
1786     HOST_WIDE_INT temp = INTVAL (operands[2]);
1787
1788     operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1789     operands[3] = GEN_INT (32 - temp);
1790   }"
1791)
1792
1793(define_split
1794  [(set (match_operand:SI 0 "s_register_operand" "")
1795	(match_operator:SI 1 "shiftable_operator"
1796	 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1797			   (match_operand:SI 3 "const_int_operand" "")
1798			   (match_operand:SI 4 "const_int_operand" ""))
1799	  (match_operand:SI 5 "s_register_operand" "")]))
1800   (clobber (match_operand:SI 6 "s_register_operand" ""))]
1801  "TARGET_ARM"
1802  [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1803   (set (match_dup 0)
1804	(match_op_dup 1
1805	 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1806	  (match_dup 5)]))]
1807  "{
1808     HOST_WIDE_INT temp = INTVAL (operands[3]);
1809
1810     operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1811     operands[4] = GEN_INT (32 - temp);
1812   }"
1813)
1814  
1815;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1816;;; represented by the bitfield, then this will produce incorrect results.
1817;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1818;;; which have a real bit-field insert instruction, the truncation happens
1819;;; in the bit-field insert instruction itself.  Since arm does not have a
1820;;; bit-field insert instruction, we would have to emit code here to truncate
1821;;; the value before we insert.  This loses some of the advantage of having
1822;;; this insv pattern, so this pattern needs to be reevalutated.
1823
1824(define_expand "insv"
1825  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1826                         (match_operand:SI 1 "general_operand" "")
1827                         (match_operand:SI 2 "general_operand" ""))
1828        (match_operand:SI 3 "reg_or_int_operand" ""))]
1829  "TARGET_ARM"
1830  "
1831  {
1832    int start_bit = INTVAL (operands[2]);
1833    int width = INTVAL (operands[1]);
1834    HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1835    rtx target, subtarget;
1836
1837    target = operands[0];
1838    /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1839       subreg as the final target.  */
1840    if (GET_CODE (target) == SUBREG)
1841      {
1842	subtarget = gen_reg_rtx (SImode);
1843	if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1844	    < GET_MODE_SIZE (SImode))
1845	  target = SUBREG_REG (target);
1846      }
1847    else
1848      subtarget = target;    
1849
1850    if (GET_CODE (operands[3]) == CONST_INT)
1851      {
1852	/* Since we are inserting a known constant, we may be able to
1853	   reduce the number of bits that we have to clear so that
1854	   the mask becomes simple.  */
1855	/* ??? This code does not check to see if the new mask is actually
1856	   simpler.  It may not be.  */
1857	rtx op1 = gen_reg_rtx (SImode);
1858	/* ??? Truncate operand3 to fit in the bitfield.  See comment before
1859	   start of this pattern.  */
1860	HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1861	HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1862
1863	emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1864	emit_insn (gen_iorsi3 (subtarget, op1,
1865			       GEN_INT (op3_value << start_bit)));
1866      }
1867    else if (start_bit == 0
1868	     && !(const_ok_for_arm (mask)
1869		  || const_ok_for_arm (~mask)))
1870      {
1871	/* A Trick, since we are setting the bottom bits in the word,
1872	   we can shift operand[3] up, operand[0] down, OR them together
1873	   and rotate the result back again.  This takes 3 insns, and
1874	   the third might be mergeable into another op.  */
1875	/* The shift up copes with the possibility that operand[3] is
1876           wider than the bitfield.  */
1877	rtx op0 = gen_reg_rtx (SImode);
1878	rtx op1 = gen_reg_rtx (SImode);
1879
1880	emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1881	emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1882	emit_insn (gen_iorsi3  (op1, op1, op0));
1883	emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1884      }
1885    else if ((width + start_bit == 32)
1886	     && !(const_ok_for_arm (mask)
1887		  || const_ok_for_arm (~mask)))
1888      {
1889	/* Similar trick, but slightly less efficient.  */
1890
1891	rtx op0 = gen_reg_rtx (SImode);
1892	rtx op1 = gen_reg_rtx (SImode);
1893
1894	emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1895	emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1896	emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1897	emit_insn (gen_iorsi3 (subtarget, op1, op0));
1898      }
1899    else
1900      {
1901	rtx op0 = GEN_INT (mask);
1902	rtx op1 = gen_reg_rtx (SImode);
1903	rtx op2 = gen_reg_rtx (SImode);
1904
1905	if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1906	  {
1907	    rtx tmp = gen_reg_rtx (SImode);
1908
1909	    emit_insn (gen_movsi (tmp, op0));
1910	    op0 = tmp;
1911	  }
1912
1913	/* Mask out any bits in operand[3] that are not needed.  */
1914	   emit_insn (gen_andsi3 (op1, operands[3], op0));
1915
1916	if (GET_CODE (op0) == CONST_INT
1917	    && (const_ok_for_arm (mask << start_bit)
1918		|| const_ok_for_arm (~(mask << start_bit))))
1919	  {
1920	    op0 = GEN_INT (~(mask << start_bit));
1921	    emit_insn (gen_andsi3 (op2, operands[0], op0));
1922	  }
1923	else
1924	  {
1925	    if (GET_CODE (op0) == CONST_INT)
1926	      {
1927		rtx tmp = gen_reg_rtx (SImode);
1928
1929		emit_insn (gen_movsi (tmp, op0));
1930		op0 = tmp;
1931	      }
1932
1933	    if (start_bit != 0)
1934	      emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1935	    
1936	    emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1937	  }
1938
1939	if (start_bit != 0)
1940          emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1941
1942	emit_insn (gen_iorsi3 (subtarget, op1, op2));
1943      }
1944
1945    if (subtarget != target)
1946      {
1947	/* If TARGET is still a SUBREG, then it must be wider than a word,
1948	   so we must be careful only to set the subword we were asked to.  */
1949	if (GET_CODE (target) == SUBREG)
1950	  emit_move_insn (target, subtarget);
1951	else
1952	  emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1953      }
1954
1955    DONE;
1956  }"
1957)
1958
1959; constants for op 2 will never be given to these patterns.
1960(define_insn_and_split "*anddi_notdi_di"
1961  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1962	(and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1963		(match_operand:DI 2 "s_register_operand" "0,r")))]
1964  "TARGET_ARM"
1965  "#"
1966  "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1967  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1968   (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1969  "
1970  {
1971    operands[3] = gen_highpart (SImode, operands[0]);
1972    operands[0] = gen_lowpart (SImode, operands[0]);
1973    operands[4] = gen_highpart (SImode, operands[1]);
1974    operands[1] = gen_lowpart (SImode, operands[1]);
1975    operands[5] = gen_highpart (SImode, operands[2]);
1976    operands[2] = gen_lowpart (SImode, operands[2]);
1977  }"
1978  [(set_attr "length" "8")
1979   (set_attr "predicable" "yes")]
1980)
1981  
1982(define_insn_and_split "*anddi_notzesidi_di"
1983  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1984	(and:DI (not:DI (zero_extend:DI
1985			 (match_operand:SI 2 "s_register_operand" "r,r")))
1986		(match_operand:DI 1 "s_register_operand" "0,?r")))]
1987  "TARGET_ARM"
1988  "@
1989   bic%?\\t%Q0, %Q1, %2
1990   #"
1991  ; (not (zero_extend ...)) allows us to just copy the high word from
1992  ; operand1 to operand0.
1993  "TARGET_ARM
1994   && reload_completed
1995   && operands[0] != operands[1]"
1996  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1997   (set (match_dup 3) (match_dup 4))]
1998  "
1999  {
2000    operands[3] = gen_highpart (SImode, operands[0]);
2001    operands[0] = gen_lowpart (SImode, operands[0]);
2002    operands[4] = gen_highpart (SImode, operands[1]);
2003    operands[1] = gen_lowpart (SImode, operands[1]);
2004  }"
2005  [(set_attr "length" "4,8")
2006   (set_attr "predicable" "yes")]
2007)
2008  
2009(define_insn_and_split "*anddi_notsesidi_di"
2010  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2011	(and:DI (not:DI (sign_extend:DI
2012			 (match_operand:SI 2 "s_register_operand" "r,r")))
2013		(match_operand:DI 1 "s_register_operand" "0,r")))]
2014  "TARGET_ARM"
2015  "#"
2016  "TARGET_ARM && reload_completed"
2017  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2018   (set (match_dup 3) (and:SI (not:SI
2019				(ashiftrt:SI (match_dup 2) (const_int 31)))
2020			       (match_dup 4)))]
2021  "
2022  {
2023    operands[3] = gen_highpart (SImode, operands[0]);
2024    operands[0] = gen_lowpart (SImode, operands[0]);
2025    operands[4] = gen_highpart (SImode, operands[1]);
2026    operands[1] = gen_lowpart (SImode, operands[1]);
2027  }"
2028  [(set_attr "length" "8")
2029   (set_attr "predicable" "yes")]
2030)
2031  
2032(define_insn "andsi_notsi_si"
2033  [(set (match_operand:SI 0 "s_register_operand" "=r")
2034	(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2035		(match_operand:SI 1 "s_register_operand" "r")))]
2036  "TARGET_ARM"
2037  "bic%?\\t%0, %1, %2"
2038  [(set_attr "predicable" "yes")]
2039)
2040
2041(define_insn "bicsi3"
2042  [(set (match_operand:SI                 0 "register_operand" "=l")
2043	(and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2044		(match_operand:SI         2 "register_operand" "0")))]
2045  "TARGET_THUMB"
2046  "bic\\t%0, %0, %1"
2047  [(set_attr "length" "2")]
2048)
2049
2050(define_insn "andsi_not_shiftsi_si"
2051  [(set (match_operand:SI                   0 "s_register_operand" "=r")
2052	(and:SI (not:SI (match_operator:SI  4 "shift_operator"
2053			 [(match_operand:SI 2 "s_register_operand"  "r")
2054			  (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2055		(match_operand:SI           1 "s_register_operand"  "r")))]
2056  "TARGET_ARM"
2057  "bic%?\\t%0, %1, %2%S4"
2058  [(set_attr "predicable" "yes")
2059   (set_attr "shift" "2")
2060   ]
2061)
2062
2063(define_insn "*andsi_notsi_si_compare0"
2064  [(set (reg:CC_NOOV CC_REGNUM)
2065	(compare:CC_NOOV
2066	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2067		 (match_operand:SI 1 "s_register_operand" "r"))
2068	 (const_int 0)))
2069   (set (match_operand:SI 0 "s_register_operand" "=r")
2070	(and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2071  "TARGET_ARM"
2072  "bic%?s\\t%0, %1, %2"
2073  [(set_attr "conds" "set")]
2074)
2075
2076(define_insn "*andsi_notsi_si_compare0_scratch"
2077  [(set (reg:CC_NOOV CC_REGNUM)
2078	(compare:CC_NOOV
2079	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080		 (match_operand:SI 1 "s_register_operand" "r"))
2081	 (const_int 0)))
2082   (clobber (match_scratch:SI 0 "=r"))]
2083  "TARGET_ARM"
2084  "bic%?s\\t%0, %1, %2"
2085  [(set_attr "conds" "set")]
2086)
2087
2088(define_insn "iordi3"
2089  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2090	(ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2091		(match_operand:DI 2 "s_register_operand"   "r,r")))]
2092  "TARGET_ARM && ! TARGET_IWMMXT"
2093  "#"
2094  [(set_attr "length" "8")
2095   (set_attr "predicable" "yes")]
2096)
2097
2098(define_insn "*iordi_zesidi_di"
2099  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2100	(ior:DI (zero_extend:DI
2101		 (match_operand:SI 2 "s_register_operand" "r,r"))
2102		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2103  "TARGET_ARM"
2104  "@
2105   orr%?\\t%Q0, %Q1, %2
2106   #"
2107  [(set_attr "length" "4,8")
2108   (set_attr "predicable" "yes")]
2109)
2110
2111(define_insn "*iordi_sesidi_di"
2112  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2113	(ior:DI (sign_extend:DI
2114		 (match_operand:SI 2 "s_register_operand" "r,r"))
2115		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2116  "TARGET_ARM"
2117  "#"
2118  [(set_attr "length" "8")
2119   (set_attr "predicable" "yes")]
2120)
2121
2122(define_expand "iorsi3"
2123  [(set (match_operand:SI         0 "s_register_operand" "")
2124	(ior:SI (match_operand:SI 1 "s_register_operand" "")
2125		(match_operand:SI 2 "reg_or_int_operand" "")))]
2126  "TARGET_EITHER"
2127  "
2128  if (GET_CODE (operands[2]) == CONST_INT)
2129    {
2130      if (TARGET_ARM)
2131        {
2132          arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2133		 	      operands[1],
2134			      (no_new_pseudos
2135			      ? 0 : preserve_subexpressions_p ()));
2136          DONE;
2137	}
2138      else /* TARGET_THUMB */
2139	operands [2] = force_reg (SImode, operands [2]);
2140    }
2141  "
2142)
2143
2144(define_insn_and_split "*arm_iorsi3"
2145  [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2146	(ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2147		(match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2148  "TARGET_ARM"
2149  "@
2150   orr%?\\t%0, %1, %2
2151   #"
2152  "TARGET_ARM
2153   && GET_CODE (operands[2]) == CONST_INT
2154   && !const_ok_for_arm (INTVAL (operands[2]))"
2155  [(clobber (const_int 0))]
2156  "
2157  arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2158		      operands[1], 0);
2159  DONE;
2160  "
2161  [(set_attr "length" "4,16")
2162   (set_attr "predicable" "yes")]
2163)
2164
2165(define_insn "*thumb_iorsi3"
2166  [(set (match_operand:SI         0 "register_operand" "=l")
2167	(ior:SI (match_operand:SI 1 "register_operand" "%0")
2168		(match_operand:SI 2 "register_operand" "l")))]
2169  "TARGET_THUMB"
2170  "orr\\t%0, %0, %2"
2171  [(set_attr "length" "2")]
2172)
2173
2174(define_peephole2
2175  [(match_scratch:SI 3 "r")
2176   (set (match_operand:SI         0 "s_register_operand" "")
2177	(ior:SI (match_operand:SI 1 "s_register_operand" "")
2178		(match_operand:SI 2 "const_int_operand" "")))]
2179  "TARGET_ARM
2180   && !const_ok_for_arm (INTVAL (operands[2]))
2181   && const_ok_for_arm (~INTVAL (operands[2]))"
2182  [(set (match_dup 3) (match_dup 2))
2183   (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2184  ""
2185)
2186
2187(define_insn "*iorsi3_compare0"
2188  [(set (reg:CC_NOOV CC_REGNUM)
2189	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2190				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2191			 (const_int 0)))
2192   (set (match_operand:SI 0 "s_register_operand" "=r")
2193	(ior:SI (match_dup 1) (match_dup 2)))]
2194  "TARGET_ARM"
2195  "orr%?s\\t%0, %1, %2"
2196  [(set_attr "conds" "set")]
2197)
2198
2199(define_insn "*iorsi3_compare0_scratch"
2200  [(set (reg:CC_NOOV CC_REGNUM)
2201	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2202				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2203			 (const_int 0)))
2204   (clobber (match_scratch:SI 0 "=r"))]
2205  "TARGET_ARM"
2206  "orr%?s\\t%0, %1, %2"
2207  [(set_attr "conds" "set")]
2208)
2209
2210(define_insn "xordi3"
2211  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2212	(xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2213		(match_operand:DI 2 "s_register_operand"   "r,r")))]
2214  "TARGET_ARM && !TARGET_IWMMXT"
2215  "#"
2216  [(set_attr "length" "8")
2217   (set_attr "predicable" "yes")]
2218)
2219
2220(define_insn "*xordi_zesidi_di"
2221  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2222	(xor:DI (zero_extend:DI
2223		 (match_operand:SI 2 "s_register_operand" "r,r"))
2224		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2225  "TARGET_ARM"
2226  "@
2227   eor%?\\t%Q0, %Q1, %2
2228   #"
2229  [(set_attr "length" "4,8")
2230   (set_attr "predicable" "yes")]
2231)
2232
2233(define_insn "*xordi_sesidi_di"
2234  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2235	(xor:DI (sign_extend:DI
2236		 (match_operand:SI 2 "s_register_operand" "r,r"))
2237		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2238  "TARGET_ARM"
2239  "#"
2240  [(set_attr "length" "8")
2241   (set_attr "predicable" "yes")]
2242)
2243
2244(define_expand "xorsi3"
2245  [(set (match_operand:SI         0 "s_register_operand" "")
2246	(xor:SI (match_operand:SI 1 "s_register_operand" "")
2247		(match_operand:SI 2 "arm_rhs_operand"  "")))]
2248  "TARGET_EITHER"
2249  "if (TARGET_THUMB)
2250     if (GET_CODE (operands[2]) == CONST_INT)
2251       operands[2] = force_reg (SImode, operands[2]);
2252  "
2253)
2254
2255(define_insn "*arm_xorsi3"
2256  [(set (match_operand:SI         0 "s_register_operand" "=r")
2257	(xor:SI (match_operand:SI 1 "s_register_operand" "r")
2258		(match_operand:SI 2 "arm_rhs_operand" "rI")))]
2259  "TARGET_ARM"
2260  "eor%?\\t%0, %1, %2"
2261  [(set_attr "predicable" "yes")]
2262)
2263
2264(define_insn "*thumb_xorsi3"
2265  [(set (match_operand:SI         0 "register_operand" "=l")
2266	(xor:SI (match_operand:SI 1 "register_operand" "%0")
2267		(match_operand:SI 2 "register_operand" "l")))]
2268  "TARGET_THUMB"
2269  "eor\\t%0, %0, %2"
2270  [(set_attr "length" "2")]
2271)
2272
2273(define_insn "*xorsi3_compare0"
2274  [(set (reg:CC_NOOV CC_REGNUM)
2275	(compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2276				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2277			 (const_int 0)))
2278   (set (match_operand:SI 0 "s_register_operand" "=r")
2279	(xor:SI (match_dup 1) (match_dup 2)))]
2280  "TARGET_ARM"
2281  "eor%?s\\t%0, %1, %2"
2282  [(set_attr "conds" "set")]
2283)
2284
2285(define_insn "*xorsi3_compare0_scratch"
2286  [(set (reg:CC_NOOV CC_REGNUM)
2287	(compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2288				 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2289			 (const_int 0)))]
2290  "TARGET_ARM"
2291  "teq%?\\t%0, %1"
2292  [(set_attr "conds" "set")]
2293)
2294
2295; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2296; (NOT D) we can sometimes merge the final NOT into one of the following
2297; insns.
2298
2299(define_split
2300  [(set (match_operand:SI 0 "s_register_operand" "")
2301	(ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2302			(not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2303		(match_operand:SI 3 "arm_rhs_operand" "")))
2304   (clobber (match_operand:SI 4 "s_register_operand" ""))]
2305  "TARGET_ARM"
2306  [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2307			      (not:SI (match_dup 3))))
2308   (set (match_dup 0) (not:SI (match_dup 4)))]
2309  ""
2310)
2311
2312(define_insn "*andsi_iorsi3_notsi"
2313  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2314	(and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2315			(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2316		(not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2317  "TARGET_ARM"
2318  "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2319  [(set_attr "length" "8")
2320   (set_attr "predicable" "yes")]
2321)
2322
2323(define_split
2324  [(set (match_operand:SI 0 "s_register_operand" "")
2325	(match_operator:SI 1 "logical_binary_operator"
2326	 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2327			   (match_operand:SI 3 "const_int_operand" "")
2328			   (match_operand:SI 4 "const_int_operand" ""))
2329	  (match_operator:SI 9 "logical_binary_operator"
2330	   [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2331			 (match_operand:SI 6 "const_int_operand" ""))
2332	    (match_operand:SI 7 "s_register_operand" "")])]))
2333   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2334  "TARGET_ARM
2335   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2336   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2337  [(set (match_dup 8)
2338	(match_op_dup 1
2339	 [(ashift:SI (match_dup 2) (match_dup 4))
2340	  (match_dup 5)]))
2341   (set (match_dup 0)
2342	(match_op_dup 1
2343	 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2344	  (match_dup 7)]))]
2345  "
2346  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2347")
2348
2349(define_split
2350  [(set (match_operand:SI 0 "s_register_operand" "")
2351	(match_operator:SI 1 "logical_binary_operator"
2352	 [(match_operator:SI 9 "logical_binary_operator"
2353	   [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2354			 (match_operand:SI 6 "const_int_operand" ""))
2355	    (match_operand:SI 7 "s_register_operand" "")])
2356	  (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2357			   (match_operand:SI 3 "const_int_operand" "")
2358			   (match_operand:SI 4 "const_int_operand" ""))]))
2359   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2360  "TARGET_ARM
2361   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2362   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2363  [(set (match_dup 8)
2364	(match_op_dup 1
2365	 [(ashift:SI (match_dup 2) (match_dup 4))
2366	  (match_dup 5)]))
2367   (set (match_dup 0)
2368	(match_op_dup 1
2369	 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2370	  (match_dup 7)]))]
2371  "
2372  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2373")
2374
2375(define_split
2376  [(set (match_operand:SI 0 "s_register_operand" "")
2377	(match_operator:SI 1 "logical_binary_operator"
2378	 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2379			   (match_operand:SI 3 "const_int_operand" "")
2380			   (match_operand:SI 4 "const_int_operand" ""))
2381	  (match_operator:SI 9 "logical_binary_operator"
2382	   [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2383			 (match_operand:SI 6 "const_int_operand" ""))
2384	    (match_operand:SI 7 "s_register_operand" "")])]))
2385   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2386  "TARGET_ARM
2387   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2388   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2389  [(set (match_dup 8)
2390	(match_op_dup 1
2391	 [(ashift:SI (match_dup 2) (match_dup 4))
2392	  (match_dup 5)]))
2393   (set (match_dup 0)
2394	(match_op_dup 1
2395	 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2396	  (match_dup 7)]))]
2397  "
2398  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2399")
2400
2401(define_split
2402  [(set (match_operand:SI 0 "s_register_operand" "")
2403	(match_operator:SI 1 "logical_binary_operator"
2404	 [(match_operator:SI 9 "logical_binary_operator"
2405	   [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2406			 (match_operand:SI 6 "const_int_operand" ""))
2407	    (match_operand:SI 7 "s_register_operand" "")])
2408	  (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2409			   (match_operand:SI 3 "const_int_operand" "")
2410			   (match_operand:SI 4 "const_int_operand" ""))]))
2411   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2412  "TARGET_ARM
2413   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2414   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2415  [(set (match_dup 8)
2416	(match_op_dup 1
2417	 [(ashift:SI (match_dup 2) (match_dup 4))
2418	  (match_dup 5)]))
2419   (set (match_dup 0)
2420	(match_op_dup 1
2421	 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2422	  (match_dup 7)]))]
2423  "
2424  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2425")
2426
2427
2428;; Minimum and maximum insns
2429
2430(define_insn "smaxsi3"
2431  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2432	(smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2433		 (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2434   (clobber (reg:CC CC_REGNUM))]
2435  "TARGET_ARM"
2436  "@
2437   cmp\\t%1, %2\;movlt\\t%0, %2
2438   cmp\\t%1, %2\;movge\\t%0, %1
2439   cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2440  [(set_attr "conds" "clob")
2441   (set_attr "length" "8,8,12")]
2442)
2443
2444(define_insn "sminsi3"
2445  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2446	(smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2447		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2448   (clobber (reg:CC CC_REGNUM))]
2449  "TARGET_ARM"
2450  "@
2451   cmp\\t%1, %2\;movge\\t%0, %2
2452   cmp\\t%1, %2\;movlt\\t%0, %1
2453   cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2454  [(set_attr "conds" "clob")
2455   (set_attr "length" "8,8,12")]
2456)
2457
2458(define_insn "umaxsi3"
2459  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2460	(umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2461		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2462   (clobber (reg:CC CC_REGNUM))]
2463  "TARGET_ARM"
2464  "@
2465   cmp\\t%1, %2\;movcc\\t%0, %2
2466   cmp\\t%1, %2\;movcs\\t%0, %1
2467   cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2468  [(set_attr "conds" "clob")
2469   (set_attr "length" "8,8,12")]
2470)
2471
2472(define_insn "uminsi3"
2473  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2474	(umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2475		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2476   (clobber (reg:CC CC_REGNUM))]
2477  "TARGET_ARM"
2478  "@
2479   cmp\\t%1, %2\;movcs\\t%0, %2
2480   cmp\\t%1, %2\;movcc\\t%0, %1
2481   cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2482  [(set_attr "conds" "clob")
2483   (set_attr "length" "8,8,12")]
2484)
2485
2486(define_insn "*store_minmaxsi"
2487  [(set (match_operand:SI 0 "memory_operand" "=m")
2488	(match_operator:SI 3 "minmax_operator"
2489	 [(match_operand:SI 1 "s_register_operand" "r")
2490	  (match_operand:SI 2 "s_register_operand" "r")]))
2491   (clobber (reg:CC CC_REGNUM))]
2492  "TARGET_ARM"
2493  "*
2494  operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2495			 operands[2]);
2496  output_asm_insn (\"cmp\\t%1, %2\", operands);
2497  output_asm_insn (\"str%d3\\t%1, %0\", operands);
2498  output_asm_insn (\"str%D3\\t%2, %0\", operands);
2499  return \"\";
2500  "
2501  [(set_attr "conds" "clob")
2502   (set_attr "length" "12")
2503   (set_attr "type" "store1")]
2504)
2505
2506; Reject the frame pointer in operand[1], since reloading this after
2507; it has been eliminated can cause carnage.
2508(define_insn "*minmax_arithsi"
2509  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2510	(match_operator:SI 4 "shiftable_operator"
2511	 [(match_operator:SI 5 "minmax_operator"
2512	   [(match_operand:SI 2 "s_register_operand" "r,r")
2513	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2514	  (match_operand:SI 1 "s_register_operand" "0,?r")]))
2515   (clobber (reg:CC CC_REGNUM))]
2516  "TARGET_ARM
2517   && (GET_CODE (operands[1]) != REG
2518       || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2519           && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2520  "*
2521  {
2522    enum rtx_code code = GET_CODE (operands[4]);
2523
2524    operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2525			   operands[3]);
2526    output_asm_insn (\"cmp\\t%2, %3\", operands);
2527    output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2528    if (which_alternative != 0 || operands[3] != const0_rtx
2529        || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2530      output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2531    return \"\";
2532  }"
2533  [(set_attr "conds" "clob")
2534   (set_attr "length" "12")]
2535)
2536
2537
2538;; Shift and rotation insns
2539
2540(define_expand "ashlsi3"
2541  [(set (match_operand:SI            0 "s_register_operand" "")
2542	(ashift:SI (match_operand:SI 1 "s_register_operand" "")
2543		   (match_operand:SI 2 "arm_rhs_operand" "")))]
2544  "TARGET_EITHER"
2545  "
2546  if (GET_CODE (operands[2]) == CONST_INT
2547      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2548    {
2549      emit_insn (gen_movsi (operands[0], const0_rtx));
2550      DONE;
2551    }
2552  "
2553)
2554
2555(define_insn "*thumb_ashlsi3"
2556  [(set (match_operand:SI            0 "register_operand" "=l,l")
2557	(ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2558		   (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2559  "TARGET_THUMB"
2560  "lsl\\t%0, %1, %2"
2561  [(set_attr "length" "2")]
2562)
2563
2564(define_expand "ashrsi3"
2565  [(set (match_operand:SI              0 "s_register_operand" "")
2566	(ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2567		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2568  "TARGET_EITHER"
2569  "
2570  if (GET_CODE (operands[2]) == CONST_INT
2571      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2572    operands[2] = GEN_INT (31);
2573  "
2574)
2575
2576(define_insn "*thumb_ashrsi3"
2577  [(set (match_operand:SI              0 "register_operand" "=l,l")
2578	(ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2579		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2580  "TARGET_THUMB"
2581  "asr\\t%0, %1, %2"
2582  [(set_attr "length" "2")]
2583)
2584
2585(define_expand "lshrsi3"
2586  [(set (match_operand:SI              0 "s_register_operand" "")
2587	(lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2588		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2589  "TARGET_EITHER"
2590  "
2591  if (GET_CODE (operands[2]) == CONST_INT
2592      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2593    {
2594      emit_insn (gen_movsi (operands[0], const0_rtx));
2595      DONE;
2596    }
2597  "
2598)
2599
2600(define_insn "*thumb_lshrsi3"
2601  [(set (match_operand:SI              0 "register_operand" "=l,l")
2602	(lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2603		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2604  "TARGET_THUMB"
2605  "lsr\\t%0, %1, %2"
2606  [(set_attr "length" "2")]
2607)
2608
2609(define_expand "rotlsi3"
2610  [(set (match_operand:SI              0 "s_register_operand" "")
2611	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2612		     (match_operand:SI 2 "reg_or_int_operand" "")))]
2613  "TARGET_ARM"
2614  "
2615  if (GET_CODE (operands[2]) == CONST_INT)
2616    operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2617  else
2618    {
2619      rtx reg = gen_reg_rtx (SImode);
2620      emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2621      operands[2] = reg;
2622    }
2623  "
2624)
2625
2626(define_expand "rotrsi3"
2627  [(set (match_operand:SI              0 "s_register_operand" "")
2628	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2629		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2630  "TARGET_EITHER"
2631  "
2632  if (TARGET_ARM)
2633    {
2634      if (GET_CODE (operands[2]) == CONST_INT
2635          && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2636        operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2637    }
2638  else /* TARGET_THUMB */
2639    {
2640      if (GET_CODE (operands [2]) == CONST_INT)
2641        operands [2] = force_reg (SImode, operands[2]);
2642    }
2643  "
2644)
2645
2646(define_insn "*thumb_rotrsi3"
2647  [(set (match_operand:SI              0 "register_operand" "=l")
2648	(rotatert:SI (match_operand:SI 1 "register_operand" "0")
2649		     (match_operand:SI 2 "register_operand" "l")))]
2650  "TARGET_THUMB"
2651  "ror\\t%0, %0, %2"
2652  [(set_attr "length" "2")]
2653)
2654
2655(define_expand "ashldi3"
2656  [(set (match_operand:DI            0 "s_register_operand" "")
2657	(ashift:DI (match_operand:DI 1 "general_operand"    "")
2658		   (match_operand:SI 2 "general_operand"    "")))]
2659  "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
2660  "
2661  if (! s_register_operand (operands[1], DImode))
2662    operands[1] = copy_to_mode_reg (DImode, operands[1]);
2663  if (! s_register_operand (operands[2], SImode))
2664    operands[2] = copy_to_mode_reg (SImode, operands[2]);
2665  "
2666)
2667
2668(define_insn "*arm_shiftsi3"
2669  [(set (match_operand:SI   0 "s_register_operand" "=r")
2670	(match_operator:SI  3 "shift_operator"
2671	 [(match_operand:SI 1 "s_register_operand"  "r")
2672	  (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2673  "TARGET_ARM"
2674  "mov%?\\t%0, %1%S3"
2675  [(set_attr "predicable" "yes")
2676   (set_attr "shift" "1")
2677   ]
2678)
2679
2680(define_insn "*shiftsi3_compare0"
2681  [(set (reg:CC_NOOV CC_REGNUM)
2682	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2683			  [(match_operand:SI 1 "s_register_operand" "r")
2684			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
2685			 (const_int 0)))
2686   (set (match_operand:SI 0 "s_register_operand" "=r")
2687	(match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2688  "TARGET_ARM"
2689  "mov%?s\\t%0, %1%S3"
2690  [(set_attr "conds" "set")
2691   (set_attr "shift" "1")
2692   ]
2693)
2694
2695(define_insn "*shiftsi3_compare0_scratch"
2696  [(set (reg:CC_NOOV CC_REGNUM)
2697	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2698			  [(match_operand:SI 1 "s_register_operand" "r")
2699			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
2700			 (const_int 0)))
2701   (clobber (match_scratch:SI 0 "=r"))]
2702  "TARGET_ARM"
2703  "mov%?s\\t%0, %1%S3"
2704  [(set_attr "conds" "set")
2705   (set_attr "shift" "1")
2706   ]
2707)
2708
2709(define_insn "*notsi_shiftsi"
2710  [(set (match_operand:SI 0 "s_register_operand" "=r")
2711	(not:SI (match_operator:SI 3 "shift_operator"
2712		 [(match_operand:SI 1 "s_register_operand" "r")
2713		  (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2714  "TARGET_ARM"
2715  "mvn%?\\t%0, %1%S3"
2716  [(set_attr "predicable" "yes")
2717   (set_attr "shift" "1")
2718   ]
2719)
2720
2721(define_insn "*notsi_shiftsi_compare0"
2722  [(set (reg:CC_NOOV CC_REGNUM)
2723	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2724			  [(match_operand:SI 1 "s_register_operand" "r")
2725			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2726			 (const_int 0)))
2727   (set (match_operand:SI 0 "s_register_operand" "=r")
2728	(not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2729  "TARGET_ARM"
2730  "mvn%?s\\t%0, %1%S3"
2731  [(set_attr "conds" "set")
2732   (set_attr "shift" "1")
2733   ]
2734)
2735
2736(define_insn "*not_shiftsi_compare0_scratch"
2737  [(set (reg:CC_NOOV CC_REGNUM)
2738	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2739			  [(match_operand:SI 1 "s_register_operand" "r")
2740			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2741			 (const_int 0)))
2742   (clobber (match_scratch:SI 0 "=r"))]
2743  "TARGET_ARM"
2744  "mvn%?s\\t%0, %1%S3"
2745  [(set_attr "conds" "set")
2746   (set_attr "shift" "1")
2747  ]
2748)
2749
2750;; We don't really have extzv, but defining this using shifts helps
2751;; to reduce register pressure later on.
2752
2753(define_expand "extzv"
2754  [(set (match_dup 4)
2755	(ashift:SI (match_operand:SI   1 "register_operand" "")
2756		   (match_operand:SI   2 "const_int_operand" "")))
2757   (set (match_operand:SI              0 "register_operand" "")
2758	(lshiftrt:SI (match_dup 4)
2759		     (match_operand:SI 3 "const_int_operand" "")))]
2760  "TARGET_THUMB"
2761  "
2762  {
2763    HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2764    HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2765    
2766    operands[3] = GEN_INT (rshift);
2767    
2768    if (lshift == 0)
2769      {
2770        emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2771        DONE;
2772      }
2773      
2774    operands[2] = GEN_INT (lshift);
2775    operands[4] = gen_reg_rtx (SImode);
2776  }"
2777)
2778
2779
2780;; Unary arithmetic insns
2781
2782(define_expand "negdi2"
2783 [(parallel
2784   [(set (match_operand:DI          0 "s_register_operand" "")
2785	  (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2786    (clobber (reg:CC CC_REGNUM))])]
2787  "TARGET_EITHER"
2788  "
2789  if (TARGET_THUMB)
2790    {
2791      if (GET_CODE (operands[1]) != REG)
2792        operands[1] = force_reg (SImode, operands[1]);
2793     }
2794  "
2795)
2796
2797;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2798;; The second alternative is to allow the common case of a *full* overlap.
2799(define_insn "*arm_negdi2"
2800  [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2801	(neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2802   (clobber (reg:CC CC_REGNUM))]
2803  "TARGET_ARM"
2804  "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2805  [(set_attr "conds" "clob")
2806   (set_attr "length" "8")]
2807)
2808
2809(define_insn "*thumb_negdi2"
2810  [(set (match_operand:DI         0 "register_operand" "=&l")
2811	(neg:DI (match_operand:DI 1 "register_operand"   "l")))
2812   (clobber (reg:CC CC_REGNUM))]
2813  "TARGET_THUMB"
2814  "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2815  [(set_attr "length" "6")]
2816)
2817
2818(define_expand "negsi2"
2819  [(set (match_operand:SI         0 "s_register_operand" "")
2820	(neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2821  "TARGET_EITHER"
2822  ""
2823)
2824
2825(define_insn "*arm_negsi2"
2826  [(set (match_operand:SI         0 "s_register_operand" "=r")
2827	(neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2828  "TARGET_ARM"
2829  "rsb%?\\t%0, %1, #0"
2830  [(set_attr "predicable" "yes")]
2831)
2832
2833(define_insn "*thumb_negsi2"
2834  [(set (match_operand:SI         0 "register_operand" "=l")
2835	(neg:SI (match_operand:SI 1 "register_operand" "l")))]
2836  "TARGET_THUMB"
2837  "neg\\t%0, %1"
2838  [(set_attr "length" "2")]
2839)
2840
2841(define_expand "negsf2"
2842  [(set (match_operand:SF         0 "s_register_operand" "")
2843	(neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2844  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2845  ""
2846)
2847
2848(define_expand "negdf2"
2849  [(set (match_operand:DF         0 "s_register_operand" "")
2850	(neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2851  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2852  "")
2853
2854;; abssi2 doesn't really clobber the condition codes if a different register
2855;; is being set.  To keep things simple, assume during rtl manipulations that
2856;; it does, but tell the final scan operator the truth.  Similarly for
2857;; (neg (abs...))
2858
2859(define_expand "abssi2"
2860  [(parallel
2861    [(set (match_operand:SI         0 "s_register_operand" "")
2862	  (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2863     (clobber (reg:CC CC_REGNUM))])]
2864  "TARGET_ARM"
2865  "")
2866
2867(define_insn "*arm_abssi2"
2868  [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2869	(abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2870   (clobber (reg:CC CC_REGNUM))]
2871  "TARGET_ARM"
2872  "@
2873   cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2874   eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2875  [(set_attr "conds" "clob,*")
2876   (set_attr "shift" "1")
2877   ;; predicable can't be set based on the variant, so left as no
2878   (set_attr "length" "8")]
2879)
2880
2881(define_insn "*neg_abssi2"
2882  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2883	(neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2884   (clobber (reg:CC CC_REGNUM))]
2885  "TARGET_ARM"
2886  "@
2887   cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2888   eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2889  [(set_attr "conds" "clob,*")
2890   (set_attr "shift" "1")
2891   ;; predicable can't be set based on the variant, so left as no
2892   (set_attr "length" "8")]
2893)
2894
2895(define_expand "abssf2"
2896  [(set (match_operand:SF         0 "s_register_operand" "")
2897	(abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2898  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2899  "")
2900
2901(define_expand "absdf2"
2902  [(set (match_operand:DF         0 "s_register_operand" "")
2903	(abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2904  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2905  "")
2906
2907(define_expand "sqrtsf2"
2908  [(set (match_operand:SF 0 "s_register_operand" "")
2909	(sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2910  "TARGET_ARM && TARGET_HARD_FLOAT"
2911  "")
2912
2913(define_expand "sqrtdf2"
2914  [(set (match_operand:DF 0 "s_register_operand" "")
2915	(sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2916  "TARGET_ARM && TARGET_HARD_FLOAT"
2917  "")
2918
2919(define_insn_and_split "one_cmpldi2"
2920  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2921	(not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2922  "TARGET_ARM"
2923  "#"
2924  "TARGET_ARM && reload_completed"
2925  [(set (match_dup 0) (not:SI (match_dup 1)))
2926   (set (match_dup 2) (not:SI (match_dup 3)))]
2927  "
2928  {
2929    operands[2] = gen_highpart (SImode, operands[0]);
2930    operands[0] = gen_lowpart (SImode, operands[0]);
2931    operands[3] = gen_highpart (SImode, operands[1]);
2932    operands[1] = gen_lowpart (SImode, operands[1]);
2933  }"
2934  [(set_attr "length" "8")
2935   (set_attr "predicable" "yes")]
2936)
2937
2938(define_expand "one_cmplsi2"
2939  [(set (match_operand:SI         0 "s_register_operand" "")
2940	(not:SI (match_operand:SI 1 "s_register_operand" "")))]
2941  "TARGET_EITHER"
2942  ""
2943)
2944
2945(define_insn "*arm_one_cmplsi2"
2946  [(set (match_operand:SI         0 "s_register_operand" "=r")
2947	(not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2948  "TARGET_ARM"
2949  "mvn%?\\t%0, %1"
2950  [(set_attr "predicable" "yes")]
2951)
2952
2953(define_insn "*thumb_one_cmplsi2"
2954  [(set (match_operand:SI         0 "register_operand" "=l")
2955	(not:SI (match_operand:SI 1 "register_operand"  "l")))]
2956  "TARGET_THUMB"
2957  "mvn\\t%0, %1"
2958  [(set_attr "length" "2")]
2959)
2960
2961(define_insn "*notsi_compare0"
2962  [(set (reg:CC_NOOV CC_REGNUM)
2963	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2964			 (const_int 0)))
2965   (set (match_operand:SI 0 "s_register_operand" "=r")
2966	(not:SI (match_dup 1)))]
2967  "TARGET_ARM"
2968  "mvn%?s\\t%0, %1"
2969  [(set_attr "conds" "set")]
2970)
2971
2972(define_insn "*notsi_compare0_scratch"
2973  [(set (reg:CC_NOOV CC_REGNUM)
2974	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2975			 (const_int 0)))
2976   (clobber (match_scratch:SI 0 "=r"))]
2977  "TARGET_ARM"
2978  "mvn%?s\\t%0, %1"
2979  [(set_attr "conds" "set")]
2980)
2981
2982;; Fixed <--> Floating conversion insns
2983
2984(define_expand "floatsisf2"
2985  [(set (match_operand:SF           0 "s_register_operand" "")
2986	(float:SF (match_operand:SI 1 "s_register_operand" "")))]
2987  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2988  "
2989  if (TARGET_CIRRUS)
2990    {
2991      emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2992      DONE;
2993    }
2994")
2995
2996(define_expand "floatsidf2"
2997  [(set (match_operand:DF           0 "s_register_operand" "")
2998	(float:DF (match_operand:SI 1 "s_register_operand" "")))]
2999  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3000  "
3001  if (TARGET_CIRRUS)
3002    {
3003      emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3004      DONE;
3005    }
3006")
3007
3008(define_expand "fix_truncsfsi2"
3009  [(set (match_operand:SI         0 "s_register_operand" "")
3010	(fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3011  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3012  "
3013  if (TARGET_CIRRUS)
3014    {
3015      if (!cirrus_fp_register (operands[0], SImode))
3016        operands[0] = force_reg (SImode, operands[0]);
3017      if (!cirrus_fp_register (operands[1], SFmode))
3018        operands[1] = force_reg (SFmode, operands[0]);
3019      emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3020      DONE;
3021    }
3022")
3023
3024(define_expand "fix_truncdfsi2"
3025  [(set (match_operand:SI         0 "s_register_operand" "")
3026	(fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3027  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3028  "
3029  if (TARGET_CIRRUS)
3030    {
3031      if (!cirrus_fp_register (operands[1], DFmode))
3032        operands[1] = force_reg (DFmode, operands[0]);
3033      emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3034      DONE;
3035    }
3036")
3037
3038;; Truncation insns
3039
3040(define_expand "truncdfsf2"
3041  [(set (match_operand:SF  0 "s_register_operand" "")
3042	(float_truncate:SF
3043 	 (match_operand:DF 1 "s_register_operand" "")))]
3044  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3045  ""
3046)
3047
3048;; Zero and sign extension instructions.
3049
3050(define_insn "zero_extendsidi2"
3051  [(set (match_operand:DI 0 "s_register_operand" "=r")
3052        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3053  "TARGET_ARM"
3054  "*
3055    if (REGNO (operands[1])
3056        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3057      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3058    return \"mov%?\\t%R0, #0\";
3059  "
3060  [(set_attr "length" "8")
3061   (set_attr "predicable" "yes")]
3062)
3063
3064(define_insn "zero_extendqidi2"
3065  [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3066	(zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3067  "TARGET_ARM"
3068  "@
3069   and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3070   ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3071  [(set_attr "length" "8")
3072   (set_attr "predicable" "yes")
3073   (set_attr "type" "*,load")
3074   (set_attr "pool_range" "*,4092")
3075   (set_attr "neg_pool_range" "*,4084")]
3076)
3077
3078(define_insn "extendsidi2"
3079  [(set (match_operand:DI 0 "s_register_operand" "=r")
3080        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3081  "TARGET_ARM"
3082  "*
3083    if (REGNO (operands[1])
3084        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3085      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3086    return \"mov%?\\t%R0, %Q0, asr #31\";
3087  "
3088  [(set_attr "length" "8")
3089   (set_attr "shift" "1")
3090   (set_attr "predicable" "yes")]
3091)
3092
3093(define_expand "zero_extendhisi2"
3094  [(set (match_dup 2)
3095	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3096		   (const_int 16)))
3097   (set (match_operand:SI 0 "s_register_operand" "")
3098	(lshiftrt:SI (match_dup 2) (const_int 16)))]
3099  "TARGET_EITHER"
3100  "
3101  {
3102    if (TARGET_ARM)
3103      {
3104        if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3105          {
3106           /* Note: We do not have to worry about TARGET_MMU_TRAPS
3107	      here because the insn below will generate an LDRH instruction
3108	      rather than an LDR instruction, so we cannot get an unaligned
3109	      word access.  */
3110            emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3111			            gen_rtx_ZERO_EXTEND (SImode,
3112							 operands[1])));
3113            DONE;
3114          }
3115        if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3116          {
3117            emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3118            DONE;
3119          }
3120        if (!s_register_operand (operands[1], HImode))
3121          operands[1] = copy_to_mode_reg (HImode, operands[1]);
3122        operands[1] = gen_lowpart (SImode, operands[1]);
3123        operands[2] = gen_reg_rtx (SImode);
3124      }
3125    else /* TARGET_THUMB */
3126      {
3127        if (GET_CODE (operands[1]) == MEM)
3128	  {
3129	    rtx tmp;
3130
3131	    tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3132	    tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3133	    emit_insn (tmp);
3134	  }
3135	else
3136	  {
3137	    rtx ops[3];
3138	    
3139	    if (!s_register_operand (operands[1], HImode))
3140	      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3141	    operands[1] = gen_lowpart (SImode, operands[1]);
3142	    operands[2] = gen_reg_rtx (SImode);
3143	    
3144	    ops[0] = operands[2];
3145	    ops[1] = operands[1];
3146	    ops[2] = GEN_INT (16);
3147	    
3148	    emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3149				    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3150
3151	    ops[0] = operands[0];
3152	    ops[1] = operands[2];
3153	    ops[2] = GEN_INT (16);
3154
3155	    emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3156				    gen_rtx_LSHIFTRT (SImode, ops[1],
3157						      ops[2])));
3158	  }
3159	DONE; 
3160      }
3161  }"
3162)
3163
3164(define_insn "*thumb_zero_extendhisi2"
3165  [(set (match_operand:SI                 0 "register_operand" "=l")
3166	(zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3167  "TARGET_THUMB"
3168  "*
3169  rtx mem = XEXP (operands[1], 0);
3170
3171  if (GET_CODE (mem) == CONST)
3172    mem = XEXP (mem, 0);
3173    
3174  if (GET_CODE (mem) == LABEL_REF)
3175    return \"ldr\\t%0, %1\";
3176    
3177  if (GET_CODE (mem) == PLUS)
3178    {
3179      rtx a = XEXP (mem, 0);
3180      rtx b = XEXP (mem, 1);
3181
3182      /* This can happen due to bugs in reload.  */
3183      if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3184        {
3185          rtx ops[2];
3186          ops[0] = operands[0];
3187          ops[1] = a;
3188      
3189          output_asm_insn (\"mov	%0, %1\", ops);
3190
3191          XEXP (mem, 0) = operands[0];
3192       }
3193
3194      else if (   GET_CODE (a) == LABEL_REF
3195	       && GET_CODE (b) == CONST_INT)
3196        return \"ldr\\t%0, %1\";
3197    }
3198    
3199  return \"ldrh\\t%0, %1\";
3200  "
3201  [(set_attr "length" "4")
3202   (set_attr "type" "load")
3203   (set_attr "pool_range" "60")]
3204)
3205
3206(define_insn "*arm_zero_extendhisi2"
3207  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3208	(zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3209  "TARGET_ARM && arm_arch4"
3210  "ldr%?h\\t%0, %1"
3211  [(set_attr "type" "load")
3212   (set_attr "predicable" "yes")
3213   (set_attr "pool_range" "256")
3214   (set_attr "neg_pool_range" "244")]
3215)
3216
3217(define_split
3218  [(set (match_operand:SI 0 "s_register_operand" "")
3219	(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3220   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3221  "TARGET_ARM && (!arm_arch4)"
3222  [(set (match_dup 2) (match_dup 1))
3223   (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3224  "
3225  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3226    FAIL;
3227  "
3228)
3229
3230(define_split
3231  [(set (match_operand:SI 0 "s_register_operand" "")
3232	(match_operator:SI 3 "shiftable_operator"
3233	 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3234	  (match_operand:SI 4 "s_register_operand" "")]))
3235   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3236  "TARGET_ARM && (!arm_arch4)"
3237  [(set (match_dup 2) (match_dup 1))
3238   (set (match_dup 0)
3239	(match_op_dup 3
3240	 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3241  "
3242  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3243    FAIL;
3244  "
3245)
3246
3247(define_expand "zero_extendqisi2"
3248  [(set (match_operand:SI 0 "s_register_operand" "")
3249	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3250  "TARGET_EITHER"
3251  "
3252  if (GET_CODE (operands[1]) != MEM)
3253    {
3254      if (TARGET_ARM)
3255        {
3256          emit_insn (gen_andsi3 (operands[0],
3257				 gen_lowpart (SImode, operands[1]),
3258			         GEN_INT (255)));
3259        }
3260      else /* TARGET_THUMB */
3261        {
3262          rtx temp = gen_reg_rtx (SImode);
3263	  rtx ops[3];
3264	  
3265          operands[1] = copy_to_mode_reg (QImode, operands[1]);
3266          operands[1] = gen_lowpart (SImode, operands[1]);
3267
3268	  ops[0] = temp;
3269	  ops[1] = operands[1];
3270	  ops[2] = GEN_INT (24);
3271
3272	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3273				  gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3274	  
3275          ops[0] = operands[0];
3276	  ops[1] = temp;
3277	  ops[2] = GEN_INT (24);
3278
3279	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3280				  gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3281	}
3282      DONE;
3283    }
3284  "
3285)
3286
3287(define_insn "*thumb_zero_extendqisi2"
3288  [(set (match_operand:SI                 0 "register_operand" "=l")
3289	(zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3290  "TARGET_THUMB"
3291  "ldrb\\t%0, %1"
3292  [(set_attr "length" "2")
3293   (set_attr "type" "load")
3294   (set_attr "pool_range" "32")]
3295)
3296
3297(define_insn "*arm_zero_extendqisi2"
3298  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3299	(zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3300  "TARGET_ARM"
3301  "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3302  [(set_attr "type" "load")
3303   (set_attr "predicable" "yes")
3304   (set_attr "pool_range" "4096")
3305   (set_attr "neg_pool_range" "4084")]
3306)
3307
3308(define_split
3309  [(set (match_operand:SI 0 "s_register_operand" "")
3310	(zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3311   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3312  "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3313  [(set (match_dup 2) (match_dup 1))
3314   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3315  ""
3316)
3317
3318(define_insn "*compareqi_eq0"
3319  [(set (reg:CC_Z CC_REGNUM)
3320	(compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3321			 (const_int 0)))]
3322  "TARGET_ARM"
3323  "tst\\t%0, #255"
3324  [(set_attr "conds" "set")]
3325)
3326
3327(define_expand "extendhisi2"
3328  [(set (match_dup 2)
3329	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3330		   (const_int 16)))
3331   (set (match_operand:SI 0 "s_register_operand" "")
3332	(ashiftrt:SI (match_dup 2)
3333		     (const_int 16)))]
3334  "TARGET_EITHER"
3335  "
3336  {
3337    if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3338      {
3339       /* Note: We do not have to worry about TARGET_MMU_TRAPS
3340	  here because the insn below will generate an LDRH instruction
3341	  rather than an LDR instruction, so we cannot get an unaligned
3342	  word access.  */
3343        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3344		   gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3345        DONE;
3346      }
3347
3348    if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3349      {
3350        emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3351        DONE;
3352      }
3353    if (!s_register_operand (operands[1], HImode))
3354      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3355    operands[1] = gen_lowpart (SImode, operands[1]);
3356    operands[2] = gen_reg_rtx (SImode);
3357
3358    if (TARGET_THUMB)
3359      {
3360	rtx ops[3];
3361	
3362	ops[0] = operands[2];
3363	ops[1] = operands[1];
3364	ops[2] = GEN_INT (16);
3365	
3366        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3367				gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3368	    
3369	ops[0] = operands[0];
3370	ops[1] = operands[2];
3371	ops[2] = GEN_INT (16);
3372	
3373        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3374				gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3375	
3376	DONE;
3377      }
3378  }"
3379)
3380
3381(define_insn "*thumb_extendhisi2_insn"
3382  [(set (match_operand:SI                 0 "register_operand" "=l")
3383	(sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3384   (clobber (match_scratch:SI             2                   "=&l"))]
3385  "TARGET_THUMB"
3386  "*
3387  {
3388    rtx ops[4];
3389    rtx mem = XEXP (operands[1], 0);
3390
3391    /* This code used to try to use 'V', and fix the address only if it was
3392       offsettable, but this fails for e.g. REG+48 because 48 is outside the
3393       range of QImode offsets, and offsettable_address_p does a QImode
3394       address check.  */
3395       
3396    if (GET_CODE (mem) == CONST)
3397      mem = XEXP (mem, 0);
3398    
3399    if (GET_CODE (mem) == LABEL_REF)
3400      return \"ldr\\t%0, %1\";
3401    
3402    if (GET_CODE (mem) == PLUS)
3403      {
3404        rtx a = XEXP (mem, 0);
3405        rtx b = XEXP (mem, 1);
3406
3407        if (GET_CODE (a) == LABEL_REF
3408	    && GET_CODE (b) == CONST_INT)
3409          return \"ldr\\t%0, %1\";
3410
3411        if (GET_CODE (b) == REG)
3412          return \"ldrsh\\t%0, %1\";
3413	  
3414        ops[1] = a;
3415        ops[2] = b;
3416      }
3417    else
3418      {
3419        ops[1] = mem;
3420        ops[2] = const0_rtx;
3421      }
3422      
3423    if (GET_CODE (ops[1]) != REG)
3424      {
3425        debug_rtx (ops[1]);
3426        abort ();
3427      }
3428
3429    ops[0] = operands[0];
3430    ops[3] = operands[2];
3431    output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3432    return \"\";
3433  }"
3434  [(set_attr "length" "4")
3435   (set_attr "type" "load")
3436   (set_attr "pool_range" "1020")]
3437)
3438
3439(define_expand "extendhisi2_mem"
3440  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3441   (set (match_dup 3)
3442	(zero_extend:SI (match_dup 7)))
3443   (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3444   (set (match_operand:SI 0 "" "")
3445	(ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3446  "TARGET_ARM"
3447  "
3448  {
3449    rtx mem1, mem2;
3450    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3451
3452    mem1 = gen_rtx_MEM (QImode, addr);
3453    MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3454    mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3455    MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3456    operands[0] = gen_lowpart (SImode, operands[0]);
3457    operands[1] = mem1;
3458    operands[2] = gen_reg_rtx (SImode);
3459    operands[3] = gen_reg_rtx (SImode);
3460    operands[6] = gen_reg_rtx (SImode);
3461    operands[7] = mem2;
3462
3463    if (BYTES_BIG_ENDIAN)
3464      {
3465	operands[4] = operands[2];
3466	operands[5] = operands[3];
3467      }
3468    else
3469      {
3470	operands[4] = operands[3];
3471	operands[5] = operands[2];
3472      }
3473  }"
3474)
3475
3476(define_insn "*arm_extendhisi_insn"
3477  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3478	(sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3479  "TARGET_ARM && arm_arch4"
3480  "ldr%?sh\\t%0, %1"
3481  [(set_attr "type" "load")
3482   (set_attr "predicable" "yes")
3483   (set_attr "pool_range" "256")
3484   (set_attr "neg_pool_range" "244")]
3485)
3486
3487(define_split
3488  [(set (match_operand:SI                 0 "s_register_operand" "")
3489	(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3490   (clobber (match_operand:SI             2 "s_register_operand" ""))]
3491  "TARGET_ARM && (!arm_arch4)"
3492  [(set (match_dup 2) (match_dup 1))
3493   (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3494  "
3495  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3496    FAIL;
3497  "
3498)
3499
3500(define_split
3501  [(set (match_operand:SI                   0 "s_register_operand" "")
3502	(match_operator:SI                  3 "shiftable_operator"
3503	 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3504	  (match_operand:SI                 4 "s_register_operand" "")]))
3505   (clobber (match_operand:SI               2 "s_register_operand" ""))]
3506  "TARGET_ARM && (!arm_arch4)"
3507  [(set (match_dup 2) (match_dup 1))
3508   (set (match_dup 0)
3509	(match_op_dup 3
3510	 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3511  "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3512     FAIL;
3513  "
3514)
3515
3516(define_expand "extendqihi2"
3517  [(set (match_dup 2)
3518	(ashift:SI (match_operand:QI 1 "general_operand" "")
3519		   (const_int 24)))
3520   (set (match_operand:HI 0 "s_register_operand" "")
3521	(ashiftrt:SI (match_dup 2)
3522		     (const_int 24)))]
3523  "TARGET_ARM"
3524  "
3525  {
3526    if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3527      {
3528	emit_insn (gen_rtx_SET (VOIDmode,
3529				operands[0],
3530				gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3531	DONE;
3532      }
3533    if (!s_register_operand (operands[1], QImode))
3534      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3535    operands[0] = gen_lowpart (SImode, operands[0]);
3536    operands[1] = gen_lowpart (SImode, operands[1]);
3537    operands[2] = gen_reg_rtx (SImode);
3538  }"
3539)
3540
3541; Rather than restricting all byte accesses to memory addresses that ldrsb
3542; can handle, we fix up the ones that ldrsb can't grok with a split.
3543(define_insn "*extendqihi_insn"
3544  [(set (match_operand:HI                 0 "s_register_operand" "=r")
3545	(sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3546  "TARGET_ARM && arm_arch4"
3547  "*
3548  /* If the address is invalid, this will split the instruction into two.  */
3549  if (bad_signed_byte_operand (operands[1], VOIDmode))
3550    return \"#\";
3551  return \"ldr%?sb\\t%0, %1\";
3552  "
3553  [(set_attr "type" "load")
3554   (set_attr "predicable" "yes")
3555   (set_attr "length" "8")
3556   (set_attr "pool_range" "256")
3557   (set_attr "neg_pool_range" "244")]
3558)
3559
3560(define_split
3561  [(set (match_operand:HI 0 "s_register_operand" "")
3562	(sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3563  "TARGET_ARM && arm_arch4 && reload_completed"
3564  [(set (match_dup 3) (match_dup 1))
3565   (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3566  "
3567  {
3568    HOST_WIDE_INT offset;
3569
3570    operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3571    operands[2] = gen_rtx_MEM (QImode, operands[3]);
3572    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3573    operands[1] = XEXP (operands[1], 0);
3574    if (GET_CODE (operands[1]) == PLUS
3575	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3576	&& !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3577	     || const_ok_for_arm (-offset)))
3578      {
3579	HOST_WIDE_INT low = (offset > 0
3580			     ? (offset & 0xff) : -((-offset) & 0xff));
3581	XEXP (operands[2], 0) = plus_constant (operands[3], low);
3582	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3583      }
3584    /* Ensure the sum is in correct canonical form.  */
3585    else if (GET_CODE (operands[1]) == PLUS
3586	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3587	     && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3588      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3589					   XEXP (operands[1], 1),
3590					   XEXP (operands[1], 0));
3591  }"
3592)
3593
3594(define_expand "extendqisi2"
3595  [(set (match_dup 2)
3596	(ashift:SI (match_operand:QI 1 "general_operand" "")
3597		   (const_int 24)))
3598   (set (match_operand:SI 0 "s_register_operand" "")
3599	(ashiftrt:SI (match_dup 2)
3600		     (const_int 24)))]
3601  "TARGET_EITHER"
3602  "
3603  {
3604    if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3605      {
3606        emit_insn (gen_rtx_SET (VOIDmode,
3607			        operands[0],
3608			        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3609        DONE;
3610      }
3611    if (!s_register_operand (operands[1], QImode))
3612      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3613    operands[1] = gen_lowpart (SImode, operands[1]);
3614    operands[2] = gen_reg_rtx (SImode);
3615    
3616    if (TARGET_THUMB)
3617      {
3618	rtx ops[3];
3619	
3620	ops[0] = operands[2];
3621	ops[1] = operands[1];
3622	ops[2] = GEN_INT (24);
3623	
3624        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3625		   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3626
3627	ops[0] = operands[0];
3628	ops[1] = operands[2];
3629	ops[2] = GEN_INT (24);
3630	
3631        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3632		   gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3633	
3634	DONE;
3635      }
3636  }"
3637)
3638
3639; Rather than restricting all byte accesses to memory addresses that ldrsb
3640; can handle, we fix up the ones that ldrsb can't grok with a split.
3641(define_insn "*arm_extendqisi_insn"
3642  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3643	(sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3644  "TARGET_ARM && arm_arch4"
3645  "*
3646  /* If the address is invalid, this will split the instruction into two.  */
3647  if (bad_signed_byte_operand (operands[1], VOIDmode))
3648    return \"#\";
3649  return \"ldr%?sb\\t%0, %1\";
3650  "
3651  [(set_attr "type" "load")
3652   (set_attr "predicable" "yes")
3653   (set_attr "length" "8")
3654   (set_attr "pool_range" "256")
3655   (set_attr "neg_pool_range" "244")]
3656)
3657
3658(define_split
3659  [(set (match_operand:SI 0 "s_register_operand" "")
3660	(sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3661  "TARGET_ARM && arm_arch4 && reload_completed"
3662  [(set (match_dup 0) (match_dup 1))
3663   (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3664  "
3665  {
3666    HOST_WIDE_INT offset;
3667
3668    operands[2] = gen_rtx_MEM (QImode, operands[0]);
3669    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3670    operands[1] = XEXP (operands[1], 0);
3671    if (GET_CODE (operands[1]) == PLUS
3672	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3673	&& !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3674	     || const_ok_for_arm (-offset)))
3675      {
3676	HOST_WIDE_INT low = (offset > 0
3677			     ? (offset & 0xff) : -((-offset) & 0xff));
3678	XEXP (operands[2], 0) = plus_constant (operands[0], low);
3679	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3680      }
3681    /* Ensure the sum is in correct canonical form.  */
3682    else if (GET_CODE (operands[1]) == PLUS
3683	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3684	     && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3685      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3686					   XEXP (operands[1], 1),
3687					   XEXP (operands[1], 0));
3688  }"
3689)
3690
3691(define_insn "*thumb_extendqisi2_insn"
3692  [(set (match_operand:SI                 0 "register_operand" "=l,l")
3693	(sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3694  "TARGET_THUMB"
3695  "*
3696  {
3697    rtx ops[3];
3698    rtx mem = XEXP (operands[1], 0);
3699    
3700    if (GET_CODE (mem) == CONST)
3701      mem = XEXP (mem, 0);
3702    
3703    if (GET_CODE (mem) == LABEL_REF)
3704      return \"ldr\\t%0, %1\";
3705
3706    if (GET_CODE (mem) == PLUS
3707        && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3708      return \"ldr\\t%0, %1\";
3709      
3710    if (which_alternative == 0)
3711      return \"ldrsb\\t%0, %1\";
3712      
3713    ops[0] = operands[0];
3714    
3715    if (GET_CODE (mem) == PLUS)
3716      {
3717        rtx a = XEXP (mem, 0);
3718	rtx b = XEXP (mem, 1);
3719	
3720        ops[1] = a;
3721        ops[2] = b;
3722
3723        if (GET_CODE (a) == REG)
3724	  {
3725	    if (GET_CODE (b) == REG)
3726              output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3727            else if (REGNO (a) == REGNO (ops[0]))
3728	      {
3729                output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3730		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3731		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3732	      }
3733	    else
3734              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3735	  }
3736        else if (GET_CODE (b) != REG)
3737	  abort ();
3738	else
3739          {
3740            if (REGNO (b) == REGNO (ops[0]))
3741	      {
3742                output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3743		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3744		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3745	      }
3746	    else
3747              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3748          }
3749      }
3750    else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3751      {
3752        output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3753	output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3754	output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3755      }
3756    else
3757      {
3758        ops[1] = mem;
3759        ops[2] = const0_rtx;
3760	
3761        output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3762      }
3763    return \"\";
3764  }"
3765  [(set_attr "length" "2,6")
3766   (set_attr "type" "load,load")
3767   (set_attr "pool_range" "32,32")]
3768)
3769
3770(define_expand "extendsfdf2"
3771  [(set (match_operand:DF                  0 "s_register_operand" "")
3772	(float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3773  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3774  ""
3775)
3776
3777;; Move insns (including loads and stores)
3778
3779;; XXX Just some ideas about movti.
3780;; I don't think these are a good idea on the arm, there just aren't enough
3781;; registers
3782;;(define_expand "loadti"
3783;;  [(set (match_operand:TI 0 "s_register_operand" "")
3784;;	(mem:TI (match_operand:SI 1 "address_operand" "")))]
3785;;  "" "")
3786
3787;;(define_expand "storeti"
3788;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3789;;	(match_operand:TI 1 "s_register_operand" ""))]
3790;;  "" "")
3791
3792;;(define_expand "movti"
3793;;  [(set (match_operand:TI 0 "general_operand" "")
3794;;	(match_operand:TI 1 "general_operand" ""))]
3795;;  ""
3796;;  "
3797;;{
3798;;  rtx insn;
3799;;
3800;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3801;;    operands[1] = copy_to_reg (operands[1]);
3802;;  if (GET_CODE (operands[0]) == MEM)
3803;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3804;;  else if (GET_CODE (operands[1]) == MEM)
3805;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3806;;  else
3807;;    FAIL;
3808;;
3809;;  emit_insn (insn);
3810;;  DONE;
3811;;}")
3812
3813;; Recognize garbage generated above.
3814
3815;;(define_insn ""
3816;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3817;;	(match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3818;;  ""
3819;;  "*
3820;;  {
3821;;    register mem = (which_alternative < 3);
3822;;    register const char *template;
3823;;
3824;;    operands[mem] = XEXP (operands[mem], 0);
3825;;    switch (which_alternative)
3826;;      {
3827;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3828;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3829;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3830;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3831;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3832;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3833;;      }
3834;;    output_asm_insn (template, operands);
3835;;    return \"\";
3836;;  }")
3837
3838(define_expand "movdi"
3839  [(set (match_operand:DI 0 "general_operand" "")
3840	(match_operand:DI 1 "general_operand" ""))]
3841  "TARGET_EITHER"
3842  "
3843  if (TARGET_THUMB)
3844    {
3845      if (!no_new_pseudos)
3846        {
3847          if (GET_CODE (operands[0]) != REG)
3848	    operands[1] = force_reg (DImode, operands[1]);
3849        }
3850    }
3851  "
3852)
3853
3854(define_insn "*arm_movdi"
3855  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3856	(match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3857  "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
3858  "*
3859  return (output_move_double (operands));
3860  "
3861  [(set_attr "length" "8")
3862   (set_attr "type" "*,load,store2")
3863   (set_attr "pool_range" "*,1020,*")
3864   (set_attr "neg_pool_range" "*,1008,*")]
3865)
3866
3867;;; ??? This should have alternatives for constants.
3868;;; ??? This was originally identical to the movdf_insn pattern.
3869;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3870;;; thumb_reorg with a memory reference.
3871(define_insn "*thumb_movdi_insn"
3872  [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3873	(match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3874  "TARGET_THUMB
3875   && !TARGET_CIRRUS
3876   && (   register_operand (operands[0], DImode)
3877       || register_operand (operands[1], DImode))"
3878  "*
3879  {
3880  switch (which_alternative)
3881    {
3882    default:
3883    case 0:
3884      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3885	return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3886      return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3887    case 1:
3888      return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3889    case 2:
3890      operands[1] = GEN_INT (- INTVAL (operands[1]));
3891      return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3892    case 3:
3893      return \"ldmia\\t%1, {%0, %H0}\";
3894    case 4:
3895      return \"stmia\\t%0, {%1, %H1}\";
3896    case 5:
3897      return thumb_load_double_from_address (operands);
3898    case 6:
3899      operands[2] = gen_rtx (MEM, SImode,
3900			     plus_constant (XEXP (operands[0], 0), 4));
3901      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3902      return \"\";
3903    case 7:
3904      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3905	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3906      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3907    }
3908  }"
3909  [(set_attr "length" "4,4,6,2,2,6,4,4")
3910   (set_attr "type" "*,*,*,load,store2,load,store2,*")
3911   (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3912)
3913
3914(define_expand "movsi"
3915  [(set (match_operand:SI 0 "general_operand" "")
3916        (match_operand:SI 1 "general_operand" ""))]
3917  "TARGET_EITHER"
3918  "
3919  if (TARGET_ARM)
3920    {
3921      /* Everything except mem = const or mem = mem can be done easily.  */
3922      if (GET_CODE (operands[0]) == MEM)
3923        operands[1] = force_reg (SImode, operands[1]);
3924      if (GET_CODE (operands[1]) == CONST_INT
3925          && !(const_ok_for_arm (INTVAL (operands[1]))
3926               || const_ok_for_arm (~INTVAL (operands[1]))))
3927        {
3928           arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3929		    	      NULL_RTX,
3930			      (no_new_pseudos ? 0
3931			       : preserve_subexpressions_p ()));
3932          DONE;
3933        }
3934    }
3935  else /* TARGET_THUMB....  */
3936    {
3937      if (!no_new_pseudos)
3938        {
3939          if (GET_CODE (operands[0]) != REG)
3940	    operands[1] = force_reg (SImode, operands[1]);
3941        }
3942    }
3943    
3944  if (flag_pic
3945      && (CONSTANT_P (operands[1])
3946	 || symbol_mentioned_p (operands[1])
3947	 || label_mentioned_p (operands[1])))
3948    operands[1] = legitimize_pic_address (operands[1], SImode,
3949					  (no_new_pseudos ? operands[0] : 0));
3950  "
3951)
3952
3953(define_insn "*arm_movsi_insn"
3954  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3955	(match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
3956  "TARGET_ARM && ! TARGET_IWMMXT
3957   && (   register_operand (operands[0], SImode)
3958       || register_operand (operands[1], SImode))"
3959  "@
3960   mov%?\\t%0, %1
3961   mvn%?\\t%0, #%B1
3962   ldr%?\\t%0, %1
3963   str%?\\t%1, %0"
3964  [(set_attr "type" "*,*,load,store1")
3965   (set_attr "predicable" "yes")
3966   (set_attr "pool_range" "*,*,4096,*")
3967   (set_attr "neg_pool_range" "*,*,4084,*")]
3968)
3969
3970(define_split
3971  [(set (match_operand:SI 0 "s_register_operand" "")
3972	(match_operand:SI 1 "const_int_operand" ""))]
3973  "TARGET_ARM
3974  && (!(const_ok_for_arm (INTVAL (operands[1]))
3975        || const_ok_for_arm (~INTVAL (operands[1]))))"
3976  [(clobber (const_int 0))]
3977  "
3978  arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3979		      NULL_RTX, 0);
3980  DONE;
3981  "
3982)
3983
3984(define_insn "*thumb_movsi_insn"
3985  [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3986	(match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
3987  "TARGET_THUMB
3988   && (   register_operand (operands[0], SImode) 
3989       || register_operand (operands[1], SImode))"
3990  "@
3991   mov	%0, %1
3992   mov	%0, %1
3993   #
3994   #
3995   ldmia\\t%1, {%0}
3996   stmia\\t%0, {%1}
3997   ldr\\t%0, %1
3998   str\\t%1, %0
3999   mov\\t%0, %1"
4000  [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4001   (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4002   (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4003)
4004
4005(define_split 
4006  [(set (match_operand:SI 0 "register_operand" "")
4007	(match_operand:SI 1 "const_int_operand" ""))]
4008  "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4009  [(set (match_dup 0) (match_dup 1))
4010   (set (match_dup 0) (neg:SI (match_dup 0)))]
4011  "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4012)
4013
4014(define_split 
4015  [(set (match_operand:SI 0 "register_operand" "")
4016	(match_operand:SI 1 "const_int_operand" ""))]
4017  "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4018  [(set (match_dup 0) (match_dup 1))
4019   (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4020  "
4021  {
4022    unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4023    unsigned HOST_WIDE_INT mask = 0xff;
4024    int i;
4025    
4026    for (i = 0; i < 25; i++)
4027      if ((val & (mask << i)) == val)
4028        break;
4029
4030    /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4031    if (i == 0)
4032      FAIL;
4033
4034    operands[1] = GEN_INT (val >> i);
4035    operands[2] = GEN_INT (i);
4036  }"
4037)
4038
4039;; When generating pic, we need to load the symbol offset into a register.
4040;; So that the optimizer does not confuse this with a normal symbol load
4041;; we use an unspec.  The offset will be loaded from a constant pool entry,
4042;; since that is the only type of relocation we can use.
4043
4044;; The rather odd constraints on the following are to force reload to leave
4045;; the insn alone, and to force the minipool generation pass to then move
4046;; the GOT symbol to memory.
4047
4048(define_insn "pic_load_addr_arm"
4049  [(set (match_operand:SI 0 "s_register_operand" "=r")
4050	(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4051  "TARGET_ARM && flag_pic"
4052  "ldr%?\\t%0, %1"
4053  [(set_attr "type" "load")
4054   (set (attr "pool_range")     (const_int 4096))
4055   (set (attr "neg_pool_range") (const_int 4084))]
4056)
4057
4058(define_insn "pic_load_addr_thumb"
4059  [(set (match_operand:SI 0 "s_register_operand" "=l")
4060	(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4061  "TARGET_THUMB && flag_pic"
4062  "ldr\\t%0, %1"
4063  [(set_attr "type" "load")
4064   (set (attr "pool_range") (const_int 1024))]
4065)
4066
4067;; This variant is used for AOF assembly, since it needs to mention the
4068;; pic register in the rtl.
4069(define_expand "pic_load_addr_based"
4070  [(set (match_operand:SI 0 "s_register_operand" "")
4071	(unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4072  "TARGET_ARM && flag_pic"
4073  "operands[2] = pic_offset_table_rtx;"
4074)
4075
4076(define_insn "*pic_load_addr_based_insn"
4077  [(set (match_operand:SI 0 "s_register_operand" "=r")
4078	(unspec:SI [(match_operand 1 "" "")
4079		    (match_operand 2 "s_register_operand" "r")]
4080		   UNSPEC_PIC_SYM))]
4081  "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4082  "*
4083#ifdef AOF_ASSEMBLER
4084  operands[1] = aof_pic_entry (operands[1]);
4085#endif
4086  output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4087  return \"\";
4088  "
4089  [(set_attr "type" "load")
4090   (set (attr "pool_range")
4091	(if_then_else (eq_attr "is_thumb" "yes")
4092		      (const_int 1024)
4093		      (const_int 4096)))
4094   (set (attr "neg_pool_range")
4095	(if_then_else (eq_attr "is_thumb" "yes")
4096		      (const_int 0)
4097		      (const_int 4084)))]
4098)
4099
4100(define_insn "pic_add_dot_plus_four"
4101  [(set (match_operand:SI 0 "register_operand" "+r")
4102	(unspec:SI [(plus:SI (match_dup 0)
4103			     (const (plus:SI (pc) (const_int 4))))]
4104		   UNSPEC_PIC_BASE))
4105   (use (label_ref (match_operand 1 "" "")))]
4106  "TARGET_THUMB && flag_pic"
4107  "*
4108  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4109			     CODE_LABEL_NUMBER (operands[1]));
4110  return \"add\\t%0, %|pc\";
4111  "
4112  [(set_attr "length" "2")]
4113)
4114
4115(define_insn "pic_add_dot_plus_eight"
4116  [(set (match_operand:SI 0 "register_operand" "+r")
4117	(unspec:SI [(plus:SI (match_dup 0)
4118			     (const (plus:SI (pc) (const_int 8))))]
4119		   UNSPEC_PIC_BASE))
4120   (use (label_ref (match_operand 1 "" "")))]
4121  "TARGET_ARM && flag_pic"
4122  "*
4123    (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4124			       CODE_LABEL_NUMBER (operands[1]));
4125    return \"add%?\\t%0, %|pc, %0\";
4126  "
4127  [(set_attr "predicable" "yes")]
4128)
4129
4130(define_expand "builtin_setjmp_receiver"
4131  [(label_ref (match_operand 0 "" ""))]
4132  "flag_pic"
4133  "
4134{
4135  arm_finalize_pic (0);
4136  DONE;
4137}")
4138
4139;; If copying one reg to another we can set the condition codes according to
4140;; its value.  Such a move is common after a return from subroutine and the
4141;; result is being tested against zero.
4142
4143(define_insn "*movsi_compare0"
4144  [(set (reg:CC CC_REGNUM)
4145	(compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4146		    (const_int 0)))
4147   (set (match_operand:SI 0 "s_register_operand" "=r,r")
4148	(match_dup 1))]
4149  "TARGET_ARM"
4150  "@
4151   cmp%?\\t%0, #0
4152   sub%?s\\t%0, %1, #0"
4153  [(set_attr "conds" "set")]
4154)
4155
4156;; Subroutine to store a half word from a register into memory.
4157;; Operand 0 is the source register (HImode)
4158;; Operand 1 is the destination address in a register (SImode)
4159
4160;; In both this routine and the next, we must be careful not to spill
4161;; a memory address of reg+large_const into a separate PLUS insn, since this
4162;; can generate unrecognizable rtl.
4163
4164(define_expand "storehi"
4165  [;; store the low byte
4166   (set (match_operand 1 "" "") (match_dup 3))
4167   ;; extract the high byte
4168   (set (match_dup 2)
4169	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4170   ;; store the high byte
4171   (set (match_dup 4) (match_dup 5))]
4172  "TARGET_ARM"
4173  "
4174  {
4175    rtx op1 = operands[1];
4176    rtx addr = XEXP (op1, 0);
4177    enum rtx_code code = GET_CODE (addr);
4178
4179    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4180	|| code == MINUS)
4181      op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4182
4183    operands[4] = adjust_address (op1, QImode, 1);
4184    operands[1] = adjust_address (operands[1], QImode, 0);
4185    operands[3] = gen_lowpart (QImode, operands[0]);
4186    operands[0] = gen_lowpart (SImode, operands[0]);
4187    operands[2] = gen_reg_rtx (SImode);
4188    operands[5] = gen_lowpart (QImode, operands[2]);
4189  }"
4190)
4191
4192(define_expand "storehi_bigend"
4193  [(set (match_dup 4) (match_dup 3))
4194   (set (match_dup 2)
4195	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4196   (set (match_operand 1 "" "")	(match_dup 5))]
4197  "TARGET_ARM"
4198  "
4199  {
4200    rtx op1 = operands[1];
4201    rtx addr = XEXP (op1, 0);
4202    enum rtx_code code = GET_CODE (addr);
4203
4204    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4205	|| code == MINUS)
4206      op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4207
4208    operands[4] = adjust_address (op1, QImode, 1);
4209    operands[1] = adjust_address (operands[1], QImode, 0);
4210    operands[3] = gen_lowpart (QImode, operands[0]);
4211    operands[0] = gen_lowpart (SImode, operands[0]);
4212    operands[2] = gen_reg_rtx (SImode);
4213    operands[5] = gen_lowpart (QImode, operands[2]);
4214  }"
4215)
4216
4217;; Subroutine to store a half word integer constant into memory.
4218(define_expand "storeinthi"
4219  [(set (match_operand 0 "" "")
4220	(match_operand 1 "" ""))
4221   (set (match_dup 3) (match_dup 2))]
4222  "TARGET_ARM"
4223  "
4224  {
4225    HOST_WIDE_INT value = INTVAL (operands[1]);
4226    rtx addr = XEXP (operands[0], 0);
4227    rtx op0 = operands[0];
4228    enum rtx_code code = GET_CODE (addr);
4229
4230    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4231	|| code == MINUS)
4232      op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4233
4234    operands[1] = gen_reg_rtx (SImode);
4235    if (BYTES_BIG_ENDIAN)
4236      {
4237	emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4238	if ((value & 255) == ((value >> 8) & 255))
4239	  operands[2] = operands[1];
4240	else
4241	  {
4242	    operands[2] = gen_reg_rtx (SImode);
4243	    emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4244	  }
4245      }
4246    else
4247      {
4248	emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4249	if ((value & 255) == ((value >> 8) & 255))
4250	  operands[2] = operands[1];
4251	else
4252	  {
4253	    operands[2] = gen_reg_rtx (SImode);
4254	    emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4255	  }
4256      }
4257
4258    operands[3] = adjust_address (op0, QImode, 1);
4259    operands[0] = adjust_address (operands[0], QImode, 0);
4260    operands[2] = gen_lowpart (QImode, operands[2]);
4261    operands[1] = gen_lowpart (QImode, operands[1]);
4262  }"
4263)
4264
4265(define_expand "storehi_single_op"
4266  [(set (match_operand:HI 0 "memory_operand" "")
4267	(match_operand:HI 1 "general_operand" ""))]
4268  "TARGET_ARM && arm_arch4"
4269  "
4270  if (!s_register_operand (operands[1], HImode))
4271    operands[1] = copy_to_mode_reg (HImode, operands[1]);
4272  "
4273)
4274
4275(define_expand "movhi"
4276  [(set (match_operand:HI 0 "general_operand" "")
4277	(match_operand:HI 1 "general_operand" ""))]
4278  "TARGET_EITHER"
4279  "
4280  if (TARGET_ARM)
4281    {
4282      if (!no_new_pseudos)
4283        {
4284          if (GET_CODE (operands[0]) == MEM)
4285	    {
4286	      if (arm_arch4)
4287	        {
4288	          emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4289	          DONE;
4290	        }
4291	      if (GET_CODE (operands[1]) == CONST_INT)
4292	        emit_insn (gen_storeinthi (operands[0], operands[1]));
4293	      else
4294	        {
4295	          if (GET_CODE (operands[1]) == MEM)
4296		    operands[1] = force_reg (HImode, operands[1]);
4297	          if (BYTES_BIG_ENDIAN)
4298		    emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4299	          else
4300		   emit_insn (gen_storehi (operands[1], operands[0]));
4301	        }
4302	      DONE;
4303	    }
4304          /* Sign extend a constant, and keep it in an SImode reg.  */
4305          else if (GET_CODE (operands[1]) == CONST_INT)
4306	    {
4307	      rtx reg = gen_reg_rtx (SImode);
4308	      HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4309
4310	      /* If the constant is already valid, leave it alone.  */
4311	      if (!const_ok_for_arm (val))
4312	        {
4313	          /* If setting all the top bits will make the constant 
4314		     loadable in a single instruction, then set them.  
4315		     Otherwise, sign extend the number.  */
4316
4317	          if (const_ok_for_arm (~(val | ~0xffff)))
4318		    val |= ~0xffff;
4319	          else if (val & 0x8000)
4320		    val |= ~0xffff;
4321	        }
4322
4323	      emit_insn (gen_movsi (reg, GEN_INT (val)));
4324	      operands[1] = gen_lowpart (HImode, reg);
4325	    }
4326	  else if (arm_arch4 && !no_new_pseudos && optimize > 0
4327		   && GET_CODE (operands[1]) == MEM)
4328	    {
4329	      rtx reg = gen_reg_rtx (SImode);
4330
4331	      emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4332	      operands[1] = gen_lowpart (HImode, reg);
4333	    }
4334          else if (!arm_arch4)
4335	    {
4336	     /* Note: We do not have to worry about TARGET_MMU_TRAPS
4337	        for v4 and up architectures because LDRH instructions will
4338	        be used to access the HI values, and these cannot generate
4339	        unaligned word access faults in the MMU.  */
4340	      if (GET_CODE (operands[1]) == MEM)
4341	        {
4342	          if (TARGET_MMU_TRAPS)
4343		    {
4344		      rtx base;
4345		      rtx offset = const0_rtx;
4346		      rtx reg = gen_reg_rtx (SImode);
4347
4348		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4349		           || (GET_CODE (base) == PLUS
4350			       && (GET_CODE (offset = XEXP (base, 1))
4351				   == CONST_INT)
4352                               && ((INTVAL(offset) & 1) != 1)
4353			       && GET_CODE (base = XEXP (base, 0)) == REG))
4354		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4355		        {
4356		          HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4357		          rtx new;
4358
4359		          new = gen_rtx_MEM (SImode,
4360				   	     plus_constant (base, new_offset));
4361	                  MEM_COPY_ATTRIBUTES (new, operands[1]);
4362		          emit_insn (gen_movsi (reg, new));
4363		          if (((INTVAL (offset) & 2) != 0)
4364			      ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4365			    {
4366			      rtx reg2 = gen_reg_rtx (SImode);
4367
4368			      emit_insn (gen_lshrsi3 (reg2, reg,
4369					 GEN_INT (16)));
4370			      reg = reg2;
4371			    }
4372		        }
4373		      else
4374		        emit_insn (gen_movhi_bytes (reg, operands[1]));
4375
4376		      operands[1] = gen_lowpart (HImode, reg);
4377		    }
4378	          else if (BYTES_BIG_ENDIAN)
4379		    {
4380		      rtx base;
4381		      rtx offset = const0_rtx;
4382
4383		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4384		           || (GET_CODE (base) == PLUS
4385			      && (GET_CODE (offset = XEXP (base, 1))
4386				  == CONST_INT)
4387			      && GET_CODE (base = XEXP (base, 0)) == REG))
4388		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4389		        {
4390		          rtx reg = gen_reg_rtx (SImode);
4391		          rtx new;
4392
4393		          if ((INTVAL (offset) & 2) == 2)
4394			    {
4395			      HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4396			      new = gen_rtx_MEM (SImode,
4397				  	         plus_constant (base,
4398								new_offset));
4399                              MEM_COPY_ATTRIBUTES (new, operands[1]);
4400			      emit_insn (gen_movsi (reg, new));
4401			    }
4402		          else
4403			    {
4404			      new = gen_rtx_MEM (SImode,
4405						 XEXP (operands[1], 0));
4406	                      MEM_COPY_ATTRIBUTES (new, operands[1]);
4407			      emit_insn (gen_rotated_loadsi (reg, new));
4408			    }
4409
4410		          operands[1] = gen_lowpart (HImode, reg);
4411		        }
4412		      else
4413		        {
4414		          emit_insn (gen_movhi_bigend (operands[0],
4415						       operands[1]));
4416		          DONE;
4417		        }
4418		    }
4419	       }
4420	   }
4421        }
4422      /* Handle loading a large integer during reload.  */
4423      else if (GET_CODE (operands[1]) == CONST_INT
4424	       && !const_ok_for_arm (INTVAL (operands[1]))
4425	       && !const_ok_for_arm (~INTVAL (operands[1])))
4426        {
4427          /* Writing a constant to memory needs a scratch, which should
4428	     be handled with SECONDARY_RELOADs.  */
4429          if (GET_CODE (operands[0]) != REG)
4430	    abort ();
4431
4432          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4433          emit_insn (gen_movsi (operands[0], operands[1]));
4434          DONE;
4435       }
4436    }
4437  else /* TARGET_THUMB */
4438    {
4439      if (!no_new_pseudos)
4440        {
4441          if (GET_CODE (operands[0]) != REG)
4442	    operands[1] = force_reg (HImode, operands[1]);
4443
4444          /* ??? We shouldn't really get invalid addresses here, but this can
4445	     happen if we are passed a SP (never OK for HImode/QImode) or 
4446	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4447	     HImode/QImode) relative address.  */
4448          /* ??? This should perhaps be fixed elsewhere, for instance, in
4449	     fixup_stack_1, by checking for other kinds of invalid addresses,
4450	     e.g. a bare reference to a virtual register.  This may confuse the
4451	     alpha though, which must handle this case differently.  */
4452          if (GET_CODE (operands[0]) == MEM
4453	      && !memory_address_p (GET_MODE (operands[0]),
4454				    XEXP (operands[0], 0)))
4455	    operands[0]
4456	      = replace_equiv_address (operands[0],
4457				       copy_to_reg (XEXP (operands[0], 0)));
4458   
4459          if (GET_CODE (operands[1]) == MEM
4460	      && !memory_address_p (GET_MODE (operands[1]),
4461				    XEXP (operands[1], 0)))
4462	    operands[1]
4463	      = replace_equiv_address (operands[1],
4464				       copy_to_reg (XEXP (operands[1], 0)));
4465        }
4466      /* Handle loading a large integer during reload.  */
4467      else if (GET_CODE (operands[1]) == CONST_INT
4468	        && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4469        {
4470          /* Writing a constant to memory needs a scratch, which should
4471	     be handled with SECONDARY_RELOADs.  */
4472          if (GET_CODE (operands[0]) != REG)
4473	    abort ();
4474
4475          operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4476          emit_insn (gen_movsi (operands[0], operands[1]));
4477          DONE;
4478        }
4479    }
4480  "
4481)
4482
4483(define_insn "*thumb_movhi_insn"
4484  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4485	(match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4486  "TARGET_THUMB
4487   && (   register_operand (operands[0], HImode)
4488       || register_operand (operands[1], HImode))"
4489  "*
4490  switch (which_alternative)
4491    {
4492    case 0: return \"add	%0, %1, #0\";
4493    case 2: return \"strh	%1, %0\";
4494    case 3: return \"mov	%0, %1\";
4495    case 4: return \"mov	%0, %1\";
4496    case 5: return \"mov	%0, %1\";
4497    default: abort ();
4498    case 1:
4499      /* The stack pointer can end up being taken as an index register.
4500          Catch this case here and deal with it.  */
4501      if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4502	  && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4503	  && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4504        {
4505	  rtx ops[2];
4506          ops[0] = operands[0];
4507          ops[1] = XEXP (XEXP (operands[1], 0), 0);
4508      
4509          output_asm_insn (\"mov	%0, %1\", ops);
4510
4511          XEXP (XEXP (operands[1], 0), 0) = operands[0];
4512    
4513	}
4514      return \"ldrh	%0, %1\";
4515    }"
4516  [(set_attr "length" "2,4,2,2,2,2")
4517   (set_attr "type" "*,load,store1,*,*,*")]
4518)
4519
4520
4521(define_insn "rotated_loadsi"
4522  [(set (match_operand:SI            0 "s_register_operand"        "=r")
4523	(rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4524		   (const_int 16)))]
4525  "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4526  "*
4527  {
4528    rtx ops[2];
4529
4530    ops[0] = operands[0];
4531    ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4532    output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4533    return \"\";
4534  }"
4535  [(set_attr "type" "load")
4536   (set_attr "predicable" "yes")]
4537)
4538
4539(define_expand "movhi_bytes"
4540  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4541   (set (match_dup 3)
4542	(zero_extend:SI (match_dup 6)))
4543   (set (match_operand:SI 0 "" "")
4544	 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4545  "TARGET_ARM"
4546  "
4547  {
4548    rtx mem1, mem2;
4549    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4550
4551    mem1 = gen_rtx_MEM (QImode, addr);
4552    MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4553    mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4554    MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4555    operands[0] = gen_lowpart (SImode, operands[0]);
4556    operands[1] = mem1;
4557    operands[2] = gen_reg_rtx (SImode);
4558    operands[3] = gen_reg_rtx (SImode);
4559    operands[6] = mem2;
4560
4561    if (BYTES_BIG_ENDIAN)
4562      {
4563	operands[4] = operands[2];
4564	operands[5] = operands[3];
4565      }
4566    else
4567      {
4568	operands[4] = operands[3];
4569	operands[5] = operands[2];
4570      }
4571  }"
4572)
4573
4574(define_expand "movhi_bigend"
4575  [(set (match_dup 2)
4576	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4577		   (const_int 16)))
4578   (set (match_dup 3)
4579	(ashiftrt:SI (match_dup 2) (const_int 16)))
4580   (set (match_operand:HI 0 "s_register_operand" "")
4581	(match_dup 4))]
4582  "TARGET_ARM"
4583  "
4584  operands[2] = gen_reg_rtx (SImode);
4585  operands[3] = gen_reg_rtx (SImode);
4586  operands[4] = gen_lowpart (HImode, operands[3]);
4587  "
4588)
4589
4590;; Pattern to recognize insn generated default case above
4591(define_insn "*movhi_insn_arch4"
4592  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4593	(match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4594  "TARGET_ARM
4595   && arm_arch4
4596   && (GET_CODE (operands[1]) != CONST_INT
4597       || const_ok_for_arm (INTVAL (operands[1]))
4598       || const_ok_for_arm (~INTVAL (operands[1])))"
4599  "@
4600   mov%?\\t%0, %1\\t%@ movhi
4601   mvn%?\\t%0, #%B1\\t%@ movhi
4602   str%?h\\t%1, %0\\t%@ movhi 
4603   ldr%?h\\t%0, %1\\t%@ movhi"
4604  [(set_attr "type" "*,*,store1,load")
4605   (set_attr "predicable" "yes")
4606   (set_attr "pool_range" "*,*,*,256")
4607   (set_attr "neg_pool_range" "*,*,*,244")]
4608)
4609
4610(define_insn "*movhi_insn_littleend"
4611  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4612	(match_operand:HI 1 "general_operand"  "rI,K,m"))]
4613  "TARGET_ARM
4614   && !arm_arch4
4615   && !BYTES_BIG_ENDIAN
4616   && !TARGET_MMU_TRAPS
4617   && (GET_CODE (operands[1]) != CONST_INT
4618       || const_ok_for_arm (INTVAL (operands[1]))
4619       || const_ok_for_arm (~INTVAL (operands[1])))"
4620  "@
4621   mov%?\\t%0, %1\\t%@ movhi
4622   mvn%?\\t%0, #%B1\\t%@ movhi
4623   ldr%?\\t%0, %1\\t%@ movhi"
4624  [(set_attr "type" "*,*,load")
4625   (set_attr "predicable" "yes")
4626   (set_attr "pool_range" "4096")
4627   (set_attr "neg_pool_range" "4084")]
4628)
4629
4630(define_insn "*movhi_insn_bigend"
4631  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4632	(match_operand:HI 1 "general_operand"    "rI,K,m"))]
4633  "TARGET_ARM
4634   && !arm_arch4
4635   && BYTES_BIG_ENDIAN
4636   && !TARGET_MMU_TRAPS
4637   && (GET_CODE (operands[1]) != CONST_INT
4638       || const_ok_for_arm (INTVAL (operands[1]))
4639       || const_ok_for_arm (~INTVAL (operands[1])))"
4640  "@
4641   mov%?\\t%0, %1\\t%@ movhi
4642   mvn%?\\t%0, #%B1\\t%@ movhi
4643   ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4644  [(set_attr "type" "*,*,load")
4645   (set_attr "predicable" "yes")
4646   (set_attr "length" "4,4,8")
4647   (set_attr "pool_range" "*,*,4092")
4648   (set_attr "neg_pool_range" "*,*,4084")]
4649)
4650
4651(define_insn "*loadhi_si_bigend"
4652  [(set (match_operand:SI                       0 "s_register_operand" "=r")
4653	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4654		   (const_int 16)))]
4655  "TARGET_ARM
4656   && BYTES_BIG_ENDIAN
4657   && !TARGET_MMU_TRAPS"
4658  "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4659  [(set_attr "type" "load")
4660   (set_attr "predicable" "yes")
4661   (set_attr "pool_range" "4096")
4662   (set_attr "neg_pool_range" "4084")]
4663)
4664
4665(define_insn "*movhi_bytes"
4666  [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4667	(match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4668  "TARGET_ARM && TARGET_MMU_TRAPS"
4669  "@
4670   mov%?\\t%0, %1\\t%@ movhi
4671   mvn%?\\t%0, #%B1\\t%@ movhi"
4672  [(set_attr "predicable" "yes")]
4673)
4674
4675(define_insn "thumb_movhi_clobber"
4676  [(set (match_operand:HI     0 "memory_operand"   "=m")
4677	(match_operand:HI     1 "register_operand" "l"))
4678   (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4679  "TARGET_THUMB"
4680  "*
4681  abort ();"
4682)
4683	
4684;; We use a DImode scratch because we may occasionally need an additional
4685;; temporary if the address isn't offsettable -- push_reload doesn't seem
4686;; to take any notice of the "o" constraints on reload_memory_operand operand.
4687(define_expand "reload_outhi"
4688  [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4689	      (match_operand:HI 1 "s_register_operand"        "r")
4690	      (match_operand:DI 2 "s_register_operand"        "=&l")])]
4691  "TARGET_EITHER"
4692  "if (TARGET_ARM)
4693     arm_reload_out_hi (operands);
4694   else
4695     thumb_reload_out_hi (operands);
4696  DONE;
4697  "
4698)
4699
4700(define_expand "reload_inhi"
4701  [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4702	      (match_operand:HI 1 "arm_reload_memory_operand" "o")
4703	      (match_operand:DI 2 "s_register_operand" "=&r")])]
4704  "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4705  "
4706  if (TARGET_ARM)
4707    arm_reload_in_hi (operands);
4708  else
4709    thumb_reload_out_hi (operands);
4710  DONE;
4711")
4712
4713(define_expand "movqi"
4714  [(set (match_operand:QI 0 "general_operand" "")
4715        (match_operand:QI 1 "general_operand" ""))]
4716  "TARGET_EITHER"
4717  "
4718  if (TARGET_ARM)
4719    {
4720      /* Everything except mem = const or mem = mem can be done easily */
4721
4722      if (!no_new_pseudos)
4723        {
4724          if (GET_CODE (operands[1]) == CONST_INT)
4725	    {
4726	      rtx reg = gen_reg_rtx (SImode);
4727
4728	      emit_insn (gen_movsi (reg, operands[1]));
4729	      operands[1] = gen_lowpart (QImode, reg);
4730	    }
4731	  if (GET_CODE (operands[1]) == MEM && optimize > 0)
4732	    {
4733	      rtx reg = gen_reg_rtx (SImode);
4734
4735	      emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4736	      operands[1] = gen_lowpart (QImode, reg);
4737	    }
4738          if (GET_CODE (operands[0]) == MEM)
4739	    operands[1] = force_reg (QImode, operands[1]);
4740        }
4741    }
4742  else /* TARGET_THUMB */
4743    {
4744      if (!no_new_pseudos)
4745        {
4746          if (GET_CODE (operands[0]) != REG)
4747	    operands[1] = force_reg (QImode, operands[1]);
4748
4749          /* ??? We shouldn't really get invalid addresses here, but this can
4750	     happen if we are passed a SP (never OK for HImode/QImode) or
4751	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4752	     HImode/QImode) relative address.  */
4753          /* ??? This should perhaps be fixed elsewhere, for instance, in
4754	     fixup_stack_1, by checking for other kinds of invalid addresses,
4755	     e.g. a bare reference to a virtual register.  This may confuse the
4756	     alpha though, which must handle this case differently.  */
4757          if (GET_CODE (operands[0]) == MEM
4758	      && !memory_address_p (GET_MODE (operands[0]),
4759		  		     XEXP (operands[0], 0)))
4760	    operands[0]
4761	      = replace_equiv_address (operands[0],
4762				       copy_to_reg (XEXP (operands[0], 0)));
4763          if (GET_CODE (operands[1]) == MEM
4764	      && !memory_address_p (GET_MODE (operands[1]),
4765				    XEXP (operands[1], 0)))
4766	     operands[1]
4767	       = replace_equiv_address (operands[1],
4768					copy_to_reg (XEXP (operands[1], 0)));
4769        }
4770      /* Handle loading a large integer during reload.  */
4771      else if (GET_CODE (operands[1]) == CONST_INT
4772	       && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4773        {
4774          /* Writing a constant to memory needs a scratch, which should
4775	     be handled with SECONDARY_RELOADs.  */
4776          if (GET_CODE (operands[0]) != REG)
4777	    abort ();
4778
4779          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4780          emit_insn (gen_movsi (operands[0], operands[1]));
4781          DONE;
4782       }
4783    }
4784  "
4785)
4786
4787
4788(define_insn "*arm_movqi_insn"
4789  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4790	(match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4791  "TARGET_ARM
4792   && (   register_operand (operands[0], QImode)
4793       || register_operand (operands[1], QImode))"
4794  "@
4795   mov%?\\t%0, %1
4796   mvn%?\\t%0, #%B1
4797   ldr%?b\\t%0, %1
4798   str%?b\\t%1, %0"
4799  [(set_attr "type" "*,*,load,store1")
4800   (set_attr "predicable" "yes")]
4801)
4802
4803(define_insn "*thumb_movqi_insn"
4804  [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4805	(match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4806  "TARGET_THUMB
4807   && (   register_operand (operands[0], QImode)
4808       || register_operand (operands[1], QImode))"
4809  "@
4810   add\\t%0, %1, #0
4811   ldrb\\t%0, %1
4812   strb\\t%1, %0
4813   mov\\t%0, %1
4814   mov\\t%0, %1
4815   mov\\t%0, %1"
4816  [(set_attr "length" "2")
4817   (set_attr "type" "*,load,store1,*,*,*")
4818   (set_attr "pool_range" "*,32,*,*,*,*")]
4819)
4820
4821(define_expand "movsf"
4822  [(set (match_operand:SF 0 "general_operand" "")
4823	(match_operand:SF 1 "general_operand" ""))]
4824  "TARGET_EITHER"
4825  "
4826  if (TARGET_ARM)
4827    {
4828      if (GET_CODE (operands[0]) == MEM)
4829        operands[1] = force_reg (SFmode, operands[1]);
4830    }
4831  else /* TARGET_THUMB */
4832    {
4833      if (!no_new_pseudos)
4834        {
4835           if (GET_CODE (operands[0]) != REG)
4836	     operands[1] = force_reg (SFmode, operands[1]);
4837        }
4838    }
4839  "
4840)
4841
4842(define_split
4843  [(set (match_operand:SF 0 "nonimmediate_operand" "")
4844	(match_operand:SF 1 "immediate_operand" ""))]
4845  "TARGET_ARM
4846   && !TARGET_HARD_FLOAT
4847   && reload_completed
4848   && GET_CODE (operands[1]) == CONST_DOUBLE"
4849  [(set (match_dup 2) (match_dup 3))]
4850  "
4851  operands[2] = gen_lowpart (SImode, operands[0]);
4852  operands[3] = gen_lowpart (SImode, operands[1]);
4853  if (operands[2] == 0 || operands[3] == 0)
4854    FAIL;
4855  "
4856)
4857
4858(define_insn "*arm_movsf_soft_insn"
4859  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4860	(match_operand:SF 1 "general_operand"  "r,mE,r"))]
4861  "TARGET_ARM
4862   && !TARGET_CIRRUS
4863   && TARGET_SOFT_FLOAT
4864   && (GET_CODE (operands[0]) != MEM
4865       || register_operand (operands[1], SFmode))"
4866  "@
4867   mov%?\\t%0, %1
4868   ldr%?\\t%0, %1\\t%@ float
4869   str%?\\t%1, %0\\t%@ float"
4870  [(set_attr "length" "4,4,4")
4871   (set_attr "predicable" "yes")
4872   (set_attr "type" "*,load,store1")
4873   (set_attr "pool_range" "*,4096,*")
4874   (set_attr "neg_pool_range" "*,4084,*")]
4875)
4876
4877;;; ??? This should have alternatives for constants.
4878(define_insn "*thumb_movsf_insn"
4879  [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4880	(match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4881  "TARGET_THUMB
4882   && (   register_operand (operands[0], SFmode) 
4883       || register_operand (operands[1], SFmode))"
4884  "@
4885   add\\t%0, %1, #0
4886   ldmia\\t%1, {%0}
4887   stmia\\t%0, {%1}
4888   ldr\\t%0, %1
4889   str\\t%1, %0
4890   mov\\t%0, %1
4891   mov\\t%0, %1"
4892  [(set_attr "length" "2")
4893   (set_attr "type" "*,load,store1,load,store1,*,*")
4894   (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4895)
4896
4897(define_expand "movdf"
4898  [(set (match_operand:DF 0 "general_operand" "")
4899	(match_operand:DF 1 "general_operand" ""))]
4900  "TARGET_EITHER"
4901  "
4902  if (TARGET_ARM)
4903    {
4904      if (GET_CODE (operands[0]) == MEM)
4905        operands[1] = force_reg (DFmode, operands[1]);
4906    }
4907  else /* TARGET_THUMB */
4908    {
4909      if (!no_new_pseudos)
4910        {
4911          if (GET_CODE (operands[0]) != REG)
4912	    operands[1] = force_reg (DFmode, operands[1]);
4913        }
4914    }
4915  "
4916)
4917
4918;; Reloading a df mode value stored in integer regs to memory can require a
4919;; scratch reg.
4920(define_expand "reload_outdf"
4921  [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4922   (match_operand:DF 1 "s_register_operand" "r")
4923   (match_operand:SI 2 "s_register_operand" "=&r")]
4924  "TARGET_ARM"
4925  "
4926  {
4927    enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4928
4929    if (code == REG)
4930      operands[2] = XEXP (operands[0], 0);
4931    else if (code == POST_INC || code == PRE_DEC)
4932      {
4933	operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4934	operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4935	emit_insn (gen_movdi (operands[0], operands[1]));
4936	DONE;
4937      }
4938    else if (code == PRE_INC)
4939      {
4940	rtx reg = XEXP (XEXP (operands[0], 0), 0);
4941
4942	emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4943	operands[2] = reg;
4944      }
4945    else if (code == POST_DEC)
4946      operands[2] = XEXP (XEXP (operands[0], 0), 0);
4947    else
4948      emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4949			     XEXP (XEXP (operands[0], 0), 1)));
4950
4951    emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4952			    operands[1]));
4953
4954    if (code == POST_DEC)
4955      emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4956
4957    DONE;
4958  }"
4959)
4960
4961(define_insn "*movdf_soft_insn"
4962  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4963	(match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4964  "TARGET_ARM && TARGET_SOFT_FLOAT
4965   && !TARGET_CIRRUS
4966  "
4967  "* return output_move_double (operands);"
4968  [(set_attr "length" "8,8,8")
4969   (set_attr "type" "*,load,store2")
4970   (set_attr "pool_range" "1020")
4971   (set_attr "neg_pool_range" "1008")]
4972)
4973
4974;;; ??? This should have alternatives for constants.
4975;;; ??? This was originally identical to the movdi_insn pattern.
4976;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4977;;; thumb_reorg with a memory reference.
4978(define_insn "*thumb_movdf_insn"
4979  [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4980	(match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
4981  "TARGET_THUMB
4982   && (   register_operand (operands[0], DFmode)
4983       || register_operand (operands[1], DFmode))"
4984  "*
4985  switch (which_alternative)
4986    {
4987    default:
4988    case 0:
4989      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4990	return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4991      return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4992    case 1:
4993      return \"ldmia\\t%1, {%0, %H0}\";
4994    case 2:
4995      return \"stmia\\t%0, {%1, %H1}\";
4996    case 3:
4997      return thumb_load_double_from_address (operands);
4998    case 4:
4999      operands[2] = gen_rtx (MEM, SImode,
5000			     plus_constant (XEXP (operands[0], 0), 4));
5001      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5002      return \"\";
5003    case 5:
5004      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5005	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5006      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5007    }
5008  "
5009  [(set_attr "length" "4,2,2,6,4,4")
5010   (set_attr "type" "*,load,store2,load,store2,*")
5011   (set_attr "pool_range" "*,*,*,1020,*,*")]
5012)
5013
5014;; Vector Moves
5015(define_expand "movv2si"
5016  [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5017	(match_operand:V2SI 1 "general_operand" ""))]
5018  "TARGET_REALLY_IWMMXT"
5019{
5020})
5021
5022(define_expand "movv4hi"
5023  [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5024	(match_operand:V4HI 1 "general_operand" ""))]
5025  "TARGET_REALLY_IWMMXT"
5026{
5027})
5028
5029(define_expand "movv8qi"
5030  [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5031	(match_operand:V8QI 1 "general_operand" ""))]
5032  "TARGET_REALLY_IWMMXT"
5033{
5034})
5035
5036
5037;; load- and store-multiple insns
5038;; The arm can load/store any set of registers, provided that they are in
5039;; ascending order; but that is beyond GCC so stick with what it knows.
5040
5041(define_expand "load_multiple"
5042  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5043                          (match_operand:SI 1 "" ""))
5044                     (use (match_operand:SI 2 "" ""))])]
5045  "TARGET_ARM"
5046  "
5047  /* Support only fixed point registers.  */
5048  if (GET_CODE (operands[2]) != CONST_INT
5049      || INTVAL (operands[2]) > 14
5050      || INTVAL (operands[2]) < 2
5051      || GET_CODE (operands[1]) != MEM
5052      || GET_CODE (operands[0]) != REG
5053      || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5054      || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5055    FAIL;
5056
5057  operands[3]
5058    = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5059			     force_reg (SImode, XEXP (operands[1], 0)),
5060			     TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5061			     MEM_IN_STRUCT_P(operands[1]),
5062	                     MEM_SCALAR_P (operands[1]));
5063  "
5064)
5065
5066;; Load multiple with write-back
5067
5068(define_insn "*ldmsi_postinc4"
5069  [(match_parallel 0 "load_multiple_operation"
5070    [(set (match_operand:SI 1 "s_register_operand" "=r")
5071	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5072		   (const_int 16)))
5073     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5074	  (mem:SI (match_dup 2)))
5075     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5076	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5077     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5078	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5079     (set (match_operand:SI 6 "arm_hard_register_operand" "")
5080	  (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5081  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5082  "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5083  [(set_attr "type" "load")
5084   (set_attr "predicable" "yes")]
5085)
5086
5087(define_insn "*ldmsi_postinc3"
5088  [(match_parallel 0 "load_multiple_operation"
5089    [(set (match_operand:SI 1 "s_register_operand" "=r")
5090	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5091		   (const_int 12)))
5092     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5093	  (mem:SI (match_dup 2)))
5094     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5095	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5096     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5097	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5098  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5099  "ldm%?ia\\t%1!, {%3, %4, %5}"
5100  [(set_attr "type" "load")
5101   (set_attr "predicable" "yes")]
5102)
5103
5104(define_insn "*ldmsi_postinc2"
5105  [(match_parallel 0 "load_multiple_operation"
5106    [(set (match_operand:SI 1 "s_register_operand" "=r")
5107	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5108		   (const_int 8)))
5109     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5110	  (mem:SI (match_dup 2)))
5111     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5112	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5113  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5114  "ldm%?ia\\t%1!, {%3, %4}"
5115  [(set_attr "type" "load")
5116   (set_attr "predicable" "yes")]
5117)
5118
5119;; Ordinary load multiple
5120
5121(define_insn "*ldmsi4"
5122  [(match_parallel 0 "load_multiple_operation"
5123    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5124	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5125     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5126	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5127     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5128	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5129     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5130	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5131  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5132  "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5133  [(set_attr "type" "load")
5134   (set_attr "predicable" "yes")]
5135)
5136
5137(define_insn "*ldmsi3"
5138  [(match_parallel 0 "load_multiple_operation"
5139    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5140	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5141     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5142	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5143     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5144	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5145  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5146  "ldm%?ia\\t%1, {%2, %3, %4}"
5147  [(set_attr "type" "load")
5148   (set_attr "predicable" "yes")]
5149)
5150
5151(define_insn "*ldmsi2"
5152  [(match_parallel 0 "load_multiple_operation"
5153    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5154	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5155     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5156	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5157  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5158  "ldm%?ia\\t%1, {%2, %3}"
5159  [(set_attr "type" "load")
5160   (set_attr "predicable" "yes")]
5161)
5162
5163(define_expand "store_multiple"
5164  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5165                          (match_operand:SI 1 "" ""))
5166                     (use (match_operand:SI 2 "" ""))])]
5167  "TARGET_ARM"
5168  "
5169  /* Support only fixed point registers.  */
5170  if (GET_CODE (operands[2]) != CONST_INT
5171      || INTVAL (operands[2]) > 14
5172      || INTVAL (operands[2]) < 2
5173      || GET_CODE (operands[1]) != REG
5174      || GET_CODE (operands[0]) != MEM
5175      || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5176      || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5177    FAIL;
5178
5179  operands[3]
5180    = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5181			      force_reg (SImode, XEXP (operands[0], 0)),
5182			      TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5183			      MEM_IN_STRUCT_P(operands[0]), 
5184	                      MEM_SCALAR_P (operands[0]));
5185  "
5186)
5187
5188;; Store multiple with write-back
5189
5190(define_insn "*stmsi_postinc4"
5191  [(match_parallel 0 "store_multiple_operation"
5192    [(set (match_operand:SI 1 "s_register_operand" "=r")
5193	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5194		   (const_int 16)))
5195     (set (mem:SI (match_dup 2))
5196	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5197     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5198	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5199     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5200	  (match_operand:SI 5 "arm_hard_register_operand" ""))
5201     (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5202	  (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5203  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5204  "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5205  [(set_attr "predicable" "yes")
5206   (set_attr "type" "store4")]
5207)
5208
5209(define_insn "*stmsi_postinc3"
5210  [(match_parallel 0 "store_multiple_operation"
5211    [(set (match_operand:SI 1 "s_register_operand" "=r")
5212	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5213		   (const_int 12)))
5214     (set (mem:SI (match_dup 2))
5215	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5216     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5217	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5218     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5219	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5220  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5221  "stm%?ia\\t%1!, {%3, %4, %5}"
5222  [(set_attr "predicable" "yes")
5223   (set_attr "type" "store3")]
5224)
5225
5226(define_insn "*stmsi_postinc2"
5227  [(match_parallel 0 "store_multiple_operation"
5228    [(set (match_operand:SI 1 "s_register_operand" "=r")
5229	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5230		   (const_int 8)))
5231     (set (mem:SI (match_dup 2))
5232	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5233     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5234	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5235  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5236  "stm%?ia\\t%1!, {%3, %4}"
5237  [(set_attr "predicable" "yes")
5238   (set_attr "type" "store2")]
5239)
5240
5241;; Ordinary store multiple
5242
5243(define_insn "*stmsi4"
5244  [(match_parallel 0 "store_multiple_operation"
5245    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5246	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5247     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5248	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5249     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5250	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5251     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5252	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5253  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5254  "stm%?ia\\t%1, {%2, %3, %4, %5}"
5255  [(set_attr "predicable" "yes")
5256   (set_attr "type" "store4")]
5257)
5258
5259(define_insn "*stmsi3"
5260  [(match_parallel 0 "store_multiple_operation"
5261    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5262	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5263     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5264	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5265     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5266	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5267  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5268  "stm%?ia\\t%1, {%2, %3, %4}"
5269  [(set_attr "predicable" "yes")
5270   (set_attr "type" "store3")]
5271)
5272
5273(define_insn "*stmsi2"
5274  [(match_parallel 0 "store_multiple_operation"
5275    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5276	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5277     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5278	  (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5279  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5280  "stm%?ia\\t%1, {%2, %3}"
5281  [(set_attr "predicable" "yes")
5282   (set_attr "type" "store2")]
5283)
5284
5285;; Move a block of memory if it is word aligned and MORE than 2 words long.
5286;; We could let this apply for blocks of less than this, but it clobbers so
5287;; many registers that there is then probably a better way.
5288
5289(define_expand "movstrqi"
5290  [(match_operand:BLK 0 "general_operand" "")
5291   (match_operand:BLK 1 "general_operand" "")
5292   (match_operand:SI 2 "const_int_operand" "")
5293   (match_operand:SI 3 "const_int_operand" "")]
5294  "TARGET_EITHER"
5295  "
5296  if (TARGET_ARM)
5297    {
5298      if (arm_gen_movstrqi (operands))
5299        DONE;
5300      FAIL;
5301    }
5302  else /* TARGET_THUMB */
5303    {
5304      if (   INTVAL (operands[3]) != 4
5305          || INTVAL (operands[2]) > 48)
5306        FAIL;
5307
5308      thumb_expand_movstrqi (operands);
5309      DONE;
5310    }
5311  "
5312)
5313
5314;; Thumb block-move insns
5315
5316(define_insn "movmem12b"
5317  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5318	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5319   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5320	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5321   (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5322	(mem:SI (plus:SI (match_dup 3) (const_int 8))))
5323   (set (match_operand:SI 0 "register_operand" "=l")
5324	(plus:SI (match_dup 2) (const_int 12)))
5325   (set (match_operand:SI 1 "register_operand" "=l")
5326	(plus:SI (match_dup 3) (const_int 12)))
5327   (clobber (match_scratch:SI 4 "=&l"))
5328   (clobber (match_scratch:SI 5 "=&l"))
5329   (clobber (match_scratch:SI 6 "=&l"))]
5330  "TARGET_THUMB"
5331  "* return thumb_output_move_mem_multiple (3, operands);"
5332  [(set_attr "length" "4")
5333   ; This isn't entirely accurate...  It loads as well, but in terms of
5334   ; scheduling the following insn it is better to consider it as a store
5335   (set_attr "type" "store3")]
5336)
5337
5338(define_insn "movmem8b"
5339  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5340	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5341   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5342	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5343   (set (match_operand:SI 0 "register_operand" "=l")
5344	(plus:SI (match_dup 2) (const_int 8)))
5345   (set (match_operand:SI 1 "register_operand" "=l")
5346	(plus:SI (match_dup 3) (const_int 8)))
5347   (clobber (match_scratch:SI 4 "=&l"))
5348   (clobber (match_scratch:SI 5 "=&l"))]
5349  "TARGET_THUMB"
5350  "* return thumb_output_move_mem_multiple (2, operands);"
5351  [(set_attr "length" "4")
5352   ; This isn't entirely accurate...  It loads as well, but in terms of
5353   ; scheduling the following insn it is better to consider it as a store
5354   (set_attr "type" "store2")]
5355)
5356
5357
5358
5359;; Compare & branch insns
5360;; The range calculations are based as follows:
5361;; For forward branches, the address calculation returns the address of
5362;; the next instruction.  This is 2 beyond the branch instruction.
5363;; For backward branches, the address calculation returns the address of
5364;; the first instruction in this pattern (cmp).  This is 2 before the branch
5365;; instruction for the shortest sequence, and 4 before the branch instruction
5366;; if we have to jump around an unconditional branch.
5367;; To the basic branch range the PC offset must be added (this is +4).
5368;; So for forward branches we have 
5369;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5370;; And for backward branches we have 
5371;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5372;;
5373;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5374;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5375
5376(define_expand "cbranchsi4"
5377  [(set (pc) (if_then_else
5378	      (match_operator 0 "arm_comparison_operator"
5379	       [(match_operand:SI 1 "s_register_operand" "")
5380	        (match_operand:SI 2 "nonmemory_operand" "")])
5381	      (label_ref (match_operand 3 "" ""))
5382	      (pc)))]
5383  "TARGET_THUMB"
5384  "
5385  if (thumb_cmpneg_operand (operands[2], SImode))
5386    {
5387      emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5388					      operands[3], operands[0]));
5389      DONE;
5390    }
5391  if (!thumb_cmp_operand (operands[2], SImode))
5392    operands[2] = force_reg (SImode, operands[2]);
5393  ")
5394
5395(define_insn "*cbranchsi4_insn"
5396  [(set (pc) (if_then_else
5397	      (match_operator 0 "arm_comparison_operator"
5398	       [(match_operand:SI 1 "s_register_operand" "l,*h")
5399	        (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5400	      (label_ref (match_operand 3 "" ""))
5401	      (pc)))]
5402  "TARGET_THUMB"
5403  "*
5404  output_asm_insn (\"cmp\\t%1, %2\", operands);
5405
5406  switch (get_attr_length (insn))
5407    {
5408    case 4:  return \"b%d0\\t%l3\";
5409    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5410    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5411    }
5412  "
5413  [(set (attr "far_jump")
5414        (if_then_else
5415	    (eq_attr "length" "8")
5416	    (const_string "yes")
5417            (const_string "no")))
5418   (set (attr "length") 
5419        (if_then_else
5420	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5421	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5422	    (const_int 4)
5423	    (if_then_else
5424	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5425		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5426		(const_int 6)
5427		(const_int 8))))]
5428)
5429
5430(define_insn "cbranchsi4_scratch"
5431  [(set (pc) (if_then_else
5432	      (match_operator 4 "arm_comparison_operator"
5433	       [(match_operand:SI 1 "s_register_operand" "l,0")
5434	        (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5435	      (label_ref (match_operand 3 "" ""))
5436	      (pc)))
5437   (clobber (match_scratch:SI 0 "=l,l"))]
5438  "TARGET_THUMB"
5439  "*
5440  output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5441
5442  switch (get_attr_length (insn))
5443    {
5444    case 4:  return \"b%d4\\t%l3\";
5445    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5446    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5447    }
5448  "
5449  [(set (attr "far_jump")
5450        (if_then_else
5451	    (eq_attr "length" "8")
5452	    (const_string "yes")
5453            (const_string "no")))
5454   (set (attr "length") 
5455        (if_then_else
5456	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5457	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5458	    (const_int 4)
5459	    (if_then_else
5460	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5461		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5462		(const_int 6)
5463		(const_int 8))))]
5464)
5465(define_insn "*movsi_cbranchsi4"
5466  [(set (pc)
5467	(if_then_else
5468	 (match_operator 3 "arm_comparison_operator"
5469	  [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5470	   (const_int 0)])
5471	 (label_ref (match_operand 2 "" ""))
5472	 (pc)))
5473   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5474	(match_dup 1))]
5475  "TARGET_THUMB"
5476  "*{
5477  if (which_alternative == 0)
5478    output_asm_insn (\"cmp\t%0, #0\", operands);
5479  else if (which_alternative == 1)
5480    output_asm_insn (\"sub\t%0, %1, #0\", operands);
5481  else
5482    {
5483      output_asm_insn (\"cmp\t%1, #0\", operands);
5484      if (which_alternative == 2)
5485	output_asm_insn (\"mov\t%0, %1\", operands);
5486      else
5487	output_asm_insn (\"str\t%1, %0\", operands);
5488    }
5489  switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5490    {
5491    case 4:  return \"b%d3\\t%l2\";
5492    case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5493    default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5494    }
5495  }"
5496  [(set (attr "far_jump")
5497        (if_then_else
5498	    (ior (and (gt (symbol_ref ("which_alternative"))
5499	                  (const_int 1))
5500		      (eq_attr "length" "8"))
5501		 (eq_attr "length" "10"))
5502	    (const_string "yes")
5503            (const_string "no")))
5504   (set (attr "length")
5505     (if_then_else
5506       (le (symbol_ref ("which_alternative"))
5507		       (const_int 1))
5508       (if_then_else
5509	 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5510	      (le (minus (match_dup 2) (pc)) (const_int 256)))
5511	 (const_int 4)
5512	 (if_then_else
5513	   (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5514		(le (minus (match_dup 2) (pc)) (const_int 2048)))
5515	   (const_int 6)
5516	   (const_int 8)))
5517       (if_then_else
5518	 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5519	      (le (minus (match_dup 2) (pc)) (const_int 256)))
5520	 (const_int 6)
5521	 (if_then_else
5522	   (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5523		(le (minus (match_dup 2) (pc)) (const_int 2048)))
5524	   (const_int 8)
5525	   (const_int 10)))))]
5526)
5527
5528(define_insn "*negated_cbranchsi4"
5529  [(set (pc)
5530	(if_then_else
5531	 (match_operator 0 "arm_comparison_operator"
5532	  [(match_operand:SI 1 "s_register_operand" "l")
5533	   (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5534	 (label_ref (match_operand 3 "" ""))
5535	 (pc)))]
5536  "TARGET_THUMB"
5537  "*
5538  output_asm_insn (\"cmn\\t%1, %2\", operands);
5539  switch (get_attr_length (insn))
5540    {
5541    case 4:  return \"b%d0\\t%l3\";
5542    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5543    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5544    }
5545  "
5546  [(set (attr "far_jump")
5547        (if_then_else
5548	    (eq_attr "length" "8")
5549	    (const_string "yes")
5550            (const_string "no")))
5551   (set (attr "length") 
5552        (if_then_else
5553	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5554	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5555	    (const_int 4)
5556	    (if_then_else
5557	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5558		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5559		(const_int 6)
5560		(const_int 8))))]
5561)
5562
5563(define_insn "*tbit_cbranch"
5564  [(set (pc)
5565	(if_then_else
5566	 (match_operator 0 "equality_operator"
5567	  [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5568			    (const_int 1)
5569			    (match_operand:SI 2 "const_int_operand" "i"))
5570	   (const_int 0)])
5571	 (label_ref (match_operand 3 "" ""))
5572	 (pc)))
5573   (clobber (match_scratch:SI 4 "=l"))]
5574  "TARGET_THUMB"
5575  "*
5576  {
5577  rtx op[3];
5578  op[0] = operands[4];
5579  op[1] = operands[1];
5580  op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5581
5582  output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5583  switch (get_attr_length (insn))
5584    {
5585    case 4:  return \"b%d0\\t%l3\";
5586    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5587    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5588    }
5589  }"
5590  [(set (attr "far_jump")
5591        (if_then_else
5592	    (eq_attr "length" "8")
5593	    (const_string "yes")
5594            (const_string "no")))
5595   (set (attr "length") 
5596        (if_then_else
5597	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5598	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5599	    (const_int 4)
5600	    (if_then_else
5601	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5602		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5603		(const_int 6)
5604		(const_int 8))))]
5605)
5606  
5607(define_insn "*tstsi3_cbranch"
5608  [(set (pc)
5609	(if_then_else
5610	 (match_operator 3 "equality_operator"
5611	  [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5612		   (match_operand:SI 1 "s_register_operand" "l"))
5613	   (const_int 0)])
5614	 (label_ref (match_operand 2 "" ""))
5615	 (pc)))]
5616  "TARGET_THUMB"
5617  "*
5618  {
5619  output_asm_insn (\"tst\\t%0, %1\", operands);
5620  switch (get_attr_length (insn))
5621    {
5622    case 4:  return \"b%d3\\t%l2\";
5623    case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5624    default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5625    }
5626  }"
5627  [(set (attr "far_jump")
5628        (if_then_else
5629	    (eq_attr "length" "8")
5630	    (const_string "yes")
5631            (const_string "no")))
5632   (set (attr "length") 
5633        (if_then_else
5634	    (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5635	         (le (minus (match_dup 2) (pc)) (const_int 256)))
5636	    (const_int 4)
5637	    (if_then_else
5638	        (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5639		     (le (minus (match_dup 2) (pc)) (const_int 2048)))
5640		(const_int 6)
5641		(const_int 8))))]
5642)
5643  
5644(define_insn "*andsi3_cbranch"
5645  [(set (pc)
5646	(if_then_else
5647	 (match_operator 5 "equality_operator"
5648	  [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5649		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5650	   (const_int 0)])
5651	 (label_ref (match_operand 4 "" ""))
5652	 (pc)))
5653   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5654	(and:SI (match_dup 2) (match_dup 3)))
5655   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5656  "TARGET_THUMB"
5657  "*
5658  {
5659  if (which_alternative == 0)
5660    output_asm_insn (\"and\\t%0, %3\", operands);
5661  else if (which_alternative == 1)
5662    {
5663      output_asm_insn (\"and\\t%1, %3\", operands);
5664      output_asm_insn (\"mov\\t%0, %1\", operands);
5665    }
5666  else
5667    {
5668      output_asm_insn (\"and\\t%1, %3\", operands);
5669      output_asm_insn (\"str\\t%1, %0\", operands);
5670    }
5671
5672  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5673    {
5674    case 4:  return \"b%d5\\t%l4\";
5675    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5676    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5677    }
5678  }"
5679  [(set (attr "far_jump")
5680        (if_then_else
5681	    (ior (and (eq (symbol_ref ("which_alternative"))
5682	                  (const_int 0))
5683		      (eq_attr "length" "8"))
5684		 (eq_attr "length" "10"))
5685	    (const_string "yes")
5686            (const_string "no")))
5687   (set (attr "length")
5688     (if_then_else
5689       (eq (symbol_ref ("which_alternative"))
5690		       (const_int 0))
5691       (if_then_else
5692	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5693	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5694	 (const_int 4)
5695	 (if_then_else
5696	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5697		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5698	   (const_int 6)
5699	   (const_int 8)))
5700       (if_then_else
5701	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5702	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5703	 (const_int 6)
5704	 (if_then_else
5705	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5706		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5707	   (const_int 8)
5708	   (const_int 10)))))]
5709)
5710
5711(define_insn "*orrsi3_cbranch_scratch"
5712  [(set (pc)
5713	(if_then_else
5714	 (match_operator 4 "equality_operator"
5715	  [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5716		   (match_operand:SI 2 "s_register_operand" "l"))
5717	   (const_int 0)])
5718	 (label_ref (match_operand 3 "" ""))
5719	 (pc)))
5720   (clobber (match_scratch:SI 0 "=l"))]
5721  "TARGET_THUMB"
5722  "*
5723  {
5724  output_asm_insn (\"orr\\t%0, %2\", operands);
5725  switch (get_attr_length (insn))
5726    {
5727    case 4:  return \"b%d4\\t%l3\";
5728    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5729    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5730    }
5731  }"
5732  [(set (attr "far_jump")
5733        (if_then_else
5734	    (eq_attr "length" "8")
5735	    (const_string "yes")
5736            (const_string "no")))
5737   (set (attr "length") 
5738        (if_then_else
5739	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5740	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5741	    (const_int 4)
5742	    (if_then_else
5743	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5744		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5745		(const_int 6)
5746		(const_int 8))))]
5747)
5748  
5749(define_insn "*orrsi3_cbranch"
5750  [(set (pc)
5751	(if_then_else
5752	 (match_operator 5 "equality_operator"
5753	  [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5754		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5755	   (const_int 0)])
5756	 (label_ref (match_operand 4 "" ""))
5757	 (pc)))
5758   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5759	(ior:SI (match_dup 2) (match_dup 3)))
5760   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5761  "TARGET_THUMB"
5762  "*
5763  {
5764  if (which_alternative == 0)
5765    output_asm_insn (\"orr\\t%0, %3\", operands);
5766  else if (which_alternative == 1)
5767    {
5768      output_asm_insn (\"orr\\t%1, %3\", operands);
5769      output_asm_insn (\"mov\\t%0, %1\", operands);
5770    }
5771  else
5772    {
5773      output_asm_insn (\"orr\\t%1, %3\", operands);
5774      output_asm_insn (\"str\\t%1, %0\", operands);
5775    }
5776
5777  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5778    {
5779    case 4:  return \"b%d5\\t%l4\";
5780    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5781    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5782    }
5783  }"
5784  [(set (attr "far_jump")
5785        (if_then_else
5786	    (ior (and (eq (symbol_ref ("which_alternative"))
5787	                  (const_int 0))
5788		      (eq_attr "length" "8"))
5789		 (eq_attr "length" "10"))
5790	    (const_string "yes")
5791            (const_string "no")))
5792   (set (attr "length")
5793     (if_then_else
5794       (eq (symbol_ref ("which_alternative"))
5795		       (const_int 0))
5796       (if_then_else
5797	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5798	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5799	 (const_int 4)
5800	 (if_then_else
5801	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5802		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5803	   (const_int 6)
5804	   (const_int 8)))
5805       (if_then_else
5806	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5807	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5808	 (const_int 6)
5809	 (if_then_else
5810	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5811		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5812	   (const_int 8)
5813	   (const_int 10)))))]
5814)
5815
5816(define_insn "*xorsi3_cbranch_scratch"
5817  [(set (pc)
5818	(if_then_else
5819	 (match_operator 4 "equality_operator"
5820	  [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
5821		   (match_operand:SI 2 "s_register_operand" "l"))
5822	   (const_int 0)])
5823	 (label_ref (match_operand 3 "" ""))
5824	 (pc)))
5825   (clobber (match_scratch:SI 0 "=l"))]
5826  "TARGET_THUMB"
5827  "*
5828  {
5829  output_asm_insn (\"eor\\t%0, %2\", operands);
5830  switch (get_attr_length (insn))
5831    {
5832    case 4:  return \"b%d4\\t%l3\";
5833    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5834    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5835    }
5836  }"
5837  [(set (attr "far_jump")
5838        (if_then_else
5839	    (eq_attr "length" "8")
5840	    (const_string "yes")
5841            (const_string "no")))
5842   (set (attr "length") 
5843        (if_then_else
5844	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5845	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5846	    (const_int 4)
5847	    (if_then_else
5848	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5849		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5850		(const_int 6)
5851		(const_int 8))))]
5852)
5853  
5854(define_insn "*xorsi3_cbranch"
5855  [(set (pc)
5856	(if_then_else
5857	 (match_operator 5 "equality_operator"
5858	  [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5859		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5860	   (const_int 0)])
5861	 (label_ref (match_operand 4 "" ""))
5862	 (pc)))
5863   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5864	(xor:SI (match_dup 2) (match_dup 3)))
5865   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5866  "TARGET_THUMB"
5867  "*
5868  {
5869  if (which_alternative == 0)
5870    output_asm_insn (\"eor\\t%0, %3\", operands);
5871  else if (which_alternative == 1)
5872    {
5873      output_asm_insn (\"eor\\t%1, %3\", operands);
5874      output_asm_insn (\"mov\\t%0, %1\", operands);
5875    }
5876  else
5877    {
5878      output_asm_insn (\"eor\\t%1, %3\", operands);
5879      output_asm_insn (\"str\\t%1, %0\", operands);
5880    }
5881
5882  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5883    {
5884    case 4:  return \"b%d5\\t%l4\";
5885    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5886    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5887    }
5888  }"
5889  [(set (attr "far_jump")
5890        (if_then_else
5891	    (ior (and (eq (symbol_ref ("which_alternative"))
5892	                  (const_int 0))
5893		      (eq_attr "length" "8"))
5894		 (eq_attr "length" "10"))
5895	    (const_string "yes")
5896            (const_string "no")))
5897   (set (attr "length")
5898     (if_then_else
5899       (eq (symbol_ref ("which_alternative"))
5900		       (const_int 0))
5901       (if_then_else
5902	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5903	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5904	 (const_int 4)
5905	 (if_then_else
5906	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5907		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5908	   (const_int 6)
5909	   (const_int 8)))
5910       (if_then_else
5911	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5912	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5913	 (const_int 6)
5914	 (if_then_else
5915	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5916		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5917	   (const_int 8)
5918	   (const_int 10)))))]
5919)
5920
5921(define_insn "*bicsi3_cbranch_scratch"
5922  [(set (pc)
5923	(if_then_else
5924	 (match_operator 4 "equality_operator"
5925	  [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
5926		   (match_operand:SI 1 "s_register_operand" "0"))
5927	   (const_int 0)])
5928	 (label_ref (match_operand 3 "" ""))
5929	 (pc)))
5930   (clobber (match_scratch:SI 0 "=l"))]
5931  "TARGET_THUMB"
5932  "*
5933  {
5934  output_asm_insn (\"bic\\t%0, %2\", operands);
5935  switch (get_attr_length (insn))
5936    {
5937    case 4:  return \"b%d4\\t%l3\";
5938    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5939    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5940    }
5941  }"
5942  [(set (attr "far_jump")
5943        (if_then_else
5944	    (eq_attr "length" "8")
5945	    (const_string "yes")
5946            (const_string "no")))
5947   (set (attr "length") 
5948        (if_then_else
5949	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5950	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5951	    (const_int 4)
5952	    (if_then_else
5953	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5954		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5955		(const_int 6)
5956		(const_int 8))))]
5957)
5958  
5959(define_insn "*bicsi3_cbranch"
5960  [(set (pc)
5961	(if_then_else
5962	 (match_operator 5 "equality_operator"
5963	  [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
5964		   (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
5965	   (const_int 0)])
5966	 (label_ref (match_operand 4 "" ""))
5967	 (pc)))
5968   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
5969	(and:SI (not:SI (match_dup 3)) (match_dup 2)))
5970   (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
5971  "TARGET_THUMB"
5972  "*
5973  {
5974  if (which_alternative == 0)
5975    output_asm_insn (\"bic\\t%0, %3\", operands);
5976  else if (which_alternative <= 2)
5977    {
5978      output_asm_insn (\"bic\\t%1, %3\", operands);
5979      /* It's ok if OP0 is a lo-reg, even though the mov will set the
5980	 conditions again, since we're only testing for equality.  */
5981      output_asm_insn (\"mov\\t%0, %1\", operands);
5982    }
5983  else
5984    {
5985      output_asm_insn (\"bic\\t%1, %3\", operands);
5986      output_asm_insn (\"str\\t%1, %0\", operands);
5987    }
5988
5989  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5990    {
5991    case 4:  return \"b%d5\\t%l4\";
5992    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5993    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5994    }
5995  }"
5996  [(set (attr "far_jump")
5997        (if_then_else
5998	    (ior (and (eq (symbol_ref ("which_alternative"))
5999	                  (const_int 0))
6000		      (eq_attr "length" "8"))
6001		 (eq_attr "length" "10"))
6002	    (const_string "yes")
6003            (const_string "no")))
6004   (set (attr "length")
6005     (if_then_else
6006       (eq (symbol_ref ("which_alternative"))
6007		       (const_int 0))
6008       (if_then_else
6009	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6010	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6011	 (const_int 4)
6012	 (if_then_else
6013	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6014		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6015	   (const_int 6)
6016	   (const_int 8)))
6017       (if_then_else
6018	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6019	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6020	 (const_int 6)
6021	 (if_then_else
6022	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6023		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6024	   (const_int 8)
6025	   (const_int 10)))))]
6026)
6027
6028(define_insn "*cbranchne_decr1"
6029  [(set (pc)
6030	(if_then_else (match_operator 3 "equality_operator"
6031		       [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6032		        (const_int 0)])
6033		      (label_ref (match_operand 4 "" ""))
6034		      (pc)))
6035   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6036	(plus:SI (match_dup 2) (const_int -1)))
6037   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6038  "TARGET_THUMB"
6039  "*
6040   {
6041     rtx cond[2];
6042     cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6043				? GEU : LTU),
6044			       VOIDmode, operands[2], const1_rtx);
6045     cond[1] = operands[4];
6046
6047     if (which_alternative == 0)
6048       output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6049     else if (which_alternative == 1)
6050       {
6051	 /* We must provide an alternative for a hi reg because reload 
6052	    cannot handle output reloads on a jump instruction, but we
6053	    can't subtract into that.  Fortunately a mov from lo to hi
6054	    does not clobber the condition codes.  */
6055	 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6056	 output_asm_insn (\"mov\\t%0, %1\", operands);
6057       }
6058     else
6059       {
6060	 /* Similarly, but the target is memory.  */
6061	 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6062	 output_asm_insn (\"str\\t%1, %0\", operands);
6063       }
6064
6065     switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6066       {
6067	 case 4:
6068	   output_asm_insn (\"b%d0\\t%l1\", cond);
6069	   return \"\";
6070	 case 6:
6071	   output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6072	   return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6073	 default:
6074	   output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6075	   return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6076       }
6077   }
6078  "
6079  [(set (attr "far_jump")
6080        (if_then_else
6081	    (ior (and (eq (symbol_ref ("which_alternative"))
6082	                  (const_int 0))
6083		      (eq_attr "length" "8"))
6084		 (eq_attr "length" "10"))
6085	    (const_string "yes")
6086            (const_string "no")))
6087   (set_attr_alternative "length"
6088      [
6089       ;; Alternative 0
6090       (if_then_else
6091	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6092	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6093	 (const_int 4)
6094	 (if_then_else
6095	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6096		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6097	   (const_int 6)
6098	   (const_int 8)))
6099       ;; Alternative 1
6100       (if_then_else
6101	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6102	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6103	 (const_int 6)
6104	 (if_then_else
6105	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6106		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6107	   (const_int 8)
6108	   (const_int 10)))
6109       ;; Alternative 2
6110       (if_then_else
6111	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6112	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6113	 (const_int 6)
6114	 (if_then_else
6115	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6116		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6117	   (const_int 8)
6118	   (const_int 10)))
6119       ;; Alternative 3
6120       (if_then_else
6121	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6122	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6123	 (const_int 6)
6124	 (if_then_else
6125	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6126		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6127	   (const_int 8)
6128	   (const_int 10)))])]
6129)
6130
6131(define_insn "*addsi3_cbranch"
6132  [(set (pc)
6133	(if_then_else
6134	 (match_operator 4 "comparison_operator"
6135	  [(plus:SI
6136	    (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6137	    (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6138	   (const_int 0)])
6139	 (label_ref (match_operand 5 "" ""))
6140	 (pc)))
6141   (set
6142    (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6143    (plus:SI (match_dup 2) (match_dup 3)))
6144   (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6145  "TARGET_THUMB
6146   && (GET_CODE (operands[4]) == EQ
6147       || GET_CODE (operands[4]) == NE
6148       || GET_CODE (operands[4]) == GE
6149       || GET_CODE (operands[4]) == LT)"
6150  "*
6151   {
6152     rtx cond[3];
6153
6154     
6155     cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6156     cond[1] = operands[2];
6157     cond[2] = operands[3];
6158
6159     if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6160       output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6161     else
6162       output_asm_insn (\"add\\t%0, %1, %2\", cond);
6163
6164     if (which_alternative >= 3
6165	 && which_alternative < 4)
6166       output_asm_insn (\"mov\\t%0, %1\", operands);
6167     else if (which_alternative >= 4)
6168       output_asm_insn (\"str\\t%1, %0\", operands);
6169
6170     switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6171       {
6172	 case 4:
6173	   return \"b%d4\\t%l5\";
6174	 case 6:
6175	   return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6176	 default:
6177	   return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6178       }
6179   }
6180  "
6181  [(set (attr "far_jump")
6182        (if_then_else
6183	    (ior (and (lt (symbol_ref ("which_alternative"))
6184	                  (const_int 3))
6185		      (eq_attr "length" "8"))
6186		 (eq_attr "length" "10"))
6187	    (const_string "yes")
6188            (const_string "no")))
6189   (set (attr "length")
6190     (if_then_else
6191       (lt (symbol_ref ("which_alternative"))
6192		       (const_int 3))
6193       (if_then_else
6194	 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6195	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6196	 (const_int 4)
6197	 (if_then_else
6198	   (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6199		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6200	   (const_int 6)
6201	   (const_int 8)))
6202       (if_then_else
6203	 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6204	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6205	 (const_int 6)
6206	 (if_then_else
6207	   (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6208		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6209	   (const_int 8)
6210	   (const_int 10)))))]
6211)
6212
6213(define_insn "*addsi3_cbranch_scratch"
6214  [(set (pc)
6215	(if_then_else
6216	 (match_operator 3 "comparison_operator"
6217	  [(plus:SI
6218	    (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6219	    (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6220	   (const_int 0)])
6221	 (label_ref (match_operand 4 "" ""))
6222	 (pc)))
6223   (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6224  "TARGET_THUMB
6225   && (GET_CODE (operands[3]) == EQ
6226       || GET_CODE (operands[3]) == NE
6227       || GET_CODE (operands[3]) == GE
6228       || GET_CODE (operands[3]) == LT)"
6229  "*
6230   {
6231     switch (which_alternative)
6232       {
6233       case 0:
6234	 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6235	 break;
6236       case 1:
6237	 output_asm_insn (\"cmn\t%1, %2\", operands);
6238	 break;
6239       case 2:
6240	 output_asm_insn (\"add\t%0, %1, %2\", operands);
6241	 break;
6242       case 3:
6243	 output_asm_insn (\"add\t%0, %0, %2\", operands);
6244	 break;
6245       }
6246
6247     switch (get_attr_length (insn))
6248       {
6249	 case 4:
6250	   return \"b%d3\\t%l4\";
6251	 case 6:
6252	   return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6253	 default:
6254	   return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6255       }
6256   }
6257  "
6258  [(set (attr "far_jump")
6259        (if_then_else
6260	    (eq_attr "length" "8")
6261	    (const_string "yes")
6262            (const_string "no")))
6263   (set (attr "length")
6264       (if_then_else
6265	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6266	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6267	 (const_int 4)
6268	 (if_then_else
6269	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6270		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6271	   (const_int 6)
6272	   (const_int 8))))]
6273)
6274
6275(define_insn "*subsi3_cbranch"
6276  [(set (pc)
6277	(if_then_else
6278	 (match_operator 4 "comparison_operator"
6279	  [(minus:SI
6280	    (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6281	    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6282	   (const_int 0)])
6283	 (label_ref (match_operand 5 "" ""))
6284	 (pc)))
6285   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6286	(minus:SI (match_dup 2) (match_dup 3)))
6287   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6288  "TARGET_THUMB
6289   && (GET_CODE (operands[4]) == EQ
6290       || GET_CODE (operands[4]) == NE
6291       || GET_CODE (operands[4]) == GE
6292       || GET_CODE (operands[4]) == LT)"
6293  "*
6294   {
6295     if (which_alternative == 0)
6296       output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6297     else if (which_alternative == 1)
6298       {
6299	 /* We must provide an alternative for a hi reg because reload 
6300	    cannot handle output reloads on a jump instruction, but we
6301	    can't subtract into that.  Fortunately a mov from lo to hi
6302	    does not clobber the condition codes.  */
6303	 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6304	 output_asm_insn (\"mov\\t%0, %1\", operands);
6305       }
6306     else
6307       {
6308	 /* Similarly, but the target is memory.  */
6309	 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6310	 output_asm_insn (\"str\\t%1, %0\", operands);
6311       }
6312
6313     switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6314       {
6315	 case 4:
6316	   return \"b%d4\\t%l5\";
6317	 case 6:
6318	   return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6319	 default:
6320	   return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6321       }
6322   }
6323  "
6324  [(set (attr "far_jump")
6325        (if_then_else
6326	    (ior (and (eq (symbol_ref ("which_alternative"))
6327	                  (const_int 0))
6328		      (eq_attr "length" "8"))
6329		 (eq_attr "length" "10"))
6330	    (const_string "yes")
6331            (const_string "no")))
6332   (set (attr "length")
6333     (if_then_else
6334       (eq (symbol_ref ("which_alternative"))
6335		       (const_int 0))
6336       (if_then_else
6337	 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6338	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6339	 (const_int 4)
6340	 (if_then_else
6341	   (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6342		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6343	   (const_int 6)
6344	   (const_int 8)))
6345       (if_then_else
6346	 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6347	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6348	 (const_int 6)
6349	 (if_then_else
6350	   (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6351		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6352	   (const_int 8)
6353	   (const_int 10)))))]
6354)
6355
6356(define_insn "*subsi3_cbranch_scratch"
6357  [(set (pc)
6358	(if_then_else
6359	 (match_operator 0 "arm_comparison_operator"
6360	  [(minus:SI (match_operand:SI 1 "register_operand" "l")
6361		     (match_operand:SI 2 "nonmemory_operand" "l"))
6362	   (const_int 0)])
6363	 (label_ref (match_operand 3 "" ""))
6364	 (pc)))]
6365  "TARGET_THUMB
6366   && (GET_CODE (operands[0]) == EQ
6367       || GET_CODE (operands[0]) == NE
6368       || GET_CODE (operands[0]) == GE
6369       || GET_CODE (operands[0]) == LT)"
6370  "*
6371  output_asm_insn (\"cmp\\t%1, %2\", operands);
6372  switch (get_attr_length (insn))
6373    {
6374    case 4:  return \"b%d0\\t%l3\";
6375    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6376    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6377    }
6378  "
6379  [(set (attr "far_jump")
6380        (if_then_else
6381	    (eq_attr "length" "8")
6382	    (const_string "yes")
6383            (const_string "no")))
6384   (set (attr "length") 
6385        (if_then_else
6386	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6387	         (le (minus (match_dup 3) (pc)) (const_int 256)))
6388	    (const_int 4)
6389	    (if_then_else
6390	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6391		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
6392		(const_int 6)
6393		(const_int 8))))]
6394)
6395
6396;; Comparison and test insns
6397
6398(define_expand "cmpsi"
6399  [(match_operand:SI 0 "s_register_operand" "")
6400   (match_operand:SI 1 "arm_add_operand" "")]
6401  "TARGET_ARM"
6402  "{
6403    arm_compare_op0 = operands[0];
6404    arm_compare_op1 = operands[1];
6405    DONE;
6406  }"
6407)
6408
6409(define_expand "cmpsf"
6410  [(match_operand:SF 0 "s_register_operand" "")
6411   (match_operand:SF 1 "fpa_rhs_operand" "")]
6412  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6413  "
6414  if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
6415    operands[1] = force_reg (SFmode, operands[1]);
6416
6417  arm_compare_op0 = operands[0];
6418  arm_compare_op1 = operands[1];
6419  DONE;
6420  "
6421)
6422
6423(define_expand "cmpdf"
6424  [(match_operand:DF 0 "s_register_operand" "")
6425   (match_operand:DF 1 "fpa_rhs_operand" "")]
6426  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6427  "
6428  if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
6429    operands[1] = force_reg (DFmode, operands[1]);
6430
6431  arm_compare_op0 = operands[0];
6432  arm_compare_op1 = operands[1];
6433  DONE;
6434  "
6435)
6436
6437(define_insn "*arm_cmpsi_insn"
6438  [(set (reg:CC CC_REGNUM)
6439	(compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6440		    (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6441  "TARGET_ARM"
6442  "@
6443   cmp%?\\t%0, %1
6444   cmn%?\\t%0, #%n1"
6445  [(set_attr "conds" "set")]
6446)
6447
6448(define_insn "*cmpsi_shiftsi"
6449  [(set (reg:CC CC_REGNUM)
6450	(compare:CC (match_operand:SI   0 "s_register_operand" "r")
6451		    (match_operator:SI  3 "shift_operator"
6452		     [(match_operand:SI 1 "s_register_operand" "r")
6453		      (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6454  "TARGET_ARM"
6455  "cmp%?\\t%0, %1%S3"
6456  [(set_attr "conds" "set")
6457   (set_attr "shift" "1")
6458   ]
6459)
6460
6461(define_insn "*cmpsi_shiftsi_swp"
6462  [(set (reg:CC_SWP CC_REGNUM)
6463	(compare:CC_SWP (match_operator:SI 3 "shift_operator"
6464			 [(match_operand:SI 1 "s_register_operand" "r")
6465			  (match_operand:SI 2 "reg_or_int_operand" "rM")])
6466			(match_operand:SI 0 "s_register_operand" "r")))]
6467  "TARGET_ARM"
6468  "cmp%?\\t%0, %1%S3"
6469  [(set_attr "conds" "set")
6470   (set_attr "shift" "1")
6471   ]
6472)
6473
6474(define_insn "*cmpsi_neg_shiftsi"
6475  [(set (reg:CC CC_REGNUM)
6476	(compare:CC (match_operand:SI 0 "s_register_operand" "r")
6477		    (neg:SI (match_operator:SI 3 "shift_operator"
6478			     [(match_operand:SI 1 "s_register_operand" "r")
6479			      (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6480  "TARGET_ARM"
6481  "cmn%?\\t%0, %1%S3"
6482  [(set_attr "conds" "set")
6483   (set_attr "shift" "1")
6484   ]
6485)
6486
6487;; Cirrus SF compare instruction
6488(define_insn "*cirrus_cmpsf"
6489  [(set (reg:CCFP CC_REGNUM)
6490	(compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6491		      (match_operand:SF 1 "cirrus_fp_register" "v")))]
6492  "TARGET_ARM && TARGET_CIRRUS"
6493  "cfcmps%?\\tr15, %V0, %V1"
6494  [(set_attr "type"   "mav_farith")
6495   (set_attr "cirrus" "compare")]
6496)
6497
6498;; Cirrus DF compare instruction
6499(define_insn "*cirrus_cmpdf"
6500  [(set (reg:CCFP CC_REGNUM)
6501	(compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6502		      (match_operand:DF 1 "cirrus_fp_register" "v")))]
6503  "TARGET_ARM && TARGET_CIRRUS"
6504  "cfcmpd%?\\tr15, %V0, %V1"
6505  [(set_attr "type"   "mav_farith")
6506   (set_attr "cirrus" "compare")]
6507)
6508
6509;; Cirrus DI compare instruction
6510(define_expand "cmpdi"
6511  [(match_operand:DI 0 "cirrus_fp_register" "")
6512   (match_operand:DI 1 "cirrus_fp_register" "")]
6513  "TARGET_ARM && TARGET_CIRRUS"
6514  "{
6515     arm_compare_op0 = operands[0];
6516     arm_compare_op1 = operands[1];
6517     DONE;
6518   }")
6519
6520(define_insn "*cirrus_cmpdi"
6521  [(set (reg:CC CC_REGNUM)
6522	(compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6523		    (match_operand:DI 1 "cirrus_fp_register" "v")))]
6524  "TARGET_ARM && TARGET_CIRRUS"
6525  "cfcmp64%?\\tr15, %V0, %V1"
6526  [(set_attr "type"   "mav_farith")
6527   (set_attr "cirrus" "compare")]
6528)
6529
6530; This insn allows redundant compares to be removed by cse, nothing should
6531; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6532; is deleted later on. The match_dup will match the mode here, so that
6533; mode changes of the condition codes aren't lost by this even though we don't
6534; specify what they are.
6535
6536(define_insn "*deleted_compare"
6537  [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6538  "TARGET_ARM"
6539  "\\t%@ deleted compare"
6540  [(set_attr "conds" "set")
6541   (set_attr "length" "0")]
6542)
6543
6544
6545;; Conditional branch insns
6546
6547(define_expand "beq"
6548  [(set (pc)
6549	(if_then_else (eq (match_dup 1) (const_int 0))
6550		      (label_ref (match_operand 0 "" ""))
6551		      (pc)))]
6552  "TARGET_ARM"
6553  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6554)
6555
6556(define_expand "bne"
6557  [(set (pc)
6558	(if_then_else (ne (match_dup 1) (const_int 0))
6559		      (label_ref (match_operand 0 "" ""))
6560		      (pc)))]
6561  "TARGET_ARM"
6562  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6563)
6564
6565(define_expand "bgt"
6566  [(set (pc)
6567	(if_then_else (gt (match_dup 1) (const_int 0))
6568		      (label_ref (match_operand 0 "" ""))
6569		      (pc)))]
6570  "TARGET_ARM"
6571  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6572)
6573
6574(define_expand "ble"
6575  [(set (pc)
6576	(if_then_else (le (match_dup 1) (const_int 0))
6577		      (label_ref (match_operand 0 "" ""))
6578		      (pc)))]
6579  "TARGET_ARM"
6580  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6581)
6582
6583(define_expand "bge"
6584  [(set (pc)
6585	(if_then_else (ge (match_dup 1) (const_int 0))
6586		      (label_ref (match_operand 0 "" ""))
6587		      (pc)))]
6588  "TARGET_ARM"
6589  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6590)
6591
6592(define_expand "blt"
6593  [(set (pc)
6594	(if_then_else (lt (match_dup 1) (const_int 0))
6595		      (label_ref (match_operand 0 "" ""))
6596		      (pc)))]
6597  "TARGET_ARM"
6598  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6599)
6600
6601(define_expand "bgtu"
6602  [(set (pc)
6603	(if_then_else (gtu (match_dup 1) (const_int 0))
6604		      (label_ref (match_operand 0 "" ""))
6605		      (pc)))]
6606  "TARGET_ARM"
6607  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6608)
6609
6610(define_expand "bleu"
6611  [(set (pc)
6612	(if_then_else (leu (match_dup 1) (const_int 0))
6613		      (label_ref (match_operand 0 "" ""))
6614		      (pc)))]
6615  "TARGET_ARM"
6616  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6617)
6618
6619(define_expand "bgeu"
6620  [(set (pc)
6621	(if_then_else (geu (match_dup 1) (const_int 0))
6622		      (label_ref (match_operand 0 "" ""))
6623		      (pc)))]
6624  "TARGET_ARM"
6625  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6626)
6627
6628(define_expand "bltu"
6629  [(set (pc)
6630	(if_then_else (ltu (match_dup 1) (const_int 0))
6631		      (label_ref (match_operand 0 "" ""))
6632		      (pc)))]
6633  "TARGET_ARM"
6634  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6635)
6636
6637(define_expand "bunordered"
6638  [(set (pc)
6639	(if_then_else (unordered (match_dup 1) (const_int 0))
6640		      (label_ref (match_operand 0 "" ""))
6641		      (pc)))]
6642  "TARGET_ARM && TARGET_HARD_FLOAT"
6643  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6644				      arm_compare_op1);"
6645)
6646
6647(define_expand "bordered"
6648  [(set (pc)
6649	(if_then_else (ordered (match_dup 1) (const_int 0))
6650		      (label_ref (match_operand 0 "" ""))
6651		      (pc)))]
6652  "TARGET_ARM && TARGET_HARD_FLOAT"
6653  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6654				      arm_compare_op1);"
6655)
6656
6657(define_expand "bungt"
6658  [(set (pc)
6659	(if_then_else (ungt (match_dup 1) (const_int 0))
6660		      (label_ref (match_operand 0 "" ""))
6661		      (pc)))]
6662  "TARGET_ARM && TARGET_HARD_FLOAT"
6663  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6664)
6665
6666(define_expand "bunlt"
6667  [(set (pc)
6668	(if_then_else (unlt (match_dup 1) (const_int 0))
6669		      (label_ref (match_operand 0 "" ""))
6670		      (pc)))]
6671  "TARGET_ARM && TARGET_HARD_FLOAT"
6672  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6673)
6674
6675(define_expand "bunge"
6676  [(set (pc)
6677	(if_then_else (unge (match_dup 1) (const_int 0))
6678		      (label_ref (match_operand 0 "" ""))
6679		      (pc)))]
6680  "TARGET_ARM && TARGET_HARD_FLOAT"
6681  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6682)
6683
6684(define_expand "bunle"
6685  [(set (pc)
6686	(if_then_else (unle (match_dup 1) (const_int 0))
6687		      (label_ref (match_operand 0 "" ""))
6688		      (pc)))]
6689  "TARGET_ARM && TARGET_HARD_FLOAT"
6690  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6691)
6692
6693;; The following two patterns need two branch instructions, since there is
6694;; no single instruction that will handle all cases.
6695(define_expand "buneq"
6696  [(set (pc)
6697	(if_then_else (uneq (match_dup 1) (const_int 0))
6698		      (label_ref (match_operand 0 "" ""))
6699		      (pc)))]
6700  "TARGET_ARM && TARGET_HARD_FLOAT"
6701  "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6702)
6703
6704(define_expand "bltgt"
6705  [(set (pc)
6706	(if_then_else (ltgt (match_dup 1) (const_int 0))
6707		      (label_ref (match_operand 0 "" ""))
6708		      (pc)))]
6709  "TARGET_ARM && TARGET_HARD_FLOAT"
6710  "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6711)
6712
6713;;
6714;; Patterns to match conditional branch insns.
6715;;
6716
6717; Special pattern to match UNEQ.
6718(define_insn "*arm_buneq"
6719  [(set (pc)
6720	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6721		      (label_ref (match_operand 0 "" ""))
6722		      (pc)))]
6723  "TARGET_ARM && TARGET_HARD_FLOAT"
6724  "*
6725  if (arm_ccfsm_state != 0)
6726    abort ();
6727
6728  return \"bvs\\t%l0\;beq\\t%l0\";
6729  "
6730  [(set_attr "conds" "jump_clob")
6731   (set_attr "length" "8")]
6732)
6733
6734; Special pattern to match LTGT.
6735(define_insn "*arm_bltgt"
6736  [(set (pc)
6737	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6738		      (label_ref (match_operand 0 "" ""))
6739		      (pc)))]
6740  "TARGET_ARM && TARGET_HARD_FLOAT"
6741  "*
6742  if (arm_ccfsm_state != 0)
6743    abort ();
6744
6745  return \"bmi\\t%l0\;bgt\\t%l0\";
6746  "
6747  [(set_attr "conds" "jump_clob")
6748   (set_attr "length" "8")]
6749)
6750
6751(define_insn "*arm_cond_branch"
6752  [(set (pc)
6753	(if_then_else (match_operator 1 "arm_comparison_operator"
6754		       [(match_operand 2 "cc_register" "") (const_int 0)])
6755		      (label_ref (match_operand 0 "" ""))
6756		      (pc)))]
6757  "TARGET_ARM"
6758  "*
6759  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6760    {
6761      arm_ccfsm_state += 2;
6762      return \"\";
6763    }
6764  return \"b%d1\\t%l0\";
6765  "
6766  [(set_attr "conds" "use")]
6767)
6768
6769; Special pattern to match reversed UNEQ.
6770(define_insn "*arm_buneq_reversed"
6771  [(set (pc)
6772	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6773		      (pc)
6774		      (label_ref (match_operand 0 "" ""))))]
6775  "TARGET_ARM && TARGET_HARD_FLOAT"
6776  "*
6777  if (arm_ccfsm_state != 0)
6778    abort ();
6779
6780  return \"bmi\\t%l0\;bgt\\t%l0\";
6781  "
6782  [(set_attr "conds" "jump_clob")
6783   (set_attr "length" "8")]
6784)
6785
6786; Special pattern to match reversed LTGT.
6787(define_insn "*arm_bltgt_reversed"
6788  [(set (pc)
6789	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6790		      (pc)
6791		      (label_ref (match_operand 0 "" ""))))]
6792  "TARGET_ARM && TARGET_HARD_FLOAT"
6793  "*
6794  if (arm_ccfsm_state != 0)
6795    abort ();
6796
6797  return \"bvs\\t%l0\;beq\\t%l0\";
6798  "
6799  [(set_attr "conds" "jump_clob")
6800   (set_attr "length" "8")]
6801)
6802
6803(define_insn "*arm_cond_branch_reversed"
6804  [(set (pc)
6805	(if_then_else (match_operator 1 "arm_comparison_operator"
6806		       [(match_operand 2 "cc_register" "") (const_int 0)])
6807		      (pc)
6808		      (label_ref (match_operand 0 "" ""))))]
6809  "TARGET_ARM"
6810  "*
6811  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6812    {
6813      arm_ccfsm_state += 2;
6814      return \"\";
6815    }
6816  return \"b%D1\\t%l0\";
6817  "
6818  [(set_attr "conds" "use")]
6819)
6820
6821
6822
6823; scc insns
6824
6825(define_expand "seq"
6826  [(set (match_operand:SI 0 "s_register_operand" "")
6827	(eq:SI (match_dup 1) (const_int 0)))]
6828  "TARGET_ARM"
6829  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6830)
6831
6832(define_expand "sne"
6833  [(set (match_operand:SI 0 "s_register_operand" "")
6834	(ne:SI (match_dup 1) (const_int 0)))]
6835  "TARGET_ARM"
6836  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6837)
6838
6839(define_expand "sgt"
6840  [(set (match_operand:SI 0 "s_register_operand" "")
6841	(gt:SI (match_dup 1) (const_int 0)))]
6842  "TARGET_ARM"
6843  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6844)
6845
6846(define_expand "sle"
6847  [(set (match_operand:SI 0 "s_register_operand" "")
6848	(le:SI (match_dup 1) (const_int 0)))]
6849  "TARGET_ARM"
6850  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6851)
6852
6853(define_expand "sge"
6854  [(set (match_operand:SI 0 "s_register_operand" "")
6855	(ge:SI (match_dup 1) (const_int 0)))]
6856  "TARGET_ARM"
6857  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6858)
6859
6860(define_expand "slt"
6861  [(set (match_operand:SI 0 "s_register_operand" "")
6862	(lt:SI (match_dup 1) (const_int 0)))]
6863  "TARGET_ARM"
6864  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6865)
6866
6867(define_expand "sgtu"
6868  [(set (match_operand:SI 0 "s_register_operand" "")
6869	(gtu:SI (match_dup 1) (const_int 0)))]
6870  "TARGET_ARM"
6871  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6872)
6873
6874(define_expand "sleu"
6875  [(set (match_operand:SI 0 "s_register_operand" "")
6876	(leu:SI (match_dup 1) (const_int 0)))]
6877  "TARGET_ARM"
6878  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6879)
6880
6881(define_expand "sgeu"
6882  [(set (match_operand:SI 0 "s_register_operand" "")
6883	(geu:SI (match_dup 1) (const_int 0)))]
6884  "TARGET_ARM"
6885  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6886)
6887
6888(define_expand "sltu"
6889  [(set (match_operand:SI 0 "s_register_operand" "")
6890	(ltu:SI (match_dup 1) (const_int 0)))]
6891  "TARGET_ARM"
6892  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6893)
6894
6895(define_expand "sunordered"
6896  [(set (match_operand:SI 0 "s_register_operand" "")
6897	(unordered:SI (match_dup 1) (const_int 0)))]
6898  "TARGET_ARM && TARGET_HARD_FLOAT"
6899  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6900				      arm_compare_op1);"
6901)
6902
6903(define_expand "sordered"
6904  [(set (match_operand:SI 0 "s_register_operand" "")
6905	(ordered:SI (match_dup 1) (const_int 0)))]
6906  "TARGET_ARM && TARGET_HARD_FLOAT"
6907  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6908				      arm_compare_op1);"
6909)
6910
6911(define_expand "sungt"
6912  [(set (match_operand:SI 0 "s_register_operand" "")
6913	(ungt:SI (match_dup 1) (const_int 0)))]
6914  "TARGET_ARM && TARGET_HARD_FLOAT"
6915  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6916				      arm_compare_op1);"
6917)
6918
6919(define_expand "sunge"
6920  [(set (match_operand:SI 0 "s_register_operand" "")
6921	(unge:SI (match_dup 1) (const_int 0)))]
6922  "TARGET_ARM && TARGET_HARD_FLOAT"
6923  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6924				      arm_compare_op1);"
6925)
6926
6927(define_expand "sunlt"
6928  [(set (match_operand:SI 0 "s_register_operand" "")
6929	(unlt:SI (match_dup 1) (const_int 0)))]
6930  "TARGET_ARM && TARGET_HARD_FLOAT"
6931  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6932				      arm_compare_op1);"
6933)
6934
6935(define_expand "sunle"
6936  [(set (match_operand:SI 0 "s_register_operand" "")
6937	(unle:SI (match_dup 1) (const_int 0)))]
6938  "TARGET_ARM && TARGET_HARD_FLOAT"
6939  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6940				      arm_compare_op1);"
6941)
6942
6943;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6944;;; simple ARM instructions. 
6945;
6946; (define_expand "suneq"
6947;   [(set (match_operand:SI 0 "s_register_operand" "")
6948; 	(uneq:SI (match_dup 1) (const_int 0)))]
6949;   "TARGET_ARM && TARGET_HARD_FLOAT"
6950;   "abort ();"
6951; )
6952;
6953; (define_expand "sltgt"
6954;   [(set (match_operand:SI 0 "s_register_operand" "")
6955; 	(ltgt:SI (match_dup 1) (const_int 0)))]
6956;   "TARGET_ARM && TARGET_HARD_FLOAT"
6957;   "abort ();"
6958; )
6959
6960(define_insn "*mov_scc"
6961  [(set (match_operand:SI 0 "s_register_operand" "=r")
6962	(match_operator:SI 1 "arm_comparison_operator"
6963	 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6964  "TARGET_ARM"
6965  "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6966  [(set_attr "conds" "use")
6967   (set_attr "length" "8")]
6968)
6969
6970(define_insn "*mov_negscc"
6971  [(set (match_operand:SI 0 "s_register_operand" "=r")
6972	(neg:SI (match_operator:SI 1 "arm_comparison_operator"
6973		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6974  "TARGET_ARM"
6975  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6976  [(set_attr "conds" "use")
6977   (set_attr "length" "8")]
6978)
6979
6980(define_insn "*mov_notscc"
6981  [(set (match_operand:SI 0 "s_register_operand" "=r")
6982	(not:SI (match_operator:SI 1 "arm_comparison_operator"
6983		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6984  "TARGET_ARM"
6985  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6986  [(set_attr "conds" "use")
6987   (set_attr "length" "8")]
6988)
6989
6990
6991;; Conditional move insns
6992
6993(define_expand "movsicc"
6994  [(set (match_operand:SI 0 "s_register_operand" "")
6995	(if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6996			 (match_operand:SI 2 "arm_not_operand" "")
6997			 (match_operand:SI 3 "arm_not_operand" "")))]
6998  "TARGET_ARM"
6999  "
7000  {
7001    enum rtx_code code = GET_CODE (operands[1]);
7002    rtx ccreg;
7003
7004    if (code == UNEQ || code == LTGT)
7005      FAIL;
7006
7007    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7008    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7009  }"
7010)
7011
7012(define_expand "movsfcc"
7013  [(set (match_operand:SF 0 "s_register_operand" "")
7014	(if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7015			 (match_operand:SF 2 "s_register_operand" "")
7016			 (match_operand:SF 3 "nonmemory_operand" "")))]
7017  "TARGET_ARM"
7018  "
7019  {
7020    enum rtx_code code = GET_CODE (operands[1]);
7021    rtx ccreg;
7022
7023    if (code == UNEQ || code == LTGT)
7024      FAIL;
7025
7026    /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7027       Otherwise, ensure it is a valid FP add operand.  */
7028    if ((!TARGET_HARD_FLOAT)
7029        || (!fpa_add_operand (operands[3], SFmode)))
7030      operands[3] = force_reg (SFmode, operands[3]);
7031
7032    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7033    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7034  }"
7035)
7036
7037(define_expand "movdfcc"
7038  [(set (match_operand:DF 0 "s_register_operand" "")
7039	(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7040			 (match_operand:DF 2 "s_register_operand" "")
7041			 (match_operand:DF 3 "fpa_add_operand" "")))]
7042  "TARGET_ARM && TARGET_HARD_FLOAT"
7043  "
7044  {
7045    enum rtx_code code = GET_CODE (operands[1]);
7046    rtx ccreg;
7047
7048    if (code == UNEQ || code == LTGT)
7049      FAIL;
7050
7051    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7052    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7053  }"
7054)
7055
7056(define_insn "*movsicc_insn"
7057  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7058	(if_then_else:SI
7059	 (match_operator 3 "arm_comparison_operator"
7060	  [(match_operand 4 "cc_register" "") (const_int 0)])
7061	 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7062	 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7063  "TARGET_ARM"
7064  "@
7065   mov%D3\\t%0, %2
7066   mvn%D3\\t%0, #%B2
7067   mov%d3\\t%0, %1
7068   mvn%d3\\t%0, #%B1
7069   mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7070   mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7071   mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7072   mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7073  [(set_attr "length" "4,4,4,4,8,8,8,8")
7074   (set_attr "conds" "use")]
7075)
7076
7077(define_insn "*movsfcc_soft_insn"
7078  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7079	(if_then_else:SF (match_operator 3 "arm_comparison_operator"
7080			  [(match_operand 4 "cc_register" "") (const_int 0)])
7081			 (match_operand:SF 1 "s_register_operand" "0,r")
7082			 (match_operand:SF 2 "s_register_operand" "r,0")))]
7083  "TARGET_ARM && TARGET_SOFT_FLOAT"
7084  "@
7085   mov%D3\\t%0, %2
7086   mov%d3\\t%0, %1"
7087  [(set_attr "conds" "use")]
7088)
7089
7090
7091;; Jump and linkage insns
7092
7093(define_expand "jump"
7094  [(set (pc)
7095	(label_ref (match_operand 0 "" "")))]
7096  "TARGET_EITHER"
7097  ""
7098)
7099
7100(define_insn "*arm_jump"
7101  [(set (pc)
7102	(label_ref (match_operand 0 "" "")))]
7103  "TARGET_ARM"
7104  "*
7105  {
7106    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7107      {
7108        arm_ccfsm_state += 2;
7109        return \"\";
7110      }
7111    return \"b%?\\t%l0\";
7112  }
7113  "
7114  [(set_attr "predicable" "yes")]
7115)
7116
7117(define_insn "*thumb_jump"
7118  [(set (pc)
7119	(label_ref (match_operand 0 "" "")))]
7120  "TARGET_THUMB"
7121  "*
7122  if (get_attr_length (insn) == 2)
7123    return \"b\\t%l0\";
7124  return \"bl\\t%l0\\t%@ far jump\";
7125  "
7126  [(set (attr "far_jump")
7127        (if_then_else
7128	    (eq_attr "length" "4")
7129	    (const_string "yes")
7130	    (const_string "no")))
7131   (set (attr "length") 
7132        (if_then_else
7133	    (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7134		 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7135  	    (const_int 2)
7136	    (const_int 4)))]
7137)
7138
7139(define_expand "call"
7140  [(parallel [(call (match_operand 0 "memory_operand" "")
7141	            (match_operand 1 "general_operand" ""))
7142	      (use (match_operand 2 "" ""))
7143	      (clobber (reg:SI LR_REGNUM))])]
7144  "TARGET_EITHER"
7145  "
7146  {
7147    rtx callee;
7148    
7149    /* In an untyped call, we can get NULL for operand 2.  */
7150    if (operands[2] == NULL_RTX)
7151      operands[2] = const0_rtx;
7152      
7153    /* This is to decide if we should generate indirect calls by loading the
7154       32 bit address of the callee into a register before performing the
7155       branch and link.  operand[2] encodes the long_call/short_call
7156       attribute of the function being called.  This attribute is set whenever
7157       __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7158       is used, and the short_call attribute can also be set if function is
7159       declared as static or if it has already been defined in the current
7160       compilation unit.  See arm.c and arm.h for info about this.  The third
7161       parameter to arm_is_longcall_p is used to tell it which pattern
7162       invoked it.  */
7163    callee  = XEXP (operands[0], 0);
7164    
7165    if (GET_CODE (callee) != REG
7166       && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7167      XEXP (operands[0], 0) = force_reg (Pmode, callee);
7168  }"
7169)
7170
7171(define_insn "*call_reg"
7172  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7173         (match_operand 1 "" ""))
7174   (use (match_operand 2 "" ""))
7175   (clobber (reg:SI LR_REGNUM))]
7176  "TARGET_ARM"
7177  "*
7178  return output_call (operands);
7179  "
7180  ;; length is worst case, normally it is only two
7181  [(set_attr "length" "12")
7182   (set_attr "type" "call")]
7183)
7184
7185(define_insn "*call_mem"
7186  [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7187	 (match_operand 1 "" ""))
7188   (use (match_operand 2 "" ""))
7189   (clobber (reg:SI LR_REGNUM))]
7190  "TARGET_ARM"
7191  "*
7192  return output_call_mem (operands);
7193  "
7194  [(set_attr "length" "12")
7195   (set_attr "type" "call")]
7196)
7197
7198(define_insn "*call_indirect"
7199  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7200	 (match_operand 1 "" ""))
7201   (use (match_operand 2 "" ""))
7202   (clobber (reg:SI LR_REGNUM))]
7203  "TARGET_THUMB"
7204  "*
7205  {
7206    if (TARGET_CALLER_INTERWORKING)
7207      return \"bl\\t%__interwork_call_via_%0\";
7208    else
7209      return \"bl\\t%__call_via_%0\";
7210  }"
7211  [(set_attr "type" "call")]
7212)
7213
7214(define_insn "*call_value_indirect"
7215  [(set (match_operand 0 "" "")
7216	(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7217	      (match_operand 2 "" "")))
7218   (use (match_operand 3 "" ""))
7219   (clobber (reg:SI LR_REGNUM))]
7220  "TARGET_THUMB"
7221  "*
7222  {
7223    if (TARGET_CALLER_INTERWORKING)
7224      return \"bl\\t%__interwork_call_via_%1\";
7225    else
7226      return \"bl\\t%__call_via_%1\";
7227  }"
7228  [(set_attr "type" "call")]
7229)
7230
7231(define_expand "call_value"
7232  [(parallel [(set (match_operand       0 "" "")
7233	           (call (match_operand 1 "memory_operand" "")
7234		         (match_operand 2 "general_operand" "")))
7235	      (use (match_operand 3 "" ""))
7236	      (clobber (reg:SI LR_REGNUM))])]
7237  "TARGET_EITHER"
7238  "
7239  {
7240    rtx callee = XEXP (operands[1], 0);
7241    
7242    /* In an untyped call, we can get NULL for operand 2.  */
7243    if (operands[3] == 0)
7244      operands[3] = const0_rtx;
7245      
7246    /* See the comment in define_expand \"call\".  */
7247    if (GET_CODE (callee) != REG
7248	&& arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7249      XEXP (operands[1], 0) = force_reg (Pmode, callee);
7250  }"
7251)
7252
7253(define_insn "*call_value_reg"
7254  [(set (match_operand 0 "" "")
7255        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7256	      (match_operand 2 "" "")))
7257   (use (match_operand 3 "" ""))
7258   (clobber (reg:SI LR_REGNUM))]
7259  "TARGET_ARM"
7260  "*
7261  return output_call (&operands[1]);
7262  "
7263  [(set_attr "length" "12")
7264   (set_attr "type" "call")]
7265)
7266
7267(define_insn "*call_value_mem"
7268  [(set (match_operand 0 "" "")
7269	(call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7270	      (match_operand 2 "" "")))
7271   (use (match_operand 3 "" ""))
7272   (clobber (reg:SI LR_REGNUM))]
7273  "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7274  "*
7275  return output_call_mem (&operands[1]);
7276  "
7277  [(set_attr "length" "12")
7278   (set_attr "type" "call")]
7279)
7280
7281;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7282;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7283
7284(define_insn "*call_symbol"
7285  [(call (mem:SI (match_operand:SI 0 "" ""))
7286	 (match_operand 1 "" ""))
7287   (use (match_operand 2 "" ""))
7288   (clobber (reg:SI LR_REGNUM))]
7289  "TARGET_ARM
7290   && (GET_CODE (operands[0]) == SYMBOL_REF)
7291   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7292  "*
7293  {
7294    return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7295  }"
7296  [(set_attr "type" "call")]
7297)
7298
7299(define_insn "*call_value_symbol"
7300  [(set (match_operand 0 "s_register_operand" "")
7301	(call (mem:SI (match_operand:SI 1 "" ""))
7302	(match_operand:SI 2 "" "")))
7303   (use (match_operand 3 "" ""))
7304   (clobber (reg:SI LR_REGNUM))]
7305  "TARGET_ARM
7306   && (GET_CODE (operands[1]) == SYMBOL_REF)
7307   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7308  "*
7309  {
7310    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7311  }"
7312  [(set_attr "type" "call")]
7313)
7314
7315(define_insn "*call_insn"
7316  [(call (mem:SI (match_operand:SI 0 "" ""))
7317	 (match_operand:SI 1 "" ""))
7318   (use (match_operand 2 "" ""))
7319   (clobber (reg:SI LR_REGNUM))]
7320  "TARGET_THUMB
7321   && GET_CODE (operands[0]) == SYMBOL_REF
7322   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7323  "bl\\t%a0"
7324  [(set_attr "length" "4")
7325   (set_attr "type" "call")]
7326)
7327
7328(define_insn "*call_value_insn"
7329  [(set (match_operand 0 "register_operand" "")
7330	(call (mem:SI (match_operand 1 "" ""))
7331	      (match_operand 2 "" "")))
7332   (use (match_operand 3 "" ""))
7333   (clobber (reg:SI LR_REGNUM))]
7334  "TARGET_THUMB
7335   && GET_CODE (operands[1]) == SYMBOL_REF
7336   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7337  "bl\\t%a1"
7338  [(set_attr "length" "4")
7339   (set_attr "type" "call")]
7340)
7341
7342;; We may also be able to do sibcalls for Thumb, but it's much harder...
7343(define_expand "sibcall"
7344  [(parallel [(call (match_operand 0 "memory_operand" "")
7345		    (match_operand 1 "general_operand" ""))
7346	      (return)
7347	      (use (match_operand 2 "" ""))])]
7348  "TARGET_ARM"
7349  "
7350  {
7351    if (operands[2] == NULL_RTX)
7352      operands[2] = const0_rtx;
7353  }"
7354)
7355
7356(define_expand "sibcall_value"
7357  [(parallel [(set (match_operand 0 "register_operand" "")
7358		   (call (match_operand 1 "memory_operand" "")
7359			 (match_operand 2 "general_operand" "")))
7360	      (return)
7361	      (use (match_operand 3 "" ""))])]
7362  "TARGET_ARM"
7363  "
7364  {
7365    if (operands[3] == NULL_RTX)
7366      operands[3] = const0_rtx;
7367  }"
7368)
7369
7370(define_insn "*sibcall_insn"
7371 [(call (mem:SI (match_operand:SI 0 "" "X"))
7372	(match_operand 1 "" ""))
7373  (return)
7374  (use (match_operand 2 "" ""))]
7375  "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7376  "*
7377  return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7378  "
7379  [(set_attr "type" "call")]
7380)
7381
7382(define_insn "*sibcall_value_insn"
7383 [(set (match_operand 0 "s_register_operand" "")
7384       (call (mem:SI (match_operand:SI 1 "" "X"))
7385	     (match_operand 2 "" "")))
7386  (return)
7387  (use (match_operand 3 "" ""))]
7388  "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7389  "*
7390  return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7391  "
7392  [(set_attr "type" "call")]
7393)
7394
7395;; Often the return insn will be the same as loading from memory, so set attr
7396(define_insn "return"
7397  [(return)]
7398  "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7399  "*
7400  {
7401    if (arm_ccfsm_state == 2)
7402      {
7403        arm_ccfsm_state += 2;
7404        return \"\";
7405      }
7406    return output_return_instruction (const_true_rtx, TRUE, FALSE);
7407  }"
7408  [(set_attr "type" "load")
7409   (set_attr "length" "12")
7410   (set_attr "predicable" "yes")]
7411)
7412
7413(define_insn "*cond_return"
7414  [(set (pc)
7415        (if_then_else (match_operator 0 "arm_comparison_operator"
7416		       [(match_operand 1 "cc_register" "") (const_int 0)])
7417                      (return)
7418                      (pc)))]
7419  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7420  "*
7421  {
7422    if (arm_ccfsm_state == 2)
7423      {
7424        arm_ccfsm_state += 2;
7425        return \"\";
7426      }
7427    return output_return_instruction (operands[0], TRUE, FALSE);
7428  }"
7429  [(set_attr "conds" "use")
7430   (set_attr "length" "12")
7431   (set_attr "type" "load")]
7432)
7433
7434(define_insn "*cond_return_inverted"
7435  [(set (pc)
7436        (if_then_else (match_operator 0 "arm_comparison_operator"
7437		       [(match_operand 1 "cc_register" "") (const_int 0)])
7438                      (pc)
7439		      (return)))]
7440  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7441  "*
7442  {
7443    if (arm_ccfsm_state == 2)
7444      {
7445        arm_ccfsm_state += 2;
7446        return \"\";
7447      }
7448    return output_return_instruction (operands[0], TRUE, TRUE);
7449  }"
7450  [(set_attr "conds" "use")
7451   (set_attr "type" "load")]
7452)
7453
7454;; Generate a sequence of instructions to determine if the processor is
7455;; in 26-bit or 32-bit mode, and return the appropriate return address
7456;; mask.
7457
7458(define_expand "return_addr_mask"
7459  [(set (match_dup 1)
7460      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7461		       (const_int 0)))
7462   (set (match_operand:SI 0 "s_register_operand" "")
7463      (if_then_else:SI (eq (match_dup 1) (const_int 0))
7464		       (const_int -1)
7465		       (const_int 67108860)))] ; 0x03fffffc
7466  "TARGET_ARM"
7467  "
7468  operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7469  ")
7470
7471(define_insn "*check_arch2"
7472  [(set (match_operand:CC_NOOV 0 "cc_register" "")
7473      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7474		       (const_int 0)))]
7475  "TARGET_ARM"
7476  "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7477  [(set_attr "length" "8")
7478   (set_attr "conds" "set")]
7479)
7480
7481;; Call subroutine returning any type.
7482
7483(define_expand "untyped_call"
7484  [(parallel [(call (match_operand 0 "" "")
7485		    (const_int 0))
7486	      (match_operand 1 "" "")
7487	      (match_operand 2 "" "")])]
7488  "TARGET_ARM"
7489  "
7490  {
7491    int i;
7492
7493    emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7494
7495    for (i = 0; i < XVECLEN (operands[2], 0); i++)
7496      {
7497	rtx set = XVECEXP (operands[2], 0, i);
7498
7499	emit_move_insn (SET_DEST (set), SET_SRC (set));
7500      }
7501
7502    /* The optimizer does not know that the call sets the function value
7503       registers we stored in the result block.  We avoid problems by
7504       claiming that all hard registers are used and clobbered at this
7505       point.  */
7506    emit_insn (gen_blockage ());
7507
7508    DONE;
7509  }"
7510)
7511
7512;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7513;; all of memory.  This blocks insns from being moved across this point.
7514
7515(define_insn "blockage"
7516  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7517  "TARGET_EITHER"
7518  ""
7519  [(set_attr "length" "0")
7520   (set_attr "type" "block")]
7521)
7522
7523(define_expand "casesi"
7524  [(match_operand:SI 0 "s_register_operand" "")	; index to jump on
7525   (match_operand:SI 1 "const_int_operand" "")	; lower bound
7526   (match_operand:SI 2 "const_int_operand" "")	; total range
7527   (match_operand:SI 3 "" "")			; table label
7528   (match_operand:SI 4 "" "")]			; Out of range label
7529  "TARGET_ARM"
7530  "
7531  {
7532    rtx reg;
7533    if (operands[1] != const0_rtx)
7534      {
7535	reg = gen_reg_rtx (SImode);
7536
7537	emit_insn (gen_addsi3 (reg, operands[0],
7538			       GEN_INT (-INTVAL (operands[1]))));
7539	operands[0] = reg;
7540      }
7541
7542    if (!const_ok_for_arm (INTVAL (operands[2])))
7543      operands[2] = force_reg (SImode, operands[2]);
7544
7545    emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7546					 operands[4]));
7547    DONE;
7548  }"
7549)
7550
7551;; The USE in this pattern is needed to tell flow analysis that this is
7552;; a CASESI insn.  It has no other purpose.
7553(define_insn "casesi_internal"
7554  [(parallel [(set (pc)
7555	       (if_then_else
7556		(leu (match_operand:SI 0 "s_register_operand" "r")
7557		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
7558		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7559				 (label_ref (match_operand 2 "" ""))))
7560		(label_ref (match_operand 3 "" ""))))
7561	      (clobber (reg:CC CC_REGNUM))
7562	      (use (label_ref (match_dup 2)))])]
7563  "TARGET_ARM"
7564  "*
7565    if (flag_pic)
7566      return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7567    return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7568  "
7569  [(set_attr "conds" "clob")
7570   (set_attr "length" "12")]
7571)
7572
7573(define_expand "indirect_jump"
7574  [(set (pc)
7575	(match_operand:SI 0 "s_register_operand" ""))]
7576  "TARGET_EITHER"
7577  ""
7578)
7579
7580(define_insn "*arm_indirect_jump"
7581  [(set (pc)
7582	(match_operand:SI 0 "s_register_operand" "r"))]
7583  "TARGET_ARM"
7584  "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7585  [(set_attr "predicable" "yes")]
7586)
7587
7588;; Although not supported by the define_expand above,
7589;; cse/combine may generate this form.
7590(define_insn "*load_indirect_jump"
7591  [(set (pc)
7592	(match_operand:SI 0 "memory_operand" "m"))]
7593  "TARGET_ARM"
7594  "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7595  [(set_attr "type" "load")
7596   (set_attr "pool_range" "4096")
7597   (set_attr "neg_pool_range" "4084")
7598   (set_attr "predicable" "yes")]
7599)
7600
7601(define_insn "*thumb_indirect_jump"
7602  [(set (pc)
7603	(match_operand:SI 0 "register_operand" "l*r"))]
7604  "TARGET_THUMB"
7605  "mov\\tpc, %0"
7606  [(set_attr "conds" "clob")
7607   (set_attr "length" "2")]
7608)
7609
7610
7611;; Misc insns
7612
7613(define_insn "nop"
7614  [(const_int 0)]
7615  "TARGET_EITHER"
7616  "*
7617  if (TARGET_ARM)
7618    return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7619  return  \"mov\\tr8, r8\";
7620  "
7621  [(set (attr "length")
7622	(if_then_else (eq_attr "is_thumb" "yes")
7623		      (const_int 2)
7624		      (const_int 4)))]
7625)
7626
7627
7628;; Patterns to allow combination of arithmetic, cond code and shifts
7629
7630(define_insn "*arith_shiftsi"
7631  [(set (match_operand:SI 0 "s_register_operand" "=r")
7632        (match_operator:SI 1 "shiftable_operator"
7633          [(match_operator:SI 3 "shift_operator"
7634             [(match_operand:SI 4 "s_register_operand" "r")
7635              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7636           (match_operand:SI 2 "s_register_operand" "r")]))]
7637  "TARGET_ARM"
7638  "%i1%?\\t%0, %2, %4%S3"
7639  [(set_attr "predicable" "yes")
7640   (set_attr "shift" "4")
7641   ]
7642)
7643
7644(define_split
7645  [(set (match_operand:SI 0 "s_register_operand" "")
7646	(match_operator:SI 1 "shiftable_operator"
7647	 [(match_operator:SI 2 "shiftable_operator"
7648	   [(match_operator:SI 3 "shift_operator"
7649	     [(match_operand:SI 4 "s_register_operand" "")
7650	      (match_operand:SI 5 "reg_or_int_operand" "")])
7651	    (match_operand:SI 6 "s_register_operand" "")])
7652	  (match_operand:SI 7 "arm_rhs_operand" "")]))
7653   (clobber (match_operand:SI 8 "s_register_operand" ""))]
7654  "TARGET_ARM"
7655  [(set (match_dup 8)
7656	(match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7657			 (match_dup 6)]))
7658   (set (match_dup 0)
7659	(match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7660  "")
7661
7662(define_insn "*arith_shiftsi_compare0"
7663  [(set (reg:CC_NOOV CC_REGNUM)
7664        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7665		          [(match_operator:SI 3 "shift_operator"
7666		            [(match_operand:SI 4 "s_register_operand" "r")
7667		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
7668		           (match_operand:SI 2 "s_register_operand" "r")])
7669			 (const_int 0)))
7670   (set (match_operand:SI 0 "s_register_operand" "=r")
7671	(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7672			 (match_dup 2)]))]
7673  "TARGET_ARM"
7674  "%i1%?s\\t%0, %2, %4%S3"
7675  [(set_attr "conds" "set")
7676   (set_attr "shift" "4")
7677   ]
7678)
7679
7680(define_insn "*arith_shiftsi_compare0_scratch"
7681  [(set (reg:CC_NOOV CC_REGNUM)
7682        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7683		          [(match_operator:SI 3 "shift_operator"
7684		            [(match_operand:SI 4 "s_register_operand" "r")
7685		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
7686		           (match_operand:SI 2 "s_register_operand" "r")])
7687			 (const_int 0)))
7688   (clobber (match_scratch:SI 0 "=r"))]
7689  "TARGET_ARM"
7690  "%i1%?s\\t%0, %2, %4%S3"
7691  [(set_attr "conds" "set")
7692   (set_attr "shift" "4")
7693   ]
7694)
7695
7696(define_insn "*sub_shiftsi"
7697  [(set (match_operand:SI 0 "s_register_operand" "=r")
7698	(minus:SI (match_operand:SI 1 "s_register_operand" "r")
7699		  (match_operator:SI 2 "shift_operator"
7700		   [(match_operand:SI 3 "s_register_operand" "r")
7701		    (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7702  "TARGET_ARM"
7703  "sub%?\\t%0, %1, %3%S2"
7704  [(set_attr "predicable" "yes")
7705   (set_attr "shift" "3")
7706   ]
7707)
7708
7709(define_insn "*sub_shiftsi_compare0"
7710  [(set (reg:CC_NOOV CC_REGNUM)
7711	(compare:CC_NOOV
7712	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7713		   (match_operator:SI 2 "shift_operator"
7714		    [(match_operand:SI 3 "s_register_operand" "r")
7715		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7716	 (const_int 0)))
7717   (set (match_operand:SI 0 "s_register_operand" "=r")
7718	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7719						 (match_dup 4)])))]
7720  "TARGET_ARM"
7721  "sub%?s\\t%0, %1, %3%S2"
7722  [(set_attr "conds" "set")
7723   (set_attr "shift" "3") 
7724   ]
7725)
7726
7727(define_insn "*sub_shiftsi_compare0_scratch"
7728  [(set (reg:CC_NOOV CC_REGNUM)
7729	(compare:CC_NOOV
7730	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7731		   (match_operator:SI 2 "shift_operator"
7732		    [(match_operand:SI 3 "s_register_operand" "r")
7733		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7734	 (const_int 0)))
7735   (clobber (match_scratch:SI 0 "=r"))]
7736  "TARGET_ARM"
7737  "sub%?s\\t%0, %1, %3%S2"
7738  [(set_attr "conds" "set")
7739   (set_attr "shift" "3") 
7740   ]
7741)
7742
7743
7744
7745(define_insn "*and_scc"
7746  [(set (match_operand:SI 0 "s_register_operand" "=r")
7747	(and:SI (match_operator:SI 1 "arm_comparison_operator"
7748		 [(match_operand 3 "cc_register" "") (const_int 0)])
7749		(match_operand:SI 2 "s_register_operand" "r")))]
7750  "TARGET_ARM"
7751  "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7752  [(set_attr "conds" "use")
7753   (set_attr "length" "8")]
7754)
7755
7756(define_insn "*ior_scc"
7757  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7758	(ior:SI (match_operator:SI 2 "arm_comparison_operator"
7759		 [(match_operand 3 "cc_register" "") (const_int 0)])
7760		(match_operand:SI 1 "s_register_operand" "0,?r")))]
7761  "TARGET_ARM"
7762  "@
7763   orr%d2\\t%0, %1, #1
7764   mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7765  [(set_attr "conds" "use")
7766   (set_attr "length" "4,8")]
7767)
7768
7769(define_insn "*compare_scc"
7770  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7771	(match_operator:SI 1 "arm_comparison_operator"
7772	 [(match_operand:SI 2 "s_register_operand" "r,r")
7773	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7774   (clobber (reg:CC CC_REGNUM))]
7775  "TARGET_ARM"
7776  "*
7777    if (operands[3] == const0_rtx)
7778      {
7779	if (GET_CODE (operands[1]) == LT)
7780	  return \"mov\\t%0, %2, lsr #31\";
7781
7782	if (GET_CODE (operands[1]) == GE)
7783	  return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7784
7785	if (GET_CODE (operands[1]) == EQ)
7786	  return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
7787      }
7788
7789    if (GET_CODE (operands[1]) == NE)
7790      {
7791        if (which_alternative == 1)
7792	  return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7793        return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7794      }
7795    if (which_alternative == 1)
7796      output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7797    else
7798      output_asm_insn (\"cmp\\t%2, %3\", operands);
7799    return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7800  "
7801  [(set_attr "conds" "clob")
7802   (set_attr "length" "12")]
7803)
7804
7805(define_insn "*cond_move"
7806  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7807	(if_then_else:SI (match_operator 3 "equality_operator"
7808			  [(match_operator 4 "arm_comparison_operator"
7809			    [(match_operand 5 "cc_register" "") (const_int 0)])
7810			   (const_int 0)])
7811			 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7812			 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7813  "TARGET_ARM"
7814  "*
7815    if (GET_CODE (operands[3]) == NE)
7816      {
7817        if (which_alternative != 1)
7818	  output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7819        if (which_alternative != 0)
7820	  output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7821        return \"\";
7822      }
7823    if (which_alternative != 0)
7824      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7825    if (which_alternative != 1)
7826      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7827    return \"\";
7828  "
7829  [(set_attr "conds" "use")
7830   (set_attr "length" "4,4,8")]
7831)
7832
7833(define_insn "*cond_arith"
7834  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7835        (match_operator:SI 5 "shiftable_operator" 
7836	 [(match_operator:SI 4 "arm_comparison_operator"
7837           [(match_operand:SI 2 "s_register_operand" "r,r")
7838	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7839          (match_operand:SI 1 "s_register_operand" "0,?r")]))
7840   (clobber (reg:CC CC_REGNUM))]
7841  "TARGET_ARM"
7842  "*
7843    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7844      return \"%i5\\t%0, %1, %2, lsr #31\";
7845
7846    output_asm_insn (\"cmp\\t%2, %3\", operands);
7847    if (GET_CODE (operands[5]) == AND)
7848      output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7849    else if (GET_CODE (operands[5]) == MINUS)
7850      output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7851    else if (which_alternative != 0)
7852      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7853    return \"%i5%d4\\t%0, %1, #1\";
7854  "
7855  [(set_attr "conds" "clob")
7856   (set_attr "length" "12")]
7857)
7858
7859(define_insn "*cond_sub"
7860  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7861        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7862		  (match_operator:SI 4 "arm_comparison_operator"
7863                   [(match_operand:SI 2 "s_register_operand" "r,r")
7864		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7865   (clobber (reg:CC CC_REGNUM))]
7866  "TARGET_ARM"
7867  "*
7868    output_asm_insn (\"cmp\\t%2, %3\", operands);
7869    if (which_alternative != 0)
7870      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7871    return \"sub%d4\\t%0, %1, #1\";
7872  "
7873  [(set_attr "conds" "clob")
7874   (set_attr "length" "8,12")]
7875)
7876
7877(define_insn "*cmp_ite0"
7878  [(set (match_operand 6 "dominant_cc_register" "")
7879	(compare
7880	 (if_then_else:SI
7881	  (match_operator 4 "arm_comparison_operator"
7882	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7883	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7884	  (match_operator:SI 5 "arm_comparison_operator"
7885	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7886	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7887	  (const_int 0))
7888	 (const_int 0)))]
7889  "TARGET_ARM"
7890  "*
7891  {
7892    static const char * const opcodes[4][2] =
7893    {
7894      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7895       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7896      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7897       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7898      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7899       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7900      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7901       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7902    };
7903    int swap =
7904      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7905
7906    return opcodes[which_alternative][swap];
7907  }"
7908  [(set_attr "conds" "set")
7909   (set_attr "length" "8")]
7910)
7911
7912(define_insn "*cmp_ite1"
7913  [(set (match_operand 6 "dominant_cc_register" "")
7914	(compare
7915	 (if_then_else:SI
7916	  (match_operator 4 "arm_comparison_operator"
7917	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7918	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7919	  (match_operator:SI 5 "arm_comparison_operator"
7920	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7921	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7922	  (const_int 1))
7923	 (const_int 0)))]
7924  "TARGET_ARM"
7925  "*
7926  {
7927    static const char * const opcodes[4][2] =
7928    {
7929      {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7930       \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7931      {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7932       \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7933      {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7934       \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7935      {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7936       \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7937    };
7938    int swap =
7939      comparison_dominates_p (GET_CODE (operands[5]),
7940			      reverse_condition (GET_CODE (operands[4])));
7941
7942    return opcodes[which_alternative][swap];
7943  }"
7944  [(set_attr "conds" "set")
7945   (set_attr "length" "8")]
7946)
7947
7948(define_insn "*cmp_and"
7949  [(set (match_operand 6 "dominant_cc_register" "")
7950	(compare
7951	 (and:SI
7952	  (match_operator 4 "arm_comparison_operator"
7953	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7954	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7955	  (match_operator:SI 5 "arm_comparison_operator"
7956	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7957	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7958	 (const_int 0)))]
7959  "TARGET_ARM"
7960  "*
7961  {
7962    static const char *const opcodes[4][2] =
7963    {
7964      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7965       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7966      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7967       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7968      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7969       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7970      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7971       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7972    };
7973    int swap =
7974      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7975
7976    return opcodes[which_alternative][swap];
7977  }"
7978  [(set_attr "conds" "set")
7979   (set_attr "predicable" "no")
7980   (set_attr "length" "8")]
7981)
7982
7983(define_insn "*cmp_ior"
7984  [(set (match_operand 6 "dominant_cc_register" "")
7985	(compare
7986	 (ior:SI
7987	  (match_operator 4 "arm_comparison_operator"
7988	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7989	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7990	  (match_operator:SI 5 "arm_comparison_operator"
7991	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7992	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7993	 (const_int 0)))]
7994  "TARGET_ARM"
7995  "*
7996{
7997  static const char *const opcodes[4][2] =
7998  {
7999    {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8000     \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8001    {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8002     \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8003    {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8004     \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8005    {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8006     \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8007  };
8008  int swap =
8009    comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8010
8011  return opcodes[which_alternative][swap];
8012}
8013"
8014  [(set_attr "conds" "set")
8015   (set_attr "length" "8")]
8016)
8017
8018(define_insn_and_split "*ior_scc_scc"
8019  [(set (match_operand:SI 0 "s_register_operand" "=r")
8020	(ior:SI (match_operator:SI 3 "arm_comparison_operator"
8021		 [(match_operand:SI 1 "s_register_operand" "r")
8022		  (match_operand:SI 2 "arm_add_operand" "rIL")])
8023		(match_operator:SI 6 "arm_comparison_operator"
8024		 [(match_operand:SI 4 "s_register_operand" "r")
8025		  (match_operand:SI 5 "arm_add_operand" "rIL")])))
8026   (clobber (reg:CC CC_REGNUM))]
8027  "TARGET_ARM
8028   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8029       != CCmode)"
8030  "#"
8031  "TARGET_ARM && reload_completed"
8032  [(set (match_dup 7)
8033	(compare
8034	 (ior:SI
8035	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8036	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8037	 (const_int 0)))
8038   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8039  "operands[7]
8040     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8041						  DOM_CC_X_OR_Y),
8042		    CC_REGNUM);"
8043  [(set_attr "conds" "clob")
8044   (set_attr "length" "16")])
8045
8046; If the above pattern is followed by a CMP insn, then the compare is 
8047; redundant, since we can rework the conditional instruction that follows.
8048(define_insn_and_split "*ior_scc_scc_cmp"
8049  [(set (match_operand 0 "dominant_cc_register" "")
8050	(compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8051			  [(match_operand:SI 1 "s_register_operand" "r")
8052			   (match_operand:SI 2 "arm_add_operand" "rIL")])
8053			 (match_operator:SI 6 "arm_comparison_operator"
8054			  [(match_operand:SI 4 "s_register_operand" "r")
8055			   (match_operand:SI 5 "arm_add_operand" "rIL")]))
8056		 (const_int 0)))
8057   (set (match_operand:SI 7 "s_register_operand" "=r")
8058	(ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8059		(match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8060  "TARGET_ARM"
8061  "#"
8062  "TARGET_ARM && reload_completed"
8063  [(set (match_dup 0)
8064	(compare
8065	 (ior:SI
8066	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8067	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8068	 (const_int 0)))
8069   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8070  ""
8071  [(set_attr "conds" "set")
8072   (set_attr "length" "16")])
8073
8074(define_insn_and_split "*and_scc_scc"
8075  [(set (match_operand:SI 0 "s_register_operand" "=r")
8076	(and:SI (match_operator:SI 3 "arm_comparison_operator"
8077		 [(match_operand:SI 1 "s_register_operand" "r")
8078		  (match_operand:SI 2 "arm_add_operand" "rIL")])
8079		(match_operator:SI 6 "arm_comparison_operator"
8080		 [(match_operand:SI 4 "s_register_operand" "r")
8081		  (match_operand:SI 5 "arm_add_operand" "rIL")])))
8082   (clobber (reg:CC CC_REGNUM))]
8083  "TARGET_ARM
8084   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8085       != CCmode)"
8086  "#"
8087  "TARGET_ARM && reload_completed
8088   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8089       != CCmode)"
8090  [(set (match_dup 7)
8091	(compare
8092	 (and:SI
8093	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8094	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8095	 (const_int 0)))
8096   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8097  "operands[7]
8098     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8099						  DOM_CC_X_AND_Y),
8100		    CC_REGNUM);"
8101  [(set_attr "conds" "clob")
8102   (set_attr "length" "16")])
8103
8104; If the above pattern is followed by a CMP insn, then the compare is 
8105; redundant, since we can rework the conditional instruction that follows.
8106(define_insn_and_split "*and_scc_scc_cmp"
8107  [(set (match_operand 0 "dominant_cc_register" "")
8108	(compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8109			  [(match_operand:SI 1 "s_register_operand" "r")
8110			   (match_operand:SI 2 "arm_add_operand" "rIL")])
8111			 (match_operator:SI 6 "arm_comparison_operator"
8112			  [(match_operand:SI 4 "s_register_operand" "r")
8113			   (match_operand:SI 5 "arm_add_operand" "rIL")]))
8114		 (const_int 0)))
8115   (set (match_operand:SI 7 "s_register_operand" "=r")
8116	(and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8117		(match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8118  "TARGET_ARM"
8119  "#"
8120  "TARGET_ARM && reload_completed"
8121  [(set (match_dup 0)
8122	(compare
8123	 (and:SI
8124	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8125	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8126	 (const_int 0)))
8127   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8128  ""
8129  [(set_attr "conds" "set")
8130   (set_attr "length" "16")])
8131
8132;; If there is no dominance in the comparison, then we can still save an
8133;; instruction in the AND case, since we can know that the second compare
8134;; need only zero the value if false (if true, then the value is already
8135;; correct).
8136(define_insn_and_split "*and_scc_scc_nodom"
8137  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8138	(and:SI (match_operator:SI 3 "arm_comparison_operator"
8139		 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8140		  (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8141		(match_operator:SI 6 "arm_comparison_operator"
8142		 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8143		  (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8144   (clobber (reg:CC CC_REGNUM))]
8145  "TARGET_ARM
8146   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8147       == CCmode)"
8148  "#"
8149  "TARGET_ARM && reload_completed"
8150  [(parallel [(set (match_dup 0)
8151		   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8152	      (clobber (reg:CC CC_REGNUM))])
8153   (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8154   (set (match_dup 0)
8155	(if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8156			 (match_dup 0)
8157			 (const_int 0)))]
8158  "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8159					      operands[4], operands[5]),
8160			      CC_REGNUM);
8161   operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8162				  operands[5]);"
8163  [(set_attr "conds" "clob")
8164   (set_attr "length" "20")])
8165
8166(define_split
8167  [(set (reg:CC_NOOV CC_REGNUM)
8168	(compare:CC_NOOV (ior:SI
8169			  (and:SI (match_operand:SI 0 "s_register_operand" "")
8170				  (const_int 1))
8171			  (match_operator:SI 1 "comparison_operator"
8172			   [(match_operand:SI 2 "s_register_operand" "")
8173			    (match_operand:SI 3 "arm_add_operand" "")]))
8174			 (const_int 0)))
8175   (clobber (match_operand:SI 4 "s_register_operand" ""))]
8176  "TARGET_ARM"
8177  [(set (match_dup 4)
8178	(ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8179		(match_dup 0)))
8180   (set (reg:CC_NOOV CC_REGNUM)
8181	(compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8182			 (const_int 0)))]
8183  "")
8184
8185(define_split
8186  [(set (reg:CC_NOOV CC_REGNUM)
8187	(compare:CC_NOOV (ior:SI
8188			  (match_operator:SI 1 "comparison_operator"
8189			   [(match_operand:SI 2 "s_register_operand" "")
8190			    (match_operand:SI 3 "arm_add_operand" "")])
8191			  (and:SI (match_operand:SI 0 "s_register_operand" "")
8192				  (const_int 1)))
8193			 (const_int 0)))
8194   (clobber (match_operand:SI 4 "s_register_operand" ""))]
8195  "TARGET_ARM"
8196  [(set (match_dup 4)
8197	(ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8198		(match_dup 0)))
8199   (set (reg:CC_NOOV CC_REGNUM)
8200	(compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8201			 (const_int 0)))]
8202  "")
8203
8204(define_insn "*negscc"
8205  [(set (match_operand:SI 0 "s_register_operand" "=r")
8206	(neg:SI (match_operator 3 "arm_comparison_operator"
8207		 [(match_operand:SI 1 "s_register_operand" "r")
8208		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8209   (clobber (reg:CC CC_REGNUM))]
8210  "TARGET_ARM"
8211  "*
8212  if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8213    return \"mov\\t%0, %1, asr #31\";
8214
8215  if (GET_CODE (operands[3]) == NE)
8216    return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8217
8218  if (GET_CODE (operands[3]) == GT)
8219    return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8220
8221  output_asm_insn (\"cmp\\t%1, %2\", operands);
8222  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8223  return \"mvn%d3\\t%0, #0\";
8224  "
8225  [(set_attr "conds" "clob")
8226   (set_attr "length" "12")]
8227)
8228
8229(define_insn "movcond"
8230  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8231	(if_then_else:SI
8232	 (match_operator 5 "arm_comparison_operator"
8233	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
8234	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8235	 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8236	 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8237   (clobber (reg:CC CC_REGNUM))]
8238  "TARGET_ARM"
8239  "*
8240  if (GET_CODE (operands[5]) == LT
8241      && (operands[4] == const0_rtx))
8242    {
8243      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8244	{
8245	  if (operands[2] == const0_rtx)
8246	    return \"and\\t%0, %1, %3, asr #31\";
8247	  return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8248	}
8249      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8250	{
8251	  if (operands[1] == const0_rtx)
8252	    return \"bic\\t%0, %2, %3, asr #31\";
8253	  return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8254	}
8255      /* The only case that falls through to here is when both ops 1 & 2
8256	 are constants.  */
8257    }
8258
8259  if (GET_CODE (operands[5]) == GE
8260      && (operands[4] == const0_rtx))
8261    {
8262      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8263	{
8264	  if (operands[2] == const0_rtx)
8265	    return \"bic\\t%0, %1, %3, asr #31\";
8266	  return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8267	}
8268      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8269	{
8270	  if (operands[1] == const0_rtx)
8271	    return \"and\\t%0, %2, %3, asr #31\";
8272	  return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8273	}
8274      /* The only case that falls through to here is when both ops 1 & 2
8275	 are constants.  */
8276    }
8277  if (GET_CODE (operands[4]) == CONST_INT
8278      && !const_ok_for_arm (INTVAL (operands[4])))
8279    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8280  else
8281    output_asm_insn (\"cmp\\t%3, %4\", operands);
8282  if (which_alternative != 0)
8283    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8284  if (which_alternative != 1)
8285    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8286  return \"\";
8287  "
8288  [(set_attr "conds" "clob")
8289   (set_attr "length" "8,8,12")]
8290)
8291
8292(define_insn "*ifcompare_plus_move"
8293  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8294	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8295			  [(match_operand:SI 4 "s_register_operand" "r,r")
8296			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8297			 (plus:SI
8298			  (match_operand:SI 2 "s_register_operand" "r,r")
8299			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8300			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8301   (clobber (reg:CC CC_REGNUM))]
8302  "TARGET_ARM"
8303  "#"
8304  [(set_attr "conds" "clob")
8305   (set_attr "length" "8,12")]
8306)
8307
8308(define_insn "*if_plus_move"
8309  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8310	(if_then_else:SI
8311	 (match_operator 4 "arm_comparison_operator"
8312	  [(match_operand 5 "cc_register" "") (const_int 0)])
8313	 (plus:SI
8314	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8315	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8316	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8317  "TARGET_ARM"
8318  "@
8319   add%d4\\t%0, %2, %3
8320   sub%d4\\t%0, %2, #%n3
8321   add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8322   sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8323  [(set_attr "conds" "use")
8324   (set_attr "length" "4,4,8,8")
8325   (set_attr "type" "*,*,*,*")]
8326)
8327
8328(define_insn "*ifcompare_move_plus"
8329  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8330	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8331			  [(match_operand:SI 4 "s_register_operand" "r,r")
8332			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8333			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8334			 (plus:SI
8335			  (match_operand:SI 2 "s_register_operand" "r,r")
8336			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8337   (clobber (reg:CC CC_REGNUM))]
8338  "TARGET_ARM"
8339  "#"
8340  [(set_attr "conds" "clob")
8341   (set_attr "length" "8,12")]
8342)
8343
8344(define_insn "*if_move_plus"
8345  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8346	(if_then_else:SI
8347	 (match_operator 4 "arm_comparison_operator"
8348	  [(match_operand 5 "cc_register" "") (const_int 0)])
8349	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8350	 (plus:SI
8351	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8352	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8353  "TARGET_ARM"
8354  "@
8355   add%D4\\t%0, %2, %3
8356   sub%D4\\t%0, %2, #%n3
8357   add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8358   sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8359  [(set_attr "conds" "use")
8360   (set_attr "length" "4,4,8,8")
8361   (set_attr "type" "*,*,*,*")]
8362)
8363
8364(define_insn "*ifcompare_arith_arith"
8365  [(set (match_operand:SI 0 "s_register_operand" "=r")
8366	(if_then_else:SI (match_operator 9 "arm_comparison_operator"
8367			  [(match_operand:SI 5 "s_register_operand" "r")
8368			   (match_operand:SI 6 "arm_add_operand" "rIL")])
8369			 (match_operator:SI 8 "shiftable_operator"
8370			  [(match_operand:SI 1 "s_register_operand" "r")
8371			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
8372			 (match_operator:SI 7 "shiftable_operator"
8373			  [(match_operand:SI 3 "s_register_operand" "r")
8374			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8375   (clobber (reg:CC CC_REGNUM))]
8376  "TARGET_ARM"
8377  "#"
8378  [(set_attr "conds" "clob")
8379   (set_attr "length" "12")]
8380)
8381
8382(define_insn "*if_arith_arith"
8383  [(set (match_operand:SI 0 "s_register_operand" "=r")
8384	(if_then_else:SI (match_operator 5 "arm_comparison_operator"
8385			  [(match_operand 8 "cc_register" "") (const_int 0)])
8386			 (match_operator:SI 6 "shiftable_operator"
8387			  [(match_operand:SI 1 "s_register_operand" "r")
8388			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
8389			 (match_operator:SI 7 "shiftable_operator"
8390			  [(match_operand:SI 3 "s_register_operand" "r")
8391			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8392  "TARGET_ARM"
8393  "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8394  [(set_attr "conds" "use")
8395   (set_attr "length" "8")]
8396)
8397
8398(define_insn "*ifcompare_arith_move"
8399  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8400	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8401			  [(match_operand:SI 2 "s_register_operand" "r,r")
8402			   (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8403			 (match_operator:SI 7 "shiftable_operator"
8404			  [(match_operand:SI 4 "s_register_operand" "r,r")
8405			   (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8406			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8407   (clobber (reg:CC CC_REGNUM))]
8408  "TARGET_ARM"
8409  "*
8410  /* If we have an operation where (op x 0) is the identity operation and
8411     the conditional operator is LT or GE and we are comparing against zero and
8412     everything is in registers then we can do this in two instructions.  */
8413  if (operands[3] == const0_rtx
8414      && GET_CODE (operands[7]) != AND
8415      && GET_CODE (operands[5]) == REG
8416      && GET_CODE (operands[1]) == REG 
8417      && REGNO (operands[1]) == REGNO (operands[4])
8418      && REGNO (operands[4]) != REGNO (operands[0]))
8419    {
8420      if (GET_CODE (operands[6]) == LT)
8421	return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8422      else if (GET_CODE (operands[6]) == GE)
8423	return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8424    }
8425  if (GET_CODE (operands[3]) == CONST_INT
8426      && !const_ok_for_arm (INTVAL (operands[3])))
8427    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8428  else
8429    output_asm_insn (\"cmp\\t%2, %3\", operands);
8430  output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8431  if (which_alternative != 0)
8432    return \"mov%D6\\t%0, %1\";
8433  return \"\";
8434  "
8435  [(set_attr "conds" "clob")
8436   (set_attr "length" "8,12")]
8437)
8438
8439(define_insn "*if_arith_move"
8440  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8441	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
8442			  [(match_operand 6 "cc_register" "") (const_int 0)])
8443			 (match_operator:SI 5 "shiftable_operator"
8444			  [(match_operand:SI 2 "s_register_operand" "r,r")
8445			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8446			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8447  "TARGET_ARM"
8448  "@
8449   %I5%d4\\t%0, %2, %3
8450   %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8451  [(set_attr "conds" "use")
8452   (set_attr "length" "4,8")
8453   (set_attr "type" "*,*")]
8454)
8455
8456(define_insn "*ifcompare_move_arith"
8457  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8458	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8459			  [(match_operand:SI 4 "s_register_operand" "r,r")
8460			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8461			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8462			 (match_operator:SI 7 "shiftable_operator"
8463			  [(match_operand:SI 2 "s_register_operand" "r,r")
8464			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8465   (clobber (reg:CC CC_REGNUM))]
8466  "TARGET_ARM"
8467  "*
8468  /* If we have an operation where (op x 0) is the identity operation and
8469     the conditional operator is LT or GE and we are comparing against zero and
8470     everything is in registers then we can do this in two instructions */
8471  if (operands[5] == const0_rtx
8472      && GET_CODE (operands[7]) != AND
8473      && GET_CODE (operands[3]) == REG
8474      && GET_CODE (operands[1]) == REG 
8475      && REGNO (operands[1]) == REGNO (operands[2])
8476      && REGNO (operands[2]) != REGNO (operands[0]))
8477    {
8478      if (GET_CODE (operands[6]) == GE)
8479	return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8480      else if (GET_CODE (operands[6]) == LT)
8481	return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8482    }
8483
8484  if (GET_CODE (operands[5]) == CONST_INT
8485      && !const_ok_for_arm (INTVAL (operands[5])))
8486    output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8487  else
8488    output_asm_insn (\"cmp\\t%4, %5\", operands);
8489
8490  if (which_alternative != 0)
8491    output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8492  return \"%I7%D6\\t%0, %2, %3\";
8493  "
8494  [(set_attr "conds" "clob")
8495   (set_attr "length" "8,12")]
8496)
8497
8498(define_insn "*if_move_arith"
8499  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8500	(if_then_else:SI
8501	 (match_operator 4 "arm_comparison_operator"
8502	  [(match_operand 6 "cc_register" "") (const_int 0)])
8503	 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8504	 (match_operator:SI 5 "shiftable_operator"
8505	  [(match_operand:SI 2 "s_register_operand" "r,r")
8506	   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8507  "TARGET_ARM"
8508  "@
8509   %I5%D4\\t%0, %2, %3
8510   %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8511  [(set_attr "conds" "use")
8512   (set_attr "length" "4,8")
8513   (set_attr "type" "*,*")]
8514)
8515
8516(define_insn "*ifcompare_move_not"
8517  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8518	(if_then_else:SI
8519	 (match_operator 5 "arm_comparison_operator"
8520	  [(match_operand:SI 3 "s_register_operand" "r,r")
8521	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8522	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8523	 (not:SI
8524	  (match_operand:SI 2 "s_register_operand" "r,r"))))
8525   (clobber (reg:CC CC_REGNUM))]
8526  "TARGET_ARM"
8527  "#"
8528  [(set_attr "conds" "clob")
8529   (set_attr "length" "8,12")]
8530)
8531
8532(define_insn "*if_move_not"
8533  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8534	(if_then_else:SI
8535	 (match_operator 4 "arm_comparison_operator"
8536	  [(match_operand 3 "cc_register" "") (const_int 0)])
8537	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8538	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8539  "TARGET_ARM"
8540  "@
8541   mvn%D4\\t%0, %2
8542   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8543   mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8544  [(set_attr "conds" "use")
8545   (set_attr "length" "4,8,8")]
8546)
8547
8548(define_insn "*ifcompare_not_move"
8549  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8550	(if_then_else:SI 
8551	 (match_operator 5 "arm_comparison_operator"
8552	  [(match_operand:SI 3 "s_register_operand" "r,r")
8553	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8554	 (not:SI
8555	  (match_operand:SI 2 "s_register_operand" "r,r"))
8556	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8557   (clobber (reg:CC CC_REGNUM))]
8558  "TARGET_ARM"
8559  "#"
8560  [(set_attr "conds" "clob")
8561   (set_attr "length" "8,12")]
8562)
8563
8564(define_insn "*if_not_move"
8565  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8566	(if_then_else:SI
8567	 (match_operator 4 "arm_comparison_operator"
8568	  [(match_operand 3 "cc_register" "") (const_int 0)])
8569	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8570	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8571  "TARGET_ARM"
8572  "@
8573   mvn%d4\\t%0, %2
8574   mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8575   mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8576  [(set_attr "conds" "use")
8577   (set_attr "length" "4,8,8")]
8578)
8579
8580(define_insn "*ifcompare_shift_move"
8581  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8582	(if_then_else:SI
8583	 (match_operator 6 "arm_comparison_operator"
8584	  [(match_operand:SI 4 "s_register_operand" "r,r")
8585	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8586	 (match_operator:SI 7 "shift_operator"
8587	  [(match_operand:SI 2 "s_register_operand" "r,r")
8588	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8589	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8590   (clobber (reg:CC CC_REGNUM))]
8591  "TARGET_ARM"
8592  "#"
8593  [(set_attr "conds" "clob")
8594   (set_attr "length" "8,12")]
8595)
8596
8597(define_insn "*if_shift_move"
8598  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8599	(if_then_else:SI
8600	 (match_operator 5 "arm_comparison_operator"
8601	  [(match_operand 6 "cc_register" "") (const_int 0)])
8602	 (match_operator:SI 4 "shift_operator"
8603	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
8604	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8605	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8606  "TARGET_ARM"
8607  "@
8608   mov%d5\\t%0, %2%S4
8609   mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8610   mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8611  [(set_attr "conds" "use")
8612   (set_attr "shift" "2")
8613   (set_attr "length" "4,8,8")]
8614)
8615
8616(define_insn "*ifcompare_move_shift"
8617  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8618	(if_then_else:SI
8619	 (match_operator 6 "arm_comparison_operator"
8620	  [(match_operand:SI 4 "s_register_operand" "r,r")
8621	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8622	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8623	 (match_operator:SI 7 "shift_operator"
8624	  [(match_operand:SI 2 "s_register_operand" "r,r")
8625	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8626   (clobber (reg:CC CC_REGNUM))]
8627  "TARGET_ARM"
8628  "#"
8629  [(set_attr "conds" "clob")
8630   (set_attr "length" "8,12")]
8631)
8632
8633(define_insn "*if_move_shift"
8634  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8635	(if_then_else:SI
8636	 (match_operator 5 "arm_comparison_operator"
8637	  [(match_operand 6 "cc_register" "") (const_int 0)])
8638	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8639	 (match_operator:SI 4 "shift_operator"
8640	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
8641	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8642  "TARGET_ARM"
8643  "@
8644   mov%D5\\t%0, %2%S4
8645   mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8646   mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8647  [(set_attr "conds" "use")
8648   (set_attr "shift" "2")
8649   (set_attr "length" "4,8,8")]
8650)
8651
8652(define_insn "*ifcompare_shift_shift"
8653  [(set (match_operand:SI 0 "s_register_operand" "=r")
8654	(if_then_else:SI
8655	 (match_operator 7 "arm_comparison_operator"
8656	  [(match_operand:SI 5 "s_register_operand" "r")
8657	   (match_operand:SI 6 "arm_add_operand" "rIL")])
8658	 (match_operator:SI 8 "shift_operator"
8659	  [(match_operand:SI 1 "s_register_operand" "r")
8660	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
8661	 (match_operator:SI 9 "shift_operator"
8662	  [(match_operand:SI 3 "s_register_operand" "r")
8663	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8664   (clobber (reg:CC CC_REGNUM))]
8665  "TARGET_ARM"
8666  "#"
8667  [(set_attr "conds" "clob")
8668   (set_attr "length" "12")]
8669)
8670
8671(define_insn "*if_shift_shift"
8672  [(set (match_operand:SI 0 "s_register_operand" "=r")
8673	(if_then_else:SI
8674	 (match_operator 5 "arm_comparison_operator"
8675	  [(match_operand 8 "cc_register" "") (const_int 0)])
8676	 (match_operator:SI 6 "shift_operator"
8677	  [(match_operand:SI 1 "s_register_operand" "r")
8678	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
8679	 (match_operator:SI 7 "shift_operator"
8680	  [(match_operand:SI 3 "s_register_operand" "r")
8681	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8682  "TARGET_ARM"
8683  "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8684  [(set_attr "conds" "use")
8685   (set_attr "shift" "1")
8686   (set_attr "length" "8")]
8687)
8688
8689(define_insn "*ifcompare_not_arith"
8690  [(set (match_operand:SI 0 "s_register_operand" "=r")
8691	(if_then_else:SI
8692	 (match_operator 6 "arm_comparison_operator"
8693	  [(match_operand:SI 4 "s_register_operand" "r")
8694	   (match_operand:SI 5 "arm_add_operand" "rIL")])
8695	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8696	 (match_operator:SI 7 "shiftable_operator"
8697	  [(match_operand:SI 2 "s_register_operand" "r")
8698	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8699   (clobber (reg:CC CC_REGNUM))]
8700  "TARGET_ARM"
8701  "#"
8702  [(set_attr "conds" "clob")
8703   (set_attr "length" "12")]
8704)
8705
8706(define_insn "*if_not_arith"
8707  [(set (match_operand:SI 0 "s_register_operand" "=r")
8708	(if_then_else:SI
8709	 (match_operator 5 "arm_comparison_operator"
8710	  [(match_operand 4 "cc_register" "") (const_int 0)])
8711	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8712	 (match_operator:SI 6 "shiftable_operator"
8713	  [(match_operand:SI 2 "s_register_operand" "r")
8714	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8715  "TARGET_ARM"
8716  "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8717  [(set_attr "conds" "use")
8718   (set_attr "length" "8")]
8719)
8720
8721(define_insn "*ifcompare_arith_not"
8722  [(set (match_operand:SI 0 "s_register_operand" "=r")
8723	(if_then_else:SI
8724	 (match_operator 6 "arm_comparison_operator"
8725	  [(match_operand:SI 4 "s_register_operand" "r")
8726	   (match_operand:SI 5 "arm_add_operand" "rIL")])
8727	 (match_operator:SI 7 "shiftable_operator"
8728	  [(match_operand:SI 2 "s_register_operand" "r")
8729	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
8730	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8731   (clobber (reg:CC CC_REGNUM))]
8732  "TARGET_ARM"
8733  "#"
8734  [(set_attr "conds" "clob")
8735   (set_attr "length" "12")]
8736)
8737
8738(define_insn "*if_arith_not"
8739  [(set (match_operand:SI 0 "s_register_operand" "=r")
8740	(if_then_else:SI
8741	 (match_operator 5 "arm_comparison_operator"
8742	  [(match_operand 4 "cc_register" "") (const_int 0)])
8743	 (match_operator:SI 6 "shiftable_operator"
8744	  [(match_operand:SI 2 "s_register_operand" "r")
8745	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
8746	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8747  "TARGET_ARM"
8748  "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8749  [(set_attr "conds" "use")
8750   (set_attr "length" "8")]
8751)
8752
8753(define_insn "*ifcompare_neg_move"
8754  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8755	(if_then_else:SI
8756	 (match_operator 5 "arm_comparison_operator"
8757	  [(match_operand:SI 3 "s_register_operand" "r,r")
8758	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8759	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8760	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8761   (clobber (reg:CC CC_REGNUM))]
8762  "TARGET_ARM"
8763  "#"
8764  [(set_attr "conds" "clob")
8765   (set_attr "length" "8,12")]
8766)
8767
8768(define_insn "*if_neg_move"
8769  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8770	(if_then_else:SI
8771	 (match_operator 4 "arm_comparison_operator"
8772	  [(match_operand 3 "cc_register" "") (const_int 0)])
8773	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8774	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8775  "TARGET_ARM"
8776  "@
8777   rsb%d4\\t%0, %2, #0
8778   mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8779   mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8780  [(set_attr "conds" "use")
8781   (set_attr "length" "4,8,8")]
8782)
8783
8784(define_insn "*ifcompare_move_neg"
8785  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8786	(if_then_else:SI
8787	 (match_operator 5 "arm_comparison_operator"
8788	  [(match_operand:SI 3 "s_register_operand" "r,r")
8789	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8790	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8791	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8792   (clobber (reg:CC CC_REGNUM))]
8793  "TARGET_ARM"
8794  "#"
8795  [(set_attr "conds" "clob")
8796   (set_attr "length" "8,12")]
8797)
8798
8799(define_insn "*if_move_neg"
8800  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8801	(if_then_else:SI
8802	 (match_operator 4 "arm_comparison_operator"
8803	  [(match_operand 3 "cc_register" "") (const_int 0)])
8804	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8805	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8806  "TARGET_ARM"
8807  "@
8808   rsb%D4\\t%0, %2, #0
8809   mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8810   mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8811  [(set_attr "conds" "use")
8812   (set_attr "length" "4,8,8")]
8813)
8814
8815(define_insn "*arith_adjacentmem"
8816  [(set (match_operand:SI 0 "s_register_operand" "=r")
8817	(match_operator:SI 1 "shiftable_operator"
8818	 [(match_operand:SI 2 "memory_operand" "m")
8819	  (match_operand:SI 3 "memory_operand" "m")]))
8820   (clobber (match_scratch:SI 4 "=r"))]
8821  "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8822  "*
8823  {
8824    rtx ldm[3];
8825    rtx arith[4];
8826    int val1 = 0, val2 = 0;
8827
8828    if (REGNO (operands[0]) > REGNO (operands[4]))
8829      {
8830	ldm[1] = operands[4];
8831	ldm[2] = operands[0];
8832      }
8833    else
8834      {
8835	ldm[1] = operands[0];
8836	ldm[2] = operands[4];
8837      }
8838    if (GET_CODE (XEXP (operands[2], 0)) != REG)
8839      val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8840    if (GET_CODE (XEXP (operands[3], 0)) != REG)
8841      val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8842    arith[0] = operands[0];
8843    arith[3] = operands[1];
8844    if (val1 < val2)
8845      {
8846	arith[1] = ldm[1];
8847	arith[2] = ldm[2];
8848      }
8849    else
8850      {
8851	arith[1] = ldm[2];
8852	arith[2] = ldm[1];
8853      }
8854   if (val1 && val2)
8855      {
8856	rtx ops[3];
8857	ldm[0] = ops[0] = operands[4];
8858	ops[1] = XEXP (XEXP (operands[2], 0), 0);
8859	ops[2] = XEXP (XEXP (operands[2], 0), 1);
8860	output_add_immediate (ops);
8861	if (val1 < val2)
8862	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8863	else
8864	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8865      }
8866    else if (val1)
8867      {
8868	ldm[0] = XEXP (operands[3], 0);
8869	if (val1 < val2)
8870	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8871	else
8872	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8873      }
8874    else
8875      {
8876	ldm[0] = XEXP (operands[2], 0);
8877	if (val1 < val2)
8878	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8879	else
8880	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8881      }
8882    output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8883    return \"\";
8884  }"
8885  [(set_attr "length" "12")
8886   (set_attr "predicable" "yes")
8887   (set_attr "type" "load")]
8888)
8889
8890;; the arm can support extended pre-inc instructions
8891
8892;; In all these cases, we use operands 0 and 1 for the register being
8893;; incremented because those are the operands that local-alloc will
8894;; tie and these are the pair most likely to be tieable (and the ones
8895;; that will benefit the most).
8896
8897;; We reject the frame pointer if it occurs anywhere in these patterns since
8898;; elimination will cause too many headaches.
8899
8900(define_insn "*strqi_preinc"
8901  [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8902			 (match_operand:SI 2 "index_operand" "rJ")))
8903	(match_operand:QI 3 "s_register_operand" "r"))
8904   (set (match_operand:SI 0 "s_register_operand" "=r")
8905	(plus:SI (match_dup 1) (match_dup 2)))]
8906  "TARGET_ARM
8907   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8908   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8909   && (GET_CODE (operands[2]) != REG
8910       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8911  "str%?b\\t%3, [%0, %2]!"
8912  [(set_attr "type" "store1")
8913   (set_attr "predicable" "yes")]
8914)
8915
8916(define_insn "*strqi_predec"
8917  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8918			  (match_operand:SI 2 "s_register_operand" "r")))
8919	(match_operand:QI 3 "s_register_operand" "r"))
8920   (set (match_operand:SI 0 "s_register_operand" "=r")
8921	(minus:SI (match_dup 1) (match_dup 2)))]
8922  "TARGET_ARM
8923   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8924   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8925   && (GET_CODE (operands[2]) != REG
8926       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8927  "str%?b\\t%3, [%0, -%2]!"
8928  [(set_attr "type" "store1")
8929   (set_attr "predicable" "yes")]
8930)
8931
8932(define_insn "*loadqi_preinc"
8933  [(set (match_operand:QI 3 "s_register_operand" "=r")
8934	(mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8935			 (match_operand:SI 2 "index_operand" "rJ"))))
8936   (set (match_operand:SI 0 "s_register_operand" "=r")
8937	(plus:SI (match_dup 1) (match_dup 2)))]
8938  "TARGET_ARM
8939   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8940   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8941   && (GET_CODE (operands[2]) != REG
8942       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8943  "ldr%?b\\t%3, [%0, %2]!"
8944  [(set_attr "type" "load")
8945   (set_attr "predicable" "yes")]
8946)
8947
8948(define_insn "*loadqi_predec"
8949  [(set (match_operand:QI 3 "s_register_operand" "=r")
8950	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8951			  (match_operand:SI 2 "s_register_operand" "r"))))
8952   (set (match_operand:SI 0 "s_register_operand" "=r")
8953	(minus:SI (match_dup 1) (match_dup 2)))]
8954  "TARGET_ARM
8955   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8956   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8957   && (GET_CODE (operands[2]) != REG
8958       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8959  "ldr%?b\\t%3, [%0, -%2]!"
8960  [(set_attr "type" "load")
8961   (set_attr "predicable" "yes")]
8962)
8963
8964(define_insn "*loadqisi_preinc"
8965  [(set (match_operand:SI 3 "s_register_operand" "=r")
8966	(zero_extend:SI
8967	 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8968			  (match_operand:SI 2 "index_operand" "rJ")))))
8969   (set (match_operand:SI 0 "s_register_operand" "=r")
8970	(plus:SI (match_dup 1) (match_dup 2)))]
8971  "TARGET_ARM
8972   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8973   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8974   && (GET_CODE (operands[2]) != REG
8975       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8976  "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8977  [(set_attr "type" "load")
8978   (set_attr "predicable" "yes")]
8979)
8980
8981(define_insn "*loadqisi_predec"
8982  [(set (match_operand:SI 3 "s_register_operand" "=r")
8983	(zero_extend:SI
8984	 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8985			   (match_operand:SI 2 "s_register_operand" "r")))))
8986   (set (match_operand:SI 0 "s_register_operand" "=r")
8987	(minus:SI (match_dup 1) (match_dup 2)))]
8988  "TARGET_ARM
8989   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8990   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8991   && (GET_CODE (operands[2]) != REG
8992       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8993  "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8994  [(set_attr "type" "load")
8995   (set_attr "predicable" "yes")]
8996)
8997
8998(define_insn "*strsi_preinc"
8999  [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9000			 (match_operand:SI 2 "index_operand" "rJ")))
9001	(match_operand:SI 3 "s_register_operand" "r"))
9002   (set (match_operand:SI 0 "s_register_operand" "=r")
9003	(plus:SI (match_dup 1) (match_dup 2)))]
9004  "TARGET_ARM
9005   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9006   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9007   && (GET_CODE (operands[2]) != REG
9008       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9009  "str%?\\t%3, [%0, %2]!"
9010  [(set_attr "type" "store1")
9011   (set_attr "predicable" "yes")]
9012)
9013
9014(define_insn "*strsi_predec"
9015  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9016			  (match_operand:SI 2 "s_register_operand" "r")))
9017	(match_operand:SI 3 "s_register_operand" "r"))
9018   (set (match_operand:SI 0 "s_register_operand" "=r")
9019	(minus:SI (match_dup 1) (match_dup 2)))]
9020  "TARGET_ARM
9021   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9022   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9023   && (GET_CODE (operands[2]) != REG
9024       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9025  "str%?\\t%3, [%0, -%2]!"
9026  [(set_attr "type" "store1")
9027   (set_attr "predicable" "yes")]
9028)
9029
9030(define_insn "*loadsi_preinc"
9031  [(set (match_operand:SI 3 "s_register_operand" "=r")
9032	(mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9033			 (match_operand:SI 2 "index_operand" "rJ"))))
9034   (set (match_operand:SI 0 "s_register_operand" "=r")
9035	(plus:SI (match_dup 1) (match_dup 2)))]
9036  "TARGET_ARM
9037   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9038   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9039   && (GET_CODE (operands[2]) != REG
9040       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9041  "ldr%?\\t%3, [%0, %2]!"
9042  [(set_attr "type" "load")
9043   (set_attr "predicable" "yes")]
9044)
9045
9046(define_insn "*loadsi_predec"
9047  [(set (match_operand:SI 3 "s_register_operand" "=r")
9048	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9049			  (match_operand:SI 2 "s_register_operand" "r"))))
9050   (set (match_operand:SI 0 "s_register_operand" "=r")
9051	(minus:SI (match_dup 1) (match_dup 2)))]
9052  "TARGET_ARM
9053   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9054   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9055   && (GET_CODE (operands[2]) != REG
9056       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9057  "ldr%?\\t%3, [%0, -%2]!"
9058  [(set_attr "type" "load")
9059   (set_attr "predicable" "yes")]
9060)
9061
9062(define_insn "*loadhi_preinc"
9063  [(set (match_operand:HI 3 "s_register_operand" "=r")
9064	(mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9065			 (match_operand:SI 2 "index_operand" "rJ"))))
9066   (set (match_operand:SI 0 "s_register_operand" "=r")
9067	(plus:SI (match_dup 1) (match_dup 2)))]
9068  "TARGET_ARM
9069   && !BYTES_BIG_ENDIAN
9070   && !TARGET_MMU_TRAPS
9071   && !arm_arch4
9072   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9073   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9074   && (GET_CODE (operands[2]) != REG
9075       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9076  "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
9077  [(set_attr "type" "load")
9078   (set_attr "predicable" "yes")]
9079)
9080
9081(define_insn "*loadhi_predec"
9082  [(set (match_operand:HI 3 "s_register_operand" "=r")
9083	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9084			  (match_operand:SI 2 "s_register_operand" "r"))))
9085   (set (match_operand:SI 0 "s_register_operand" "=r")
9086	(minus:SI (match_dup 1) (match_dup 2)))]
9087  "TARGET_ARM
9088   && !BYTES_BIG_ENDIAN
9089   && !TARGET_MMU_TRAPS
9090   && !arm_arch4
9091   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9092   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9093   && (GET_CODE (operands[2]) != REG
9094       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9095  "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
9096  [(set_attr "type" "load")
9097   (set_attr "predicable" "yes")]
9098)
9099
9100(define_insn "*strqi_shiftpreinc"
9101  [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9102			  [(match_operand:SI 3 "s_register_operand" "r")
9103			   (match_operand:SI 4 "const_shift_operand" "n")])
9104			 (match_operand:SI 1 "s_register_operand" "0")))
9105	(match_operand:QI 5 "s_register_operand" "r"))
9106   (set (match_operand:SI 0 "s_register_operand" "=r")
9107	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9108		 (match_dup 1)))]
9109  "TARGET_ARM
9110   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9111   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9112   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9113  "str%?b\\t%5, [%0, %3%S2]!"
9114  [(set_attr "type" "store1")
9115   (set_attr "predicable" "yes")]
9116)
9117
9118(define_insn "*strqi_shiftpredec"
9119  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9120			  (match_operator:SI 2 "shift_operator"
9121			   [(match_operand:SI 3 "s_register_operand" "r")
9122			    (match_operand:SI 4 "const_shift_operand" "n")])))
9123	(match_operand:QI 5 "s_register_operand" "r"))
9124   (set (match_operand:SI 0 "s_register_operand" "=r")
9125	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9126						 (match_dup 4)])))]
9127  "TARGET_ARM
9128   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9129   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9130   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9131  "str%?b\\t%5, [%0, -%3%S2]!"
9132  [(set_attr "type" "store1")
9133   (set_attr "predicable" "yes")]
9134)
9135
9136(define_insn "*loadqi_shiftpreinc"
9137  [(set (match_operand:QI 5 "s_register_operand" "=r")
9138	(mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9139			  [(match_operand:SI 3 "s_register_operand" "r")
9140			   (match_operand:SI 4 "const_shift_operand" "n")])
9141			 (match_operand:SI 1 "s_register_operand" "0"))))
9142   (set (match_operand:SI 0 "s_register_operand" "=r")
9143	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9144		 (match_dup 1)))]
9145  "TARGET_ARM
9146   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9147   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9148   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9149  "ldr%?b\\t%5, [%0, %3%S2]!"
9150  [(set_attr "type" "load")
9151   (set_attr "predicable" "yes")]
9152)
9153
9154(define_insn "*loadqi_shiftpredec"
9155  [(set (match_operand:QI 5 "s_register_operand" "=r")
9156	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9157			  (match_operator:SI 2 "shift_operator"
9158			   [(match_operand:SI 3 "s_register_operand" "r")
9159			    (match_operand:SI 4 "const_shift_operand" "n")]))))
9160   (set (match_operand:SI 0 "s_register_operand" "=r")
9161	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9162						 (match_dup 4)])))]
9163  "TARGET_ARM
9164   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9165   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9166   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9167  "ldr%?b\\t%5, [%0, -%3%S2]!"
9168  [(set_attr "type" "load")
9169   (set_attr "predicable" "yes")]
9170)
9171
9172(define_insn "*strsi_shiftpreinc"
9173  [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9174			  [(match_operand:SI 3 "s_register_operand" "r")
9175			   (match_operand:SI 4 "const_shift_operand" "n")])
9176			 (match_operand:SI 1 "s_register_operand" "0")))
9177	(match_operand:SI 5 "s_register_operand" "r"))
9178   (set (match_operand:SI 0 "s_register_operand" "=r")
9179	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9180		 (match_dup 1)))]
9181  "TARGET_ARM
9182   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9183   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9184   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9185  "str%?\\t%5, [%0, %3%S2]!"
9186  [(set_attr "type" "store1")
9187   (set_attr "predicable" "yes")]
9188)
9189
9190(define_insn "*strsi_shiftpredec"
9191  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9192			  (match_operator:SI 2 "shift_operator"
9193			   [(match_operand:SI 3 "s_register_operand" "r")
9194			    (match_operand:SI 4 "const_shift_operand" "n")])))
9195	(match_operand:SI 5 "s_register_operand" "r"))
9196   (set (match_operand:SI 0 "s_register_operand" "=r")
9197	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9198						 (match_dup 4)])))]
9199  "TARGET_ARM
9200   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9201   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9202   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9203  "str%?\\t%5, [%0, -%3%S2]!"
9204  [(set_attr "type" "store1")
9205   (set_attr "predicable" "yes")]
9206)
9207
9208(define_insn "*loadsi_shiftpreinc"
9209  [(set (match_operand:SI 5 "s_register_operand" "=r")
9210	(mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9211			  [(match_operand:SI 3 "s_register_operand" "r")
9212			   (match_operand:SI 4 "const_shift_operand" "n")])
9213			 (match_operand:SI 1 "s_register_operand" "0"))))
9214   (set (match_operand:SI 0 "s_register_operand" "=r")
9215	(plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9216		 (match_dup 1)))]
9217  "TARGET_ARM
9218   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9219   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9220   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9221  "ldr%?\\t%5, [%0, %3%S2]!"
9222  [(set_attr "type" "load")
9223   (set_attr "predicable" "yes")]
9224)
9225
9226(define_insn "*loadsi_shiftpredec"
9227  [(set (match_operand:SI 5 "s_register_operand" "=r")
9228	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9229			  (match_operator:SI 2 "shift_operator"
9230			   [(match_operand:SI 3 "s_register_operand" "r")
9231			    (match_operand:SI 4 "const_shift_operand" "n")]))))
9232   (set (match_operand:SI 0 "s_register_operand" "=r")
9233	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9234						 (match_dup 4)])))]
9235  "TARGET_ARM
9236   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9237   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9238   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9239  "ldr%?\\t%5, [%0, -%3%S2]!"
9240  [(set_attr "type" "load")
9241   (set_attr "predicable" "yes")])
9242
9243(define_insn "*loadhi_shiftpreinc"
9244  [(set (match_operand:HI 5 "s_register_operand" "=r")
9245	(mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9246			  [(match_operand:SI 3 "s_register_operand" "r")
9247			   (match_operand:SI 4 "const_shift_operand" "n")])
9248			 (match_operand:SI 1 "s_register_operand" "0"))))
9249   (set (match_operand:SI 0 "s_register_operand" "=r")
9250	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9251		 (match_dup 1)))]
9252  "TARGET_ARM
9253   && !BYTES_BIG_ENDIAN
9254   && !TARGET_MMU_TRAPS
9255   && !arm_arch4
9256   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9257   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9258   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9259  "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9260  [(set_attr "type" "load")
9261   (set_attr "predicable" "yes")]
9262)
9263
9264(define_insn "*loadhi_shiftpredec"
9265  [(set (match_operand:HI 5 "s_register_operand" "=r")
9266	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9267			  (match_operator:SI 2 "shift_operator"
9268			   [(match_operand:SI 3 "s_register_operand" "r")
9269			    (match_operand:SI 4 "const_shift_operand" "n")]))))
9270   (set (match_operand:SI 0 "s_register_operand" "=r")
9271	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9272						 (match_dup 4)])))]
9273  "TARGET_ARM
9274   && !BYTES_BIG_ENDIAN
9275   && !TARGET_MMU_TRAPS
9276   && !arm_arch4
9277   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9278   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9279   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9280  "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9281  [(set_attr "type" "load")
9282   (set_attr "predicable" "yes")]
9283)
9284
9285; It can also support extended post-inc expressions, but combine doesn't
9286; try these....
9287; It doesn't seem worth adding peepholes for anything but the most common
9288; cases since, unlike combine, the increment must immediately follow the load
9289; for this pattern to match.
9290; We must watch to see that the source/destination register isn't also the
9291; same as the base address register, and that if the index is a register,
9292; that it is not the same as the base address register.  In such cases the
9293; instruction that we would generate would have UNPREDICTABLE behavior so 
9294; we cannot use it.
9295
9296(define_peephole
9297  [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9298	(match_operand:QI 2 "s_register_operand" "r"))
9299   (set (match_dup 0)
9300	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9301  "TARGET_ARM
9302   && (REGNO (operands[2]) != REGNO (operands[0]))
9303   && (GET_CODE (operands[1]) != REG
9304       || (REGNO (operands[1]) != REGNO (operands[0])))"
9305  "str%?b\\t%2, [%0], %1"
9306)
9307
9308(define_peephole
9309  [(set (match_operand:QI 0 "s_register_operand" "=r")
9310	(mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9311   (set (match_dup 1)
9312	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9313  "TARGET_ARM
9314   && REGNO (operands[0]) != REGNO(operands[1])
9315   && (GET_CODE (operands[2]) != REG
9316       || REGNO(operands[0]) != REGNO (operands[2]))"
9317  "ldr%?b\\t%0, [%1], %2"
9318)
9319
9320(define_peephole
9321  [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9322	(match_operand:SI 2 "s_register_operand" "r"))
9323   (set (match_dup 0)
9324	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9325  "TARGET_ARM
9326   && (REGNO (operands[2]) != REGNO (operands[0]))
9327   && (GET_CODE (operands[1]) != REG
9328       || (REGNO (operands[1]) != REGNO (operands[0])))"
9329  "str%?\\t%2, [%0], %1"
9330)
9331
9332(define_peephole
9333  [(set (match_operand:HI 0 "s_register_operand" "=r")
9334	(mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9335   (set (match_dup 1)
9336	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9337  "TARGET_ARM
9338   && !BYTES_BIG_ENDIAN
9339   && !TARGET_MMU_TRAPS
9340   && !arm_arch4
9341   && REGNO (operands[0]) != REGNO(operands[1])
9342   && (GET_CODE (operands[2]) != REG
9343       || REGNO(operands[0]) != REGNO (operands[2]))"
9344  "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9345)
9346
9347(define_peephole
9348  [(set (match_operand:SI 0 "s_register_operand" "=r")
9349	(mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9350   (set (match_dup 1)
9351	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9352  "TARGET_ARM
9353   && REGNO (operands[0]) != REGNO(operands[1])
9354   && (GET_CODE (operands[2]) != REG
9355       || REGNO(operands[0]) != REGNO (operands[2]))"
9356  "ldr%?\\t%0, [%1], %2"
9357)
9358
9359(define_peephole
9360  [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9361			 (match_operand:SI 1 "index_operand" "rJ")))
9362	(match_operand:QI 2 "s_register_operand" "r"))
9363   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9364  "TARGET_ARM
9365   && (REGNO (operands[2]) != REGNO (operands[0]))
9366   && (GET_CODE (operands[1]) != REG
9367       || (REGNO (operands[1]) != REGNO (operands[0])))"
9368  "str%?b\\t%2, [%0, %1]!"
9369)
9370
9371(define_peephole
9372  [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9373			  [(match_operand:SI 0 "s_register_operand" "r")
9374			   (match_operand:SI 1 "const_int_operand" "n")])
9375			 (match_operand:SI 2 "s_register_operand" "+r")))
9376	(match_operand:QI 3 "s_register_operand" "r"))
9377   (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9378			       (match_dup 2)))]
9379  "TARGET_ARM
9380   && (REGNO (operands[3]) != REGNO (operands[2]))
9381   && (REGNO (operands[0]) != REGNO (operands[2]))"
9382  "str%?b\\t%3, [%2, %0%S4]!"
9383)
9384
9385; This pattern is never tried by combine, so do it as a peephole
9386
9387(define_peephole2
9388  [(set (match_operand:SI 0 "s_register_operand" "")
9389	(match_operand:SI 1 "s_register_operand" ""))
9390   (set (reg:CC CC_REGNUM)
9391	(compare:CC (match_dup 1) (const_int 0)))]
9392  "TARGET_ARM
9393   && (!TARGET_CIRRUS
9394       || (!cirrus_fp_register (operands[0], SImode)
9395           && !cirrus_fp_register (operands[1], SImode)))
9396  "
9397  [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9398	      (set (match_dup 0) (match_dup 1))])]
9399  ""
9400)
9401
9402; Peepholes to spot possible load- and store-multiples, if the ordering is
9403; reversed, check that the memory references aren't volatile.
9404
9405(define_peephole
9406  [(set (match_operand:SI 0 "s_register_operand" "=r")
9407        (match_operand:SI 4 "memory_operand" "m"))
9408   (set (match_operand:SI 1 "s_register_operand" "=r")
9409        (match_operand:SI 5 "memory_operand" "m"))
9410   (set (match_operand:SI 2 "s_register_operand" "=r")
9411        (match_operand:SI 6 "memory_operand" "m"))
9412   (set (match_operand:SI 3 "s_register_operand" "=r")
9413        (match_operand:SI 7 "memory_operand" "m"))]
9414  "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9415  "*
9416  return emit_ldm_seq (operands, 4);
9417  "
9418)
9419
9420(define_peephole
9421  [(set (match_operand:SI 0 "s_register_operand" "=r")
9422        (match_operand:SI 3 "memory_operand" "m"))
9423   (set (match_operand:SI 1 "s_register_operand" "=r")
9424        (match_operand:SI 4 "memory_operand" "m"))
9425   (set (match_operand:SI 2 "s_register_operand" "=r")
9426        (match_operand:SI 5 "memory_operand" "m"))]
9427  "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9428  "*
9429  return emit_ldm_seq (operands, 3);
9430  "
9431)
9432
9433(define_peephole
9434  [(set (match_operand:SI 0 "s_register_operand" "=r")
9435        (match_operand:SI 2 "memory_operand" "m"))
9436   (set (match_operand:SI 1 "s_register_operand" "=r")
9437        (match_operand:SI 3 "memory_operand" "m"))]
9438  "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9439  "*
9440  return emit_ldm_seq (operands, 2);
9441  "
9442)
9443
9444(define_peephole
9445  [(set (match_operand:SI 4 "memory_operand" "=m")
9446        (match_operand:SI 0 "s_register_operand" "r"))
9447   (set (match_operand:SI 5 "memory_operand" "=m")
9448        (match_operand:SI 1 "s_register_operand" "r"))
9449   (set (match_operand:SI 6 "memory_operand" "=m")
9450        (match_operand:SI 2 "s_register_operand" "r"))
9451   (set (match_operand:SI 7 "memory_operand" "=m")
9452        (match_operand:SI 3 "s_register_operand" "r"))]
9453  "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9454  "*
9455  return emit_stm_seq (operands, 4);
9456  "
9457)
9458
9459(define_peephole
9460  [(set (match_operand:SI 3 "memory_operand" "=m")
9461        (match_operand:SI 0 "s_register_operand" "r"))
9462   (set (match_operand:SI 4 "memory_operand" "=m")
9463        (match_operand:SI 1 "s_register_operand" "r"))
9464   (set (match_operand:SI 5 "memory_operand" "=m")
9465        (match_operand:SI 2 "s_register_operand" "r"))]
9466  "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9467  "*
9468  return emit_stm_seq (operands, 3);
9469  "
9470)
9471
9472(define_peephole
9473  [(set (match_operand:SI 2 "memory_operand" "=m")
9474        (match_operand:SI 0 "s_register_operand" "r"))
9475   (set (match_operand:SI 3 "memory_operand" "=m")
9476        (match_operand:SI 1 "s_register_operand" "r"))]
9477  "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9478  "*
9479  return emit_stm_seq (operands, 2);
9480  "
9481)
9482
9483(define_split
9484  [(set (match_operand:SI 0 "s_register_operand" "")
9485	(and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9486		       (const_int 0))
9487		(neg:SI (match_operator:SI 2 "arm_comparison_operator"
9488			 [(match_operand:SI 3 "s_register_operand" "")
9489			  (match_operand:SI 4 "arm_rhs_operand" "")]))))
9490   (clobber (match_operand:SI 5 "s_register_operand" ""))]
9491  "TARGET_ARM"
9492  [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9493   (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9494			      (match_dup 5)))]
9495  ""
9496)
9497
9498;; This split can be used because CC_Z mode implies that the following
9499;; branch will be an equality, or an unsigned inequality, so the sign
9500;; extension is not needed.
9501
9502(define_split
9503  [(set (reg:CC_Z CC_REGNUM)
9504	(compare:CC_Z
9505	 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9506		    (const_int 24))
9507	 (match_operand 1 "const_int_operand" "")))
9508   (clobber (match_scratch:SI 2 ""))]
9509  "TARGET_ARM
9510   && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9511       == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9512  [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9513   (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9514  "
9515  operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9516  "
9517)
9518
9519(define_expand "prologue"
9520  [(clobber (const_int 0))]
9521  "TARGET_EITHER"
9522  "if (TARGET_ARM)
9523     arm_expand_prologue ();
9524   else
9525     thumb_expand_prologue ();
9526  DONE;
9527  "
9528)
9529
9530(define_expand "epilogue"
9531  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9532  "TARGET_EITHER"
9533  "
9534  if (TARGET_THUMB)
9535    thumb_expand_epilogue ();
9536  else if (USE_RETURN_INSN (FALSE))
9537    {
9538      emit_jump_insn (gen_return ());
9539      DONE;
9540    }
9541  emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9542	gen_rtvec (1,
9543		gen_rtx_RETURN (VOIDmode)),
9544	VUNSPEC_EPILOGUE));
9545  DONE;
9546  "
9547)
9548
9549;; Note - although unspec_volatile's USE all hard registers,
9550;; USEs are ignored after relaod has completed.  Thus we need
9551;; to add an unspec of the link register to ensure that flow
9552;; does not think that it is unused by the sibcall branch that
9553;; will replace the standard function epilogue.
9554(define_insn "sibcall_epilogue"
9555  [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9556              (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9557  "TARGET_ARM"
9558  "*
9559  if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9560    return output_return_instruction (const_true_rtx, FALSE, FALSE);
9561  return arm_output_epilogue (next_nonnote_insn (insn));
9562  "
9563;; Length is absolute worst case
9564  [(set_attr "length" "44")
9565   (set_attr "type" "block")
9566   ;; We don't clobber the conditions, but the potential length of this
9567   ;; operation is sufficient to make conditionalizing the sequence 
9568   ;; unlikely to be profitable.
9569   (set_attr "conds" "clob")]
9570)
9571
9572(define_insn "*epilogue_insns"
9573  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9574  "TARGET_EITHER"
9575  "*
9576  if (TARGET_ARM)
9577    return arm_output_epilogue (NULL);
9578  else /* TARGET_THUMB */
9579    return thumb_unexpanded_epilogue ();
9580  "
9581  ; Length is absolute worst case
9582  [(set_attr "length" "44")
9583   (set_attr "type" "block")
9584   ;; We don't clobber the conditions, but the potential length of this
9585   ;; operation is sufficient to make conditionalizing the sequence 
9586   ;; unlikely to be profitable.
9587   (set_attr "conds" "clob")]
9588)
9589
9590(define_expand "eh_epilogue"
9591  [(use (match_operand:SI 0 "register_operand" ""))
9592   (use (match_operand:SI 1 "register_operand" ""))
9593   (use (match_operand:SI 2 "register_operand" ""))]
9594  "TARGET_EITHER"
9595  "
9596  {
9597    cfun->machine->eh_epilogue_sp_ofs = operands[1];
9598    if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9599      {
9600	rtx ra = gen_rtx_REG (Pmode, 2);
9601
9602	emit_move_insn (ra, operands[2]);
9603	operands[2] = ra;
9604      }
9605    /* This is a hack -- we may have crystalized the function type too
9606       early.  */
9607    cfun->machine->func_type = 0;
9608  }"
9609)
9610
9611;; This split is only used during output to reduce the number of patterns
9612;; that need assembler instructions adding to them.  We allowed the setting
9613;; of the conditions to be implicit during rtl generation so that
9614;; the conditional compare patterns would work.  However this conflicts to
9615;; some extent with the conditional data operations, so we have to split them
9616;; up again here.
9617
9618(define_split
9619  [(set (match_operand:SI 0 "s_register_operand" "")
9620	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9621			  [(match_operand 2 "" "") (match_operand 3 "" "")])
9622			 (match_dup 0)
9623			 (match_operand 4 "" "")))
9624   (clobber (reg:CC CC_REGNUM))]
9625  "TARGET_ARM && reload_completed"
9626  [(set (match_dup 5) (match_dup 6))
9627   (cond_exec (match_dup 7)
9628	      (set (match_dup 0) (match_dup 4)))]
9629  "
9630  {
9631    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9632					     operands[2], operands[3]);
9633    enum rtx_code rc = GET_CODE (operands[1]);
9634
9635    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9636    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9637    if (mode == CCFPmode || mode == CCFPEmode)
9638      rc = reverse_condition_maybe_unordered (rc);
9639    else
9640      rc = reverse_condition (rc);
9641
9642    operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9643  }"
9644)
9645
9646(define_split
9647  [(set (match_operand:SI 0 "s_register_operand" "")
9648	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9649			  [(match_operand 2 "" "") (match_operand 3 "" "")])
9650			 (match_operand 4 "" "")
9651			 (match_dup 0)))
9652   (clobber (reg:CC CC_REGNUM))]
9653  "TARGET_ARM && reload_completed"
9654  [(set (match_dup 5) (match_dup 6))
9655   (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9656	      (set (match_dup 0) (match_dup 4)))]
9657  "
9658  {
9659    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9660					     operands[2], operands[3]);
9661
9662    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9663    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9664  }"
9665)
9666
9667(define_split
9668  [(set (match_operand:SI 0 "s_register_operand" "")
9669	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9670			  [(match_operand 2 "" "") (match_operand 3 "" "")])
9671			 (match_operand 4 "" "")
9672			 (match_operand 5 "" "")))
9673   (clobber (reg:CC CC_REGNUM))]
9674  "TARGET_ARM && reload_completed"
9675  [(set (match_dup 6) (match_dup 7))
9676   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9677	      (set (match_dup 0) (match_dup 4)))
9678   (cond_exec (match_dup 8)
9679	      (set (match_dup 0) (match_dup 5)))]
9680  "
9681  {
9682    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9683					     operands[2], operands[3]);
9684    enum rtx_code rc = GET_CODE (operands[1]);
9685
9686    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9687    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9688    if (mode == CCFPmode || mode == CCFPEmode)
9689      rc = reverse_condition_maybe_unordered (rc);
9690    else
9691      rc = reverse_condition (rc);
9692
9693    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9694  }"
9695)
9696
9697(define_split
9698  [(set (match_operand:SI 0 "s_register_operand" "")
9699	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9700			  [(match_operand:SI 2 "s_register_operand" "")
9701			   (match_operand:SI 3 "arm_add_operand" "")])
9702			 (match_operand:SI 4 "arm_rhs_operand" "")
9703			 (not:SI
9704			  (match_operand:SI 5 "s_register_operand" ""))))
9705   (clobber (reg:CC CC_REGNUM))]
9706  "TARGET_ARM && reload_completed"
9707  [(set (match_dup 6) (match_dup 7))
9708   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9709	      (set (match_dup 0) (match_dup 4)))
9710   (cond_exec (match_dup 8)
9711	      (set (match_dup 0) (not:SI (match_dup 5))))]
9712  "
9713  {
9714    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9715					     operands[2], operands[3]);
9716    enum rtx_code rc = GET_CODE (operands[1]);
9717
9718    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9719    operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
9720    if (mode == CCFPmode || mode == CCFPEmode)
9721      rc = reverse_condition_maybe_unordered (rc);
9722    else
9723      rc = reverse_condition (rc);
9724
9725    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9726  }"
9727)
9728
9729(define_insn "*cond_move_not"
9730  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9731	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
9732			  [(match_operand 3 "cc_register" "") (const_int 0)])
9733			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9734			 (not:SI
9735			  (match_operand:SI 2 "s_register_operand" "r,r"))))]
9736  "TARGET_ARM"
9737  "@
9738   mvn%D4\\t%0, %2
9739   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9740  [(set_attr "conds" "use")
9741   (set_attr "length" "4,8")]
9742)
9743
9744;; The next two patterns occur when an AND operation is followed by a
9745;; scc insn sequence 
9746
9747(define_insn "*sign_extract_onebit"
9748  [(set (match_operand:SI 0 "s_register_operand" "=r")
9749	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9750			 (const_int 1)
9751			 (match_operand:SI 2 "const_int_operand" "n")))
9752    (clobber (reg:CC CC_REGNUM))]
9753  "TARGET_ARM"
9754  "*
9755    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9756    output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9757    return \"mvnne\\t%0, #0\";
9758  "
9759  [(set_attr "conds" "clob")
9760   (set_attr "length" "8")]
9761)
9762
9763(define_insn "*not_signextract_onebit"
9764  [(set (match_operand:SI 0 "s_register_operand" "=r")
9765	(not:SI
9766	 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9767			  (const_int 1)
9768			  (match_operand:SI 2 "const_int_operand" "n"))))
9769   (clobber (reg:CC CC_REGNUM))]
9770  "TARGET_ARM"
9771  "*
9772    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9773    output_asm_insn (\"tst\\t%1, %2\", operands);
9774    output_asm_insn (\"mvneq\\t%0, #0\", operands);
9775    return \"movne\\t%0, #0\";
9776  "
9777  [(set_attr "conds" "clob")
9778   (set_attr "length" "12")]
9779)
9780
9781;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9782;; expressions.  For simplicity, the first register is also in the unspec
9783;; part.
9784(define_insn "*push_multi"
9785  [(match_parallel 2 "multi_register_push"
9786    [(set (match_operand:BLK 0 "memory_operand" "=m")
9787	  (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9788		      UNSPEC_PUSH_MULT))])]
9789  "TARGET_ARM"
9790  "*
9791  {
9792    int num_saves = XVECLEN (operands[2], 0);
9793     
9794    /* For the StrongARM at least it is faster to
9795       use STR to store only a single register.  */
9796    if (num_saves == 1)
9797      output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9798    else
9799      {
9800	int i;
9801	char pattern[100];
9802
9803	strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9804
9805	for (i = 1; i < num_saves; i++)
9806	  {
9807	    strcat (pattern, \", %|\");
9808	    strcat (pattern,
9809		    reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9810	  }
9811
9812	strcat (pattern, \"}\");
9813	output_asm_insn (pattern, operands);
9814      }
9815
9816    return \"\";
9817  }"
9818  [(set_attr "type" "store4")]
9819)
9820
9821(define_insn "stack_tie"
9822  [(set (mem:BLK (scratch))
9823	(unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9824		     (match_operand:SI 1 "s_register_operand" "r")]
9825		    UNSPEC_PRLG_STK))]
9826  ""
9827  ""
9828  [(set_attr "length" "0")]
9829)
9830
9831;; Similarly for the floating point registers
9832(define_insn "*push_fp_multi"
9833  [(match_parallel 2 "multi_register_push"
9834    [(set (match_operand:BLK 0 "memory_operand" "=m")
9835	  (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9836		      UNSPEC_PUSH_MULT))])]
9837  "TARGET_ARM"
9838  "*
9839  {
9840    char pattern[100];
9841
9842    sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9843    output_asm_insn (pattern, operands);
9844    return \"\";
9845  }"
9846  [(set_attr "type" "f_store")]
9847)
9848
9849;; Special patterns for dealing with the constant pool
9850
9851(define_insn "align_4"
9852  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9853  "TARGET_EITHER"
9854  "*
9855  assemble_align (32);
9856  return \"\";
9857  "
9858)
9859
9860(define_insn "align_8"
9861  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9862  "TARGET_REALLY_IWMMXT"
9863  "*
9864  assemble_align (64);
9865  return \"\";
9866  "
9867)
9868
9869(define_insn "consttable_end"
9870  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9871  "TARGET_EITHER"
9872  "*
9873  making_const_table = FALSE;
9874  return \"\";
9875  "
9876)
9877
9878(define_insn "consttable_1"
9879  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9880  "TARGET_THUMB"
9881  "*
9882  making_const_table = TRUE;
9883  assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9884  assemble_zeros (3);
9885  return \"\";
9886  "
9887  [(set_attr "length" "4")]
9888)
9889
9890(define_insn "consttable_2"
9891  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9892  "TARGET_THUMB"
9893  "*
9894  making_const_table = TRUE;
9895  assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9896  assemble_zeros (2);
9897  return \"\";
9898  "
9899  [(set_attr "length" "4")]
9900)
9901
9902(define_insn "consttable_4"
9903  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9904  "TARGET_EITHER"
9905  "*
9906  {
9907    making_const_table = TRUE;
9908    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9909      {
9910      case MODE_FLOAT:
9911      {
9912        REAL_VALUE_TYPE r;
9913        REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9914        assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9915        break;
9916      }
9917      default:
9918        assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9919        break;
9920      }
9921    return \"\";
9922  }"
9923  [(set_attr "length" "4")]
9924)
9925
9926(define_insn "consttable_8"
9927  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9928  "TARGET_EITHER"
9929  "*
9930  {
9931    making_const_table = TRUE;
9932    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9933      {
9934       case MODE_FLOAT:
9935        {
9936          REAL_VALUE_TYPE r;
9937          REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9938          assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9939          break;
9940        }
9941      default:
9942        assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9943        break;
9944      }
9945    return \"\";
9946  }"
9947  [(set_attr "length" "8")]
9948)
9949
9950;; Miscellaneous Thumb patterns
9951
9952(define_expand "tablejump"
9953  [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9954	      (use (label_ref (match_operand 1 "" "")))])]
9955  "TARGET_THUMB"
9956  "
9957  if (flag_pic)
9958    {
9959      /* Hopefully, CSE will eliminate this copy.  */
9960      rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9961      rtx reg2 = gen_reg_rtx (SImode);
9962
9963      emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9964      operands[0] = reg2;
9965    }
9966  "
9967)
9968
9969(define_insn "*thumb_tablejump"
9970  [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9971   (use (label_ref (match_operand 1 "" "")))]
9972  "TARGET_THUMB"
9973  "mov\\t%|pc, %0"
9974  [(set_attr "length" "2")]
9975)
9976
9977;; V5 Instructions,
9978
9979(define_insn "clzsi2"
9980  [(set (match_operand:SI 0 "s_register_operand" "=r")
9981	(clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
9982  "TARGET_ARM && arm_arch5"
9983  "clz%?\\t%0, %1"
9984  [(set_attr "predicable" "yes")])
9985
9986(define_expand "ffssi2"
9987  [(set (match_operand:SI 0 "s_register_operand" "")
9988	(ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9989  "TARGET_ARM && arm_arch5"
9990  "
9991  {
9992    rtx t1, t2, t3;
9993
9994    t1 = gen_reg_rtx (SImode);
9995    t2 = gen_reg_rtx (SImode);
9996    t3 = gen_reg_rtx (SImode);
9997
9998    emit_insn (gen_negsi2 (t1, operands[1]));
9999    emit_insn (gen_andsi3 (t2, operands[1], t1));
10000    emit_insn (gen_clzsi2 (t3, t2));
10001    emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10002    DONE;
10003  }"
10004)
10005
10006(define_expand "ctzsi2"
10007  [(set (match_operand:SI 0 "s_register_operand" "")
10008	(ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10009  "TARGET_ARM && arm_arch5"
10010  "
10011  {
10012    rtx t1, t2, t3;
10013
10014    t1 = gen_reg_rtx (SImode);
10015    t2 = gen_reg_rtx (SImode);
10016    t3 = gen_reg_rtx (SImode);
10017
10018    emit_insn (gen_negsi2 (t1, operands[1]));
10019    emit_insn (gen_andsi3 (t2, operands[1], t1));
10020    emit_insn (gen_clzsi2 (t3, t2));
10021    emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10022    DONE;
10023  }"
10024)
10025
10026;; V5E instructions.
10027
10028(define_insn "prefetch"
10029  [(prefetch (match_operand:SI 0 "address_operand" "p")
10030	     (match_operand:SI 1 "" "")
10031	     (match_operand:SI 2 "" ""))]
10032  "TARGET_ARM && arm_arch5e"
10033  "pld\\t%a0")
10034
10035;; General predication pattern
10036
10037(define_cond_exec
10038  [(match_operator 0 "arm_comparison_operator"
10039    [(match_operand 1 "cc_register" "")
10040     (const_int 0)])]
10041  "TARGET_ARM"
10042  ""
10043)
10044
10045(define_insn "prologue_use"
10046  [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10047  ""
10048  "%@ %0 needed for prologue"
10049)
10050
10051;; Load the FPA co-processor patterns
10052(include "fpa.md")
10053;; Load the Maverick co-processor patterns
10054(include "cirrus.md")
10055;; Load the Intel Wireless Multimedia Extension patterns
10056(include "iwmmxt.md")
10057