arm.md revision 161651
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  HOST_WIDE_INT offset = 0;
5048  
5049  /* Support only fixed point registers.  */
5050  if (GET_CODE (operands[2]) != CONST_INT
5051      || INTVAL (operands[2]) > 14
5052      || INTVAL (operands[2]) < 2
5053      || GET_CODE (operands[1]) != MEM
5054      || GET_CODE (operands[0]) != REG
5055      || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5056      || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5057    FAIL;
5058
5059  operands[3]
5060    = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5061			     force_reg (SImode, XEXP (operands[1], 0)),
5062			     TRUE, FALSE, operands[1], &offset);
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  HOST_WIDE_INT offset = 0;
5170
5171  /* Support only fixed point registers.  */
5172  if (GET_CODE (operands[2]) != CONST_INT
5173      || INTVAL (operands[2]) > 14
5174      || INTVAL (operands[2]) < 2
5175      || GET_CODE (operands[1]) != REG
5176      || GET_CODE (operands[0]) != MEM
5177      || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5178      || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5179    FAIL;
5180
5181  operands[3]
5182    = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5183			      force_reg (SImode, XEXP (operands[0], 0)),
5184			      TRUE, FALSE, operands[0], &offset);
5185})
5186
5187;; Store multiple with write-back
5188
5189(define_insn "*stmsi_postinc4"
5190  [(match_parallel 0 "store_multiple_operation"
5191    [(set (match_operand:SI 1 "s_register_operand" "=r")
5192	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5193		   (const_int 16)))
5194     (set (mem:SI (match_dup 2))
5195	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5196     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5197	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5198     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5199	  (match_operand:SI 5 "arm_hard_register_operand" ""))
5200     (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5201	  (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5202  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5203  "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5204  [(set_attr "predicable" "yes")
5205   (set_attr "type" "store4")]
5206)
5207
5208(define_insn "*stmsi_postinc3"
5209  [(match_parallel 0 "store_multiple_operation"
5210    [(set (match_operand:SI 1 "s_register_operand" "=r")
5211	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5212		   (const_int 12)))
5213     (set (mem:SI (match_dup 2))
5214	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5215     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5216	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5217     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5218	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5219  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5220  "stm%?ia\\t%1!, {%3, %4, %5}"
5221  [(set_attr "predicable" "yes")
5222   (set_attr "type" "store3")]
5223)
5224
5225(define_insn "*stmsi_postinc2"
5226  [(match_parallel 0 "store_multiple_operation"
5227    [(set (match_operand:SI 1 "s_register_operand" "=r")
5228	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5229		   (const_int 8)))
5230     (set (mem:SI (match_dup 2))
5231	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5232     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5233	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5234  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5235  "stm%?ia\\t%1!, {%3, %4}"
5236  [(set_attr "predicable" "yes")
5237   (set_attr "type" "store2")]
5238)
5239
5240;; Ordinary store multiple
5241
5242(define_insn "*stmsi4"
5243  [(match_parallel 0 "store_multiple_operation"
5244    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5245	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5246     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5247	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5248     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5249	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5250     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5251	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5252  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5253  "stm%?ia\\t%1, {%2, %3, %4, %5}"
5254  [(set_attr "predicable" "yes")
5255   (set_attr "type" "store4")]
5256)
5257
5258(define_insn "*stmsi3"
5259  [(match_parallel 0 "store_multiple_operation"
5260    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5261	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5262     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5263	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5264     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5265	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5266  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5267  "stm%?ia\\t%1, {%2, %3, %4}"
5268  [(set_attr "predicable" "yes")
5269   (set_attr "type" "store3")]
5270)
5271
5272(define_insn "*stmsi2"
5273  [(match_parallel 0 "store_multiple_operation"
5274    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5275	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5276     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5277	  (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5278  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5279  "stm%?ia\\t%1, {%2, %3}"
5280  [(set_attr "predicable" "yes")
5281   (set_attr "type" "store2")]
5282)
5283
5284;; Move a block of memory if it is word aligned and MORE than 2 words long.
5285;; We could let this apply for blocks of less than this, but it clobbers so
5286;; many registers that there is then probably a better way.
5287
5288(define_expand "movstrqi"
5289  [(match_operand:BLK 0 "general_operand" "")
5290   (match_operand:BLK 1 "general_operand" "")
5291   (match_operand:SI 2 "const_int_operand" "")
5292   (match_operand:SI 3 "const_int_operand" "")]
5293  "TARGET_EITHER"
5294  "
5295  if (TARGET_ARM)
5296    {
5297      if (arm_gen_movstrqi (operands))
5298        DONE;
5299      FAIL;
5300    }
5301  else /* TARGET_THUMB */
5302    {
5303      if (   INTVAL (operands[3]) != 4
5304          || INTVAL (operands[2]) > 48)
5305        FAIL;
5306
5307      thumb_expand_movstrqi (operands);
5308      DONE;
5309    }
5310  "
5311)
5312
5313;; Thumb block-move insns
5314
5315(define_insn "movmem12b"
5316  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5317	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5318   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5319	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5320   (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5321	(mem:SI (plus:SI (match_dup 3) (const_int 8))))
5322   (set (match_operand:SI 0 "register_operand" "=l")
5323	(plus:SI (match_dup 2) (const_int 12)))
5324   (set (match_operand:SI 1 "register_operand" "=l")
5325	(plus:SI (match_dup 3) (const_int 12)))
5326   (clobber (match_scratch:SI 4 "=&l"))
5327   (clobber (match_scratch:SI 5 "=&l"))
5328   (clobber (match_scratch:SI 6 "=&l"))]
5329  "TARGET_THUMB"
5330  "* return thumb_output_move_mem_multiple (3, operands);"
5331  [(set_attr "length" "4")
5332   ; This isn't entirely accurate...  It loads as well, but in terms of
5333   ; scheduling the following insn it is better to consider it as a store
5334   (set_attr "type" "store3")]
5335)
5336
5337(define_insn "movmem8b"
5338  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5339	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5340   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5341	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5342   (set (match_operand:SI 0 "register_operand" "=l")
5343	(plus:SI (match_dup 2) (const_int 8)))
5344   (set (match_operand:SI 1 "register_operand" "=l")
5345	(plus:SI (match_dup 3) (const_int 8)))
5346   (clobber (match_scratch:SI 4 "=&l"))
5347   (clobber (match_scratch:SI 5 "=&l"))]
5348  "TARGET_THUMB"
5349  "* return thumb_output_move_mem_multiple (2, operands);"
5350  [(set_attr "length" "4")
5351   ; This isn't entirely accurate...  It loads as well, but in terms of
5352   ; scheduling the following insn it is better to consider it as a store
5353   (set_attr "type" "store2")]
5354)
5355
5356
5357
5358;; Compare & branch insns
5359;; The range calculations are based as follows:
5360;; For forward branches, the address calculation returns the address of
5361;; the next instruction.  This is 2 beyond the branch instruction.
5362;; For backward branches, the address calculation returns the address of
5363;; the first instruction in this pattern (cmp).  This is 2 before the branch
5364;; instruction for the shortest sequence, and 4 before the branch instruction
5365;; if we have to jump around an unconditional branch.
5366;; To the basic branch range the PC offset must be added (this is +4).
5367;; So for forward branches we have 
5368;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5369;; And for backward branches we have 
5370;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5371;;
5372;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5373;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5374
5375(define_expand "cbranchsi4"
5376  [(set (pc) (if_then_else
5377	      (match_operator 0 "arm_comparison_operator"
5378	       [(match_operand:SI 1 "s_register_operand" "")
5379	        (match_operand:SI 2 "nonmemory_operand" "")])
5380	      (label_ref (match_operand 3 "" ""))
5381	      (pc)))]
5382  "TARGET_THUMB"
5383  "
5384  if (thumb_cmpneg_operand (operands[2], SImode))
5385    {
5386      emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5387					      operands[3], operands[0]));
5388      DONE;
5389    }
5390  if (!thumb_cmp_operand (operands[2], SImode))
5391    operands[2] = force_reg (SImode, operands[2]);
5392  ")
5393
5394(define_insn "*cbranchsi4_insn"
5395  [(set (pc) (if_then_else
5396	      (match_operator 0 "arm_comparison_operator"
5397	       [(match_operand:SI 1 "s_register_operand" "l,*h")
5398	        (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5399	      (label_ref (match_operand 3 "" ""))
5400	      (pc)))]
5401  "TARGET_THUMB"
5402  "*
5403  output_asm_insn (\"cmp\\t%1, %2\", operands);
5404
5405  switch (get_attr_length (insn))
5406    {
5407    case 4:  return \"b%d0\\t%l3\";
5408    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5409    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5410    }
5411  "
5412  [(set (attr "far_jump")
5413        (if_then_else
5414	    (eq_attr "length" "8")
5415	    (const_string "yes")
5416            (const_string "no")))
5417   (set (attr "length") 
5418        (if_then_else
5419	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5420	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5421	    (const_int 4)
5422	    (if_then_else
5423	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5424		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5425		(const_int 6)
5426		(const_int 8))))]
5427)
5428
5429(define_insn "cbranchsi4_scratch"
5430  [(set (pc) (if_then_else
5431	      (match_operator 4 "arm_comparison_operator"
5432	       [(match_operand:SI 1 "s_register_operand" "l,0")
5433	        (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5434	      (label_ref (match_operand 3 "" ""))
5435	      (pc)))
5436   (clobber (match_scratch:SI 0 "=l,l"))]
5437  "TARGET_THUMB"
5438  "*
5439  output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5440
5441  switch (get_attr_length (insn))
5442    {
5443    case 4:  return \"b%d4\\t%l3\";
5444    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5445    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5446    }
5447  "
5448  [(set (attr "far_jump")
5449        (if_then_else
5450	    (eq_attr "length" "8")
5451	    (const_string "yes")
5452            (const_string "no")))
5453   (set (attr "length") 
5454        (if_then_else
5455	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5456	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5457	    (const_int 4)
5458	    (if_then_else
5459	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5460		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5461		(const_int 6)
5462		(const_int 8))))]
5463)
5464(define_insn "*movsi_cbranchsi4"
5465  [(set (pc)
5466	(if_then_else
5467	 (match_operator 3 "arm_comparison_operator"
5468	  [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5469	   (const_int 0)])
5470	 (label_ref (match_operand 2 "" ""))
5471	 (pc)))
5472   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5473	(match_dup 1))]
5474  "TARGET_THUMB"
5475  "*{
5476  if (which_alternative == 0)
5477    output_asm_insn (\"cmp\t%0, #0\", operands);
5478  else if (which_alternative == 1)
5479    output_asm_insn (\"sub\t%0, %1, #0\", operands);
5480  else
5481    {
5482      output_asm_insn (\"cmp\t%1, #0\", operands);
5483      if (which_alternative == 2)
5484	output_asm_insn (\"mov\t%0, %1\", operands);
5485      else
5486	output_asm_insn (\"str\t%1, %0\", operands);
5487    }
5488  switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5489    {
5490    case 4:  return \"b%d3\\t%l2\";
5491    case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5492    default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5493    }
5494  }"
5495  [(set (attr "far_jump")
5496        (if_then_else
5497	    (ior (and (gt (symbol_ref ("which_alternative"))
5498	                  (const_int 1))
5499		      (eq_attr "length" "8"))
5500		 (eq_attr "length" "10"))
5501	    (const_string "yes")
5502            (const_string "no")))
5503   (set (attr "length")
5504     (if_then_else
5505       (le (symbol_ref ("which_alternative"))
5506		       (const_int 1))
5507       (if_then_else
5508	 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5509	      (le (minus (match_dup 2) (pc)) (const_int 256)))
5510	 (const_int 4)
5511	 (if_then_else
5512	   (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5513		(le (minus (match_dup 2) (pc)) (const_int 2048)))
5514	   (const_int 6)
5515	   (const_int 8)))
5516       (if_then_else
5517	 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5518	      (le (minus (match_dup 2) (pc)) (const_int 256)))
5519	 (const_int 6)
5520	 (if_then_else
5521	   (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5522		(le (minus (match_dup 2) (pc)) (const_int 2048)))
5523	   (const_int 8)
5524	   (const_int 10)))))]
5525)
5526
5527(define_insn "*negated_cbranchsi4"
5528  [(set (pc)
5529	(if_then_else
5530	 (match_operator 0 "arm_comparison_operator"
5531	  [(match_operand:SI 1 "s_register_operand" "l")
5532	   (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5533	 (label_ref (match_operand 3 "" ""))
5534	 (pc)))]
5535  "TARGET_THUMB"
5536  "*
5537  output_asm_insn (\"cmn\\t%1, %2\", operands);
5538  switch (get_attr_length (insn))
5539    {
5540    case 4:  return \"b%d0\\t%l3\";
5541    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5542    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5543    }
5544  "
5545  [(set (attr "far_jump")
5546        (if_then_else
5547	    (eq_attr "length" "8")
5548	    (const_string "yes")
5549            (const_string "no")))
5550   (set (attr "length") 
5551        (if_then_else
5552	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5553	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5554	    (const_int 4)
5555	    (if_then_else
5556	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5557		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5558		(const_int 6)
5559		(const_int 8))))]
5560)
5561
5562(define_insn "*tbit_cbranch"
5563  [(set (pc)
5564	(if_then_else
5565	 (match_operator 0 "equality_operator"
5566	  [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5567			    (const_int 1)
5568			    (match_operand:SI 2 "const_int_operand" "i"))
5569	   (const_int 0)])
5570	 (label_ref (match_operand 3 "" ""))
5571	 (pc)))
5572   (clobber (match_scratch:SI 4 "=l"))]
5573  "TARGET_THUMB"
5574  "*
5575  {
5576  rtx op[3];
5577  op[0] = operands[4];
5578  op[1] = operands[1];
5579  op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5580
5581  output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5582  switch (get_attr_length (insn))
5583    {
5584    case 4:  return \"b%d0\\t%l3\";
5585    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5586    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5587    }
5588  }"
5589  [(set (attr "far_jump")
5590        (if_then_else
5591	    (eq_attr "length" "8")
5592	    (const_string "yes")
5593            (const_string "no")))
5594   (set (attr "length") 
5595        (if_then_else
5596	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5597	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5598	    (const_int 4)
5599	    (if_then_else
5600	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5601		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5602		(const_int 6)
5603		(const_int 8))))]
5604)
5605  
5606(define_insn "*tstsi3_cbranch"
5607  [(set (pc)
5608	(if_then_else
5609	 (match_operator 3 "equality_operator"
5610	  [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5611		   (match_operand:SI 1 "s_register_operand" "l"))
5612	   (const_int 0)])
5613	 (label_ref (match_operand 2 "" ""))
5614	 (pc)))]
5615  "TARGET_THUMB"
5616  "*
5617  {
5618  output_asm_insn (\"tst\\t%0, %1\", operands);
5619  switch (get_attr_length (insn))
5620    {
5621    case 4:  return \"b%d3\\t%l2\";
5622    case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5623    default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5624    }
5625  }"
5626  [(set (attr "far_jump")
5627        (if_then_else
5628	    (eq_attr "length" "8")
5629	    (const_string "yes")
5630            (const_string "no")))
5631   (set (attr "length") 
5632        (if_then_else
5633	    (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5634	         (le (minus (match_dup 2) (pc)) (const_int 256)))
5635	    (const_int 4)
5636	    (if_then_else
5637	        (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5638		     (le (minus (match_dup 2) (pc)) (const_int 2048)))
5639		(const_int 6)
5640		(const_int 8))))]
5641)
5642  
5643(define_insn "*andsi3_cbranch"
5644  [(set (pc)
5645	(if_then_else
5646	 (match_operator 5 "equality_operator"
5647	  [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5648		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5649	   (const_int 0)])
5650	 (label_ref (match_operand 4 "" ""))
5651	 (pc)))
5652   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5653	(and:SI (match_dup 2) (match_dup 3)))
5654   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5655  "TARGET_THUMB"
5656  "*
5657  {
5658  if (which_alternative == 0)
5659    output_asm_insn (\"and\\t%0, %3\", operands);
5660  else if (which_alternative == 1)
5661    {
5662      output_asm_insn (\"and\\t%1, %3\", operands);
5663      output_asm_insn (\"mov\\t%0, %1\", operands);
5664    }
5665  else
5666    {
5667      output_asm_insn (\"and\\t%1, %3\", operands);
5668      output_asm_insn (\"str\\t%1, %0\", operands);
5669    }
5670
5671  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5672    {
5673    case 4:  return \"b%d5\\t%l4\";
5674    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5675    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5676    }
5677  }"
5678  [(set (attr "far_jump")
5679        (if_then_else
5680	    (ior (and (eq (symbol_ref ("which_alternative"))
5681	                  (const_int 0))
5682		      (eq_attr "length" "8"))
5683		 (eq_attr "length" "10"))
5684	    (const_string "yes")
5685            (const_string "no")))
5686   (set (attr "length")
5687     (if_then_else
5688       (eq (symbol_ref ("which_alternative"))
5689		       (const_int 0))
5690       (if_then_else
5691	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5692	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5693	 (const_int 4)
5694	 (if_then_else
5695	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5696		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5697	   (const_int 6)
5698	   (const_int 8)))
5699       (if_then_else
5700	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5701	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5702	 (const_int 6)
5703	 (if_then_else
5704	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5705		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5706	   (const_int 8)
5707	   (const_int 10)))))]
5708)
5709
5710(define_insn "*orrsi3_cbranch_scratch"
5711  [(set (pc)
5712	(if_then_else
5713	 (match_operator 4 "equality_operator"
5714	  [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5715		   (match_operand:SI 2 "s_register_operand" "l"))
5716	   (const_int 0)])
5717	 (label_ref (match_operand 3 "" ""))
5718	 (pc)))
5719   (clobber (match_scratch:SI 0 "=l"))]
5720  "TARGET_THUMB"
5721  "*
5722  {
5723  output_asm_insn (\"orr\\t%0, %2\", operands);
5724  switch (get_attr_length (insn))
5725    {
5726    case 4:  return \"b%d4\\t%l3\";
5727    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5728    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5729    }
5730  }"
5731  [(set (attr "far_jump")
5732        (if_then_else
5733	    (eq_attr "length" "8")
5734	    (const_string "yes")
5735            (const_string "no")))
5736   (set (attr "length") 
5737        (if_then_else
5738	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5739	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5740	    (const_int 4)
5741	    (if_then_else
5742	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5743		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5744		(const_int 6)
5745		(const_int 8))))]
5746)
5747  
5748(define_insn "*orrsi3_cbranch"
5749  [(set (pc)
5750	(if_then_else
5751	 (match_operator 5 "equality_operator"
5752	  [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5753		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5754	   (const_int 0)])
5755	 (label_ref (match_operand 4 "" ""))
5756	 (pc)))
5757   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5758	(ior:SI (match_dup 2) (match_dup 3)))
5759   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5760  "TARGET_THUMB"
5761  "*
5762  {
5763  if (which_alternative == 0)
5764    output_asm_insn (\"orr\\t%0, %3\", operands);
5765  else if (which_alternative == 1)
5766    {
5767      output_asm_insn (\"orr\\t%1, %3\", operands);
5768      output_asm_insn (\"mov\\t%0, %1\", operands);
5769    }
5770  else
5771    {
5772      output_asm_insn (\"orr\\t%1, %3\", operands);
5773      output_asm_insn (\"str\\t%1, %0\", operands);
5774    }
5775
5776  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5777    {
5778    case 4:  return \"b%d5\\t%l4\";
5779    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5780    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5781    }
5782  }"
5783  [(set (attr "far_jump")
5784        (if_then_else
5785	    (ior (and (eq (symbol_ref ("which_alternative"))
5786	                  (const_int 0))
5787		      (eq_attr "length" "8"))
5788		 (eq_attr "length" "10"))
5789	    (const_string "yes")
5790            (const_string "no")))
5791   (set (attr "length")
5792     (if_then_else
5793       (eq (symbol_ref ("which_alternative"))
5794		       (const_int 0))
5795       (if_then_else
5796	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5797	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5798	 (const_int 4)
5799	 (if_then_else
5800	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5801		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5802	   (const_int 6)
5803	   (const_int 8)))
5804       (if_then_else
5805	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5806	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5807	 (const_int 6)
5808	 (if_then_else
5809	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5810		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5811	   (const_int 8)
5812	   (const_int 10)))))]
5813)
5814
5815(define_insn "*xorsi3_cbranch_scratch"
5816  [(set (pc)
5817	(if_then_else
5818	 (match_operator 4 "equality_operator"
5819	  [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
5820		   (match_operand:SI 2 "s_register_operand" "l"))
5821	   (const_int 0)])
5822	 (label_ref (match_operand 3 "" ""))
5823	 (pc)))
5824   (clobber (match_scratch:SI 0 "=l"))]
5825  "TARGET_THUMB"
5826  "*
5827  {
5828  output_asm_insn (\"eor\\t%0, %2\", operands);
5829  switch (get_attr_length (insn))
5830    {
5831    case 4:  return \"b%d4\\t%l3\";
5832    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5833    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5834    }
5835  }"
5836  [(set (attr "far_jump")
5837        (if_then_else
5838	    (eq_attr "length" "8")
5839	    (const_string "yes")
5840            (const_string "no")))
5841   (set (attr "length") 
5842        (if_then_else
5843	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5844	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5845	    (const_int 4)
5846	    (if_then_else
5847	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5848		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5849		(const_int 6)
5850		(const_int 8))))]
5851)
5852  
5853(define_insn "*xorsi3_cbranch"
5854  [(set (pc)
5855	(if_then_else
5856	 (match_operator 5 "equality_operator"
5857	  [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5858		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5859	   (const_int 0)])
5860	 (label_ref (match_operand 4 "" ""))
5861	 (pc)))
5862   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5863	(xor:SI (match_dup 2) (match_dup 3)))
5864   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5865  "TARGET_THUMB"
5866  "*
5867  {
5868  if (which_alternative == 0)
5869    output_asm_insn (\"eor\\t%0, %3\", operands);
5870  else if (which_alternative == 1)
5871    {
5872      output_asm_insn (\"eor\\t%1, %3\", operands);
5873      output_asm_insn (\"mov\\t%0, %1\", operands);
5874    }
5875  else
5876    {
5877      output_asm_insn (\"eor\\t%1, %3\", operands);
5878      output_asm_insn (\"str\\t%1, %0\", operands);
5879    }
5880
5881  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5882    {
5883    case 4:  return \"b%d5\\t%l4\";
5884    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5885    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5886    }
5887  }"
5888  [(set (attr "far_jump")
5889        (if_then_else
5890	    (ior (and (eq (symbol_ref ("which_alternative"))
5891	                  (const_int 0))
5892		      (eq_attr "length" "8"))
5893		 (eq_attr "length" "10"))
5894	    (const_string "yes")
5895            (const_string "no")))
5896   (set (attr "length")
5897     (if_then_else
5898       (eq (symbol_ref ("which_alternative"))
5899		       (const_int 0))
5900       (if_then_else
5901	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5902	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5903	 (const_int 4)
5904	 (if_then_else
5905	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5906		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5907	   (const_int 6)
5908	   (const_int 8)))
5909       (if_then_else
5910	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5911	      (le (minus (match_dup 4) (pc)) (const_int 256)))
5912	 (const_int 6)
5913	 (if_then_else
5914	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5915		(le (minus (match_dup 4) (pc)) (const_int 2048)))
5916	   (const_int 8)
5917	   (const_int 10)))))]
5918)
5919
5920(define_insn "*bicsi3_cbranch_scratch"
5921  [(set (pc)
5922	(if_then_else
5923	 (match_operator 4 "equality_operator"
5924	  [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
5925		   (match_operand:SI 1 "s_register_operand" "0"))
5926	   (const_int 0)])
5927	 (label_ref (match_operand 3 "" ""))
5928	 (pc)))
5929   (clobber (match_scratch:SI 0 "=l"))]
5930  "TARGET_THUMB"
5931  "*
5932  {
5933  output_asm_insn (\"bic\\t%0, %2\", operands);
5934  switch (get_attr_length (insn))
5935    {
5936    case 4:  return \"b%d4\\t%l3\";
5937    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5938    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5939    }
5940  }"
5941  [(set (attr "far_jump")
5942        (if_then_else
5943	    (eq_attr "length" "8")
5944	    (const_string "yes")
5945            (const_string "no")))
5946   (set (attr "length") 
5947        (if_then_else
5948	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5949	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5950	    (const_int 4)
5951	    (if_then_else
5952	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5953		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5954		(const_int 6)
5955		(const_int 8))))]
5956)
5957  
5958(define_insn "*bicsi3_cbranch"
5959  [(set (pc)
5960	(if_then_else
5961	 (match_operator 5 "equality_operator"
5962	  [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
5963		   (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
5964	   (const_int 0)])
5965	 (label_ref (match_operand 4 "" ""))
5966	 (pc)))
5967   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
5968	(and:SI (not:SI (match_dup 3)) (match_dup 2)))
5969   (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
5970  "TARGET_THUMB"
5971  "*
5972  {
5973  if (which_alternative == 0)
5974    output_asm_insn (\"bic\\t%0, %3\", operands);
5975  else if (which_alternative <= 2)
5976    {
5977      output_asm_insn (\"bic\\t%1, %3\", operands);
5978      /* It's ok if OP0 is a lo-reg, even though the mov will set the
5979	 conditions again, since we're only testing for equality.  */
5980      output_asm_insn (\"mov\\t%0, %1\", operands);
5981    }
5982  else
5983    {
5984      output_asm_insn (\"bic\\t%1, %3\", operands);
5985      output_asm_insn (\"str\\t%1, %0\", operands);
5986    }
5987
5988  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5989    {
5990    case 4:  return \"b%d5\\t%l4\";
5991    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5992    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5993    }
5994  }"
5995  [(set (attr "far_jump")
5996        (if_then_else
5997	    (ior (and (eq (symbol_ref ("which_alternative"))
5998	                  (const_int 0))
5999		      (eq_attr "length" "8"))
6000		 (eq_attr "length" "10"))
6001	    (const_string "yes")
6002            (const_string "no")))
6003   (set (attr "length")
6004     (if_then_else
6005       (eq (symbol_ref ("which_alternative"))
6006		       (const_int 0))
6007       (if_then_else
6008	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6009	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6010	 (const_int 4)
6011	 (if_then_else
6012	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6013		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6014	   (const_int 6)
6015	   (const_int 8)))
6016       (if_then_else
6017	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6018	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6019	 (const_int 6)
6020	 (if_then_else
6021	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6022		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6023	   (const_int 8)
6024	   (const_int 10)))))]
6025)
6026
6027(define_insn "*cbranchne_decr1"
6028  [(set (pc)
6029	(if_then_else (match_operator 3 "equality_operator"
6030		       [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6031		        (const_int 0)])
6032		      (label_ref (match_operand 4 "" ""))
6033		      (pc)))
6034   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6035	(plus:SI (match_dup 2) (const_int -1)))
6036   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6037  "TARGET_THUMB"
6038  "*
6039   {
6040     rtx cond[2];
6041     cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6042				? GEU : LTU),
6043			       VOIDmode, operands[2], const1_rtx);
6044     cond[1] = operands[4];
6045
6046     if (which_alternative == 0)
6047       output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6048     else if (which_alternative == 1)
6049       {
6050	 /* We must provide an alternative for a hi reg because reload 
6051	    cannot handle output reloads on a jump instruction, but we
6052	    can't subtract into that.  Fortunately a mov from lo to hi
6053	    does not clobber the condition codes.  */
6054	 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6055	 output_asm_insn (\"mov\\t%0, %1\", operands);
6056       }
6057     else
6058       {
6059	 /* Similarly, but the target is memory.  */
6060	 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6061	 output_asm_insn (\"str\\t%1, %0\", operands);
6062       }
6063
6064     switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6065       {
6066	 case 4:
6067	   output_asm_insn (\"b%d0\\t%l1\", cond);
6068	   return \"\";
6069	 case 6:
6070	   output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6071	   return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6072	 default:
6073	   output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6074	   return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6075       }
6076   }
6077  "
6078  [(set (attr "far_jump")
6079        (if_then_else
6080	    (ior (and (eq (symbol_ref ("which_alternative"))
6081	                  (const_int 0))
6082		      (eq_attr "length" "8"))
6083		 (eq_attr "length" "10"))
6084	    (const_string "yes")
6085            (const_string "no")))
6086   (set_attr_alternative "length"
6087      [
6088       ;; Alternative 0
6089       (if_then_else
6090	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6091	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6092	 (const_int 4)
6093	 (if_then_else
6094	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6095		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6096	   (const_int 6)
6097	   (const_int 8)))
6098       ;; Alternative 1
6099       (if_then_else
6100	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6101	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6102	 (const_int 6)
6103	 (if_then_else
6104	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6105		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6106	   (const_int 8)
6107	   (const_int 10)))
6108       ;; Alternative 2
6109       (if_then_else
6110	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6111	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6112	 (const_int 6)
6113	 (if_then_else
6114	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6115		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6116	   (const_int 8)
6117	   (const_int 10)))
6118       ;; Alternative 3
6119       (if_then_else
6120	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6121	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6122	 (const_int 6)
6123	 (if_then_else
6124	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6125		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6126	   (const_int 8)
6127	   (const_int 10)))])]
6128)
6129
6130(define_insn "*addsi3_cbranch"
6131  [(set (pc)
6132	(if_then_else
6133	 (match_operator 4 "comparison_operator"
6134	  [(plus:SI
6135	    (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6136	    (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6137	   (const_int 0)])
6138	 (label_ref (match_operand 5 "" ""))
6139	 (pc)))
6140   (set
6141    (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6142    (plus:SI (match_dup 2) (match_dup 3)))
6143   (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6144  "TARGET_THUMB
6145   && (GET_CODE (operands[4]) == EQ
6146       || GET_CODE (operands[4]) == NE
6147       || GET_CODE (operands[4]) == GE
6148       || GET_CODE (operands[4]) == LT)"
6149  "*
6150   {
6151     rtx cond[3];
6152
6153     
6154     cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6155     cond[1] = operands[2];
6156     cond[2] = operands[3];
6157
6158     if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6159       output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6160     else
6161       output_asm_insn (\"add\\t%0, %1, %2\", cond);
6162
6163     if (which_alternative >= 3
6164	 && which_alternative < 4)
6165       output_asm_insn (\"mov\\t%0, %1\", operands);
6166     else if (which_alternative >= 4)
6167       output_asm_insn (\"str\\t%1, %0\", operands);
6168
6169     switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6170       {
6171	 case 4:
6172	   return \"b%d4\\t%l5\";
6173	 case 6:
6174	   return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6175	 default:
6176	   return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6177       }
6178   }
6179  "
6180  [(set (attr "far_jump")
6181        (if_then_else
6182	    (ior (and (lt (symbol_ref ("which_alternative"))
6183	                  (const_int 3))
6184		      (eq_attr "length" "8"))
6185		 (eq_attr "length" "10"))
6186	    (const_string "yes")
6187            (const_string "no")))
6188   (set (attr "length")
6189     (if_then_else
6190       (lt (symbol_ref ("which_alternative"))
6191		       (const_int 3))
6192       (if_then_else
6193	 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6194	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6195	 (const_int 4)
6196	 (if_then_else
6197	   (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6198		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6199	   (const_int 6)
6200	   (const_int 8)))
6201       (if_then_else
6202	 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6203	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6204	 (const_int 6)
6205	 (if_then_else
6206	   (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6207		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6208	   (const_int 8)
6209	   (const_int 10)))))]
6210)
6211
6212(define_insn "*addsi3_cbranch_scratch"
6213  [(set (pc)
6214	(if_then_else
6215	 (match_operator 3 "comparison_operator"
6216	  [(plus:SI
6217	    (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6218	    (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6219	   (const_int 0)])
6220	 (label_ref (match_operand 4 "" ""))
6221	 (pc)))
6222   (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6223  "TARGET_THUMB
6224   && (GET_CODE (operands[3]) == EQ
6225       || GET_CODE (operands[3]) == NE
6226       || GET_CODE (operands[3]) == GE
6227       || GET_CODE (operands[3]) == LT)"
6228  "*
6229   {
6230     switch (which_alternative)
6231       {
6232       case 0:
6233	 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6234	 break;
6235       case 1:
6236	 output_asm_insn (\"cmn\t%1, %2\", operands);
6237	 break;
6238       case 2:
6239	 output_asm_insn (\"add\t%0, %1, %2\", operands);
6240	 break;
6241       case 3:
6242	 output_asm_insn (\"add\t%0, %0, %2\", operands);
6243	 break;
6244       }
6245
6246     switch (get_attr_length (insn))
6247       {
6248	 case 4:
6249	   return \"b%d3\\t%l4\";
6250	 case 6:
6251	   return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6252	 default:
6253	   return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6254       }
6255   }
6256  "
6257  [(set (attr "far_jump")
6258        (if_then_else
6259	    (eq_attr "length" "8")
6260	    (const_string "yes")
6261            (const_string "no")))
6262   (set (attr "length")
6263       (if_then_else
6264	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6265	      (le (minus (match_dup 4) (pc)) (const_int 256)))
6266	 (const_int 4)
6267	 (if_then_else
6268	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6269		(le (minus (match_dup 4) (pc)) (const_int 2048)))
6270	   (const_int 6)
6271	   (const_int 8))))]
6272)
6273
6274(define_insn "*subsi3_cbranch"
6275  [(set (pc)
6276	(if_then_else
6277	 (match_operator 4 "comparison_operator"
6278	  [(minus:SI
6279	    (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6280	    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6281	   (const_int 0)])
6282	 (label_ref (match_operand 5 "" ""))
6283	 (pc)))
6284   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6285	(minus:SI (match_dup 2) (match_dup 3)))
6286   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6287  "TARGET_THUMB
6288   && (GET_CODE (operands[4]) == EQ
6289       || GET_CODE (operands[4]) == NE
6290       || GET_CODE (operands[4]) == GE
6291       || GET_CODE (operands[4]) == LT)"
6292  "*
6293   {
6294     if (which_alternative == 0)
6295       output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6296     else if (which_alternative == 1)
6297       {
6298	 /* We must provide an alternative for a hi reg because reload 
6299	    cannot handle output reloads on a jump instruction, but we
6300	    can't subtract into that.  Fortunately a mov from lo to hi
6301	    does not clobber the condition codes.  */
6302	 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6303	 output_asm_insn (\"mov\\t%0, %1\", operands);
6304       }
6305     else
6306       {
6307	 /* Similarly, but the target is memory.  */
6308	 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6309	 output_asm_insn (\"str\\t%1, %0\", operands);
6310       }
6311
6312     switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6313       {
6314	 case 4:
6315	   return \"b%d4\\t%l5\";
6316	 case 6:
6317	   return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6318	 default:
6319	   return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6320       }
6321   }
6322  "
6323  [(set (attr "far_jump")
6324        (if_then_else
6325	    (ior (and (eq (symbol_ref ("which_alternative"))
6326	                  (const_int 0))
6327		      (eq_attr "length" "8"))
6328		 (eq_attr "length" "10"))
6329	    (const_string "yes")
6330            (const_string "no")))
6331   (set (attr "length")
6332     (if_then_else
6333       (eq (symbol_ref ("which_alternative"))
6334		       (const_int 0))
6335       (if_then_else
6336	 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6337	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6338	 (const_int 4)
6339	 (if_then_else
6340	   (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6341		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6342	   (const_int 6)
6343	   (const_int 8)))
6344       (if_then_else
6345	 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6346	      (le (minus (match_dup 5) (pc)) (const_int 256)))
6347	 (const_int 6)
6348	 (if_then_else
6349	   (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6350		(le (minus (match_dup 5) (pc)) (const_int 2048)))
6351	   (const_int 8)
6352	   (const_int 10)))))]
6353)
6354
6355(define_insn "*subsi3_cbranch_scratch"
6356  [(set (pc)
6357	(if_then_else
6358	 (match_operator 0 "arm_comparison_operator"
6359	  [(minus:SI (match_operand:SI 1 "register_operand" "l")
6360		     (match_operand:SI 2 "nonmemory_operand" "l"))
6361	   (const_int 0)])
6362	 (label_ref (match_operand 3 "" ""))
6363	 (pc)))]
6364  "TARGET_THUMB
6365   && (GET_CODE (operands[0]) == EQ
6366       || GET_CODE (operands[0]) == NE
6367       || GET_CODE (operands[0]) == GE
6368       || GET_CODE (operands[0]) == LT)"
6369  "*
6370  output_asm_insn (\"cmp\\t%1, %2\", operands);
6371  switch (get_attr_length (insn))
6372    {
6373    case 4:  return \"b%d0\\t%l3\";
6374    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6375    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6376    }
6377  "
6378  [(set (attr "far_jump")
6379        (if_then_else
6380	    (eq_attr "length" "8")
6381	    (const_string "yes")
6382            (const_string "no")))
6383   (set (attr "length") 
6384        (if_then_else
6385	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6386	         (le (minus (match_dup 3) (pc)) (const_int 256)))
6387	    (const_int 4)
6388	    (if_then_else
6389	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6390		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
6391		(const_int 6)
6392		(const_int 8))))]
6393)
6394
6395;; Comparison and test insns
6396
6397(define_expand "cmpsi"
6398  [(match_operand:SI 0 "s_register_operand" "")
6399   (match_operand:SI 1 "arm_add_operand" "")]
6400  "TARGET_ARM"
6401  "{
6402    arm_compare_op0 = operands[0];
6403    arm_compare_op1 = operands[1];
6404    DONE;
6405  }"
6406)
6407
6408(define_expand "cmpsf"
6409  [(match_operand:SF 0 "s_register_operand" "")
6410   (match_operand:SF 1 "fpa_rhs_operand" "")]
6411  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6412  "
6413  if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
6414    operands[1] = force_reg (SFmode, operands[1]);
6415
6416  arm_compare_op0 = operands[0];
6417  arm_compare_op1 = operands[1];
6418  DONE;
6419  "
6420)
6421
6422(define_expand "cmpdf"
6423  [(match_operand:DF 0 "s_register_operand" "")
6424   (match_operand:DF 1 "fpa_rhs_operand" "")]
6425  "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6426  "
6427  if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
6428    operands[1] = force_reg (DFmode, operands[1]);
6429
6430  arm_compare_op0 = operands[0];
6431  arm_compare_op1 = operands[1];
6432  DONE;
6433  "
6434)
6435
6436(define_insn "*arm_cmpsi_insn"
6437  [(set (reg:CC CC_REGNUM)
6438	(compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6439		    (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6440  "TARGET_ARM"
6441  "@
6442   cmp%?\\t%0, %1
6443   cmn%?\\t%0, #%n1"
6444  [(set_attr "conds" "set")]
6445)
6446
6447(define_insn "*cmpsi_shiftsi"
6448  [(set (reg:CC CC_REGNUM)
6449	(compare:CC (match_operand:SI   0 "s_register_operand" "r")
6450		    (match_operator:SI  3 "shift_operator"
6451		     [(match_operand:SI 1 "s_register_operand" "r")
6452		      (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6453  "TARGET_ARM"
6454  "cmp%?\\t%0, %1%S3"
6455  [(set_attr "conds" "set")
6456   (set_attr "shift" "1")
6457   ]
6458)
6459
6460(define_insn "*cmpsi_shiftsi_swp"
6461  [(set (reg:CC_SWP CC_REGNUM)
6462	(compare:CC_SWP (match_operator:SI 3 "shift_operator"
6463			 [(match_operand:SI 1 "s_register_operand" "r")
6464			  (match_operand:SI 2 "reg_or_int_operand" "rM")])
6465			(match_operand:SI 0 "s_register_operand" "r")))]
6466  "TARGET_ARM"
6467  "cmp%?\\t%0, %1%S3"
6468  [(set_attr "conds" "set")
6469   (set_attr "shift" "1")
6470   ]
6471)
6472
6473(define_insn "*cmpsi_neg_shiftsi"
6474  [(set (reg:CC CC_REGNUM)
6475	(compare:CC (match_operand:SI 0 "s_register_operand" "r")
6476		    (neg:SI (match_operator:SI 3 "shift_operator"
6477			     [(match_operand:SI 1 "s_register_operand" "r")
6478			      (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6479  "TARGET_ARM"
6480  "cmn%?\\t%0, %1%S3"
6481  [(set_attr "conds" "set")
6482   (set_attr "shift" "1")
6483   ]
6484)
6485
6486;; Cirrus SF compare instruction
6487(define_insn "*cirrus_cmpsf"
6488  [(set (reg:CCFP CC_REGNUM)
6489	(compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6490		      (match_operand:SF 1 "cirrus_fp_register" "v")))]
6491  "TARGET_ARM && TARGET_CIRRUS"
6492  "cfcmps%?\\tr15, %V0, %V1"
6493  [(set_attr "type"   "mav_farith")
6494   (set_attr "cirrus" "compare")]
6495)
6496
6497;; Cirrus DF compare instruction
6498(define_insn "*cirrus_cmpdf"
6499  [(set (reg:CCFP CC_REGNUM)
6500	(compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6501		      (match_operand:DF 1 "cirrus_fp_register" "v")))]
6502  "TARGET_ARM && TARGET_CIRRUS"
6503  "cfcmpd%?\\tr15, %V0, %V1"
6504  [(set_attr "type"   "mav_farith")
6505   (set_attr "cirrus" "compare")]
6506)
6507
6508;; Cirrus DI compare instruction
6509(define_expand "cmpdi"
6510  [(match_operand:DI 0 "cirrus_fp_register" "")
6511   (match_operand:DI 1 "cirrus_fp_register" "")]
6512  "TARGET_ARM && TARGET_CIRRUS"
6513  "{
6514     arm_compare_op0 = operands[0];
6515     arm_compare_op1 = operands[1];
6516     DONE;
6517   }")
6518
6519(define_insn "*cirrus_cmpdi"
6520  [(set (reg:CC CC_REGNUM)
6521	(compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6522		    (match_operand:DI 1 "cirrus_fp_register" "v")))]
6523  "TARGET_ARM && TARGET_CIRRUS"
6524  "cfcmp64%?\\tr15, %V0, %V1"
6525  [(set_attr "type"   "mav_farith")
6526   (set_attr "cirrus" "compare")]
6527)
6528
6529; This insn allows redundant compares to be removed by cse, nothing should
6530; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6531; is deleted later on. The match_dup will match the mode here, so that
6532; mode changes of the condition codes aren't lost by this even though we don't
6533; specify what they are.
6534
6535(define_insn "*deleted_compare"
6536  [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6537  "TARGET_ARM"
6538  "\\t%@ deleted compare"
6539  [(set_attr "conds" "set")
6540   (set_attr "length" "0")]
6541)
6542
6543
6544;; Conditional branch insns
6545
6546(define_expand "beq"
6547  [(set (pc)
6548	(if_then_else (eq (match_dup 1) (const_int 0))
6549		      (label_ref (match_operand 0 "" ""))
6550		      (pc)))]
6551  "TARGET_ARM"
6552  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6553)
6554
6555(define_expand "bne"
6556  [(set (pc)
6557	(if_then_else (ne (match_dup 1) (const_int 0))
6558		      (label_ref (match_operand 0 "" ""))
6559		      (pc)))]
6560  "TARGET_ARM"
6561  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6562)
6563
6564(define_expand "bgt"
6565  [(set (pc)
6566	(if_then_else (gt (match_dup 1) (const_int 0))
6567		      (label_ref (match_operand 0 "" ""))
6568		      (pc)))]
6569  "TARGET_ARM"
6570  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6571)
6572
6573(define_expand "ble"
6574  [(set (pc)
6575	(if_then_else (le (match_dup 1) (const_int 0))
6576		      (label_ref (match_operand 0 "" ""))
6577		      (pc)))]
6578  "TARGET_ARM"
6579  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6580)
6581
6582(define_expand "bge"
6583  [(set (pc)
6584	(if_then_else (ge (match_dup 1) (const_int 0))
6585		      (label_ref (match_operand 0 "" ""))
6586		      (pc)))]
6587  "TARGET_ARM"
6588  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6589)
6590
6591(define_expand "blt"
6592  [(set (pc)
6593	(if_then_else (lt (match_dup 1) (const_int 0))
6594		      (label_ref (match_operand 0 "" ""))
6595		      (pc)))]
6596  "TARGET_ARM"
6597  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6598)
6599
6600(define_expand "bgtu"
6601  [(set (pc)
6602	(if_then_else (gtu (match_dup 1) (const_int 0))
6603		      (label_ref (match_operand 0 "" ""))
6604		      (pc)))]
6605  "TARGET_ARM"
6606  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6607)
6608
6609(define_expand "bleu"
6610  [(set (pc)
6611	(if_then_else (leu (match_dup 1) (const_int 0))
6612		      (label_ref (match_operand 0 "" ""))
6613		      (pc)))]
6614  "TARGET_ARM"
6615  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6616)
6617
6618(define_expand "bgeu"
6619  [(set (pc)
6620	(if_then_else (geu (match_dup 1) (const_int 0))
6621		      (label_ref (match_operand 0 "" ""))
6622		      (pc)))]
6623  "TARGET_ARM"
6624  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6625)
6626
6627(define_expand "bltu"
6628  [(set (pc)
6629	(if_then_else (ltu (match_dup 1) (const_int 0))
6630		      (label_ref (match_operand 0 "" ""))
6631		      (pc)))]
6632  "TARGET_ARM"
6633  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6634)
6635
6636(define_expand "bunordered"
6637  [(set (pc)
6638	(if_then_else (unordered (match_dup 1) (const_int 0))
6639		      (label_ref (match_operand 0 "" ""))
6640		      (pc)))]
6641  "TARGET_ARM && TARGET_HARD_FLOAT"
6642  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6643				      arm_compare_op1);"
6644)
6645
6646(define_expand "bordered"
6647  [(set (pc)
6648	(if_then_else (ordered (match_dup 1) (const_int 0))
6649		      (label_ref (match_operand 0 "" ""))
6650		      (pc)))]
6651  "TARGET_ARM && TARGET_HARD_FLOAT"
6652  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6653				      arm_compare_op1);"
6654)
6655
6656(define_expand "bungt"
6657  [(set (pc)
6658	(if_then_else (ungt (match_dup 1) (const_int 0))
6659		      (label_ref (match_operand 0 "" ""))
6660		      (pc)))]
6661  "TARGET_ARM && TARGET_HARD_FLOAT"
6662  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6663)
6664
6665(define_expand "bunlt"
6666  [(set (pc)
6667	(if_then_else (unlt (match_dup 1) (const_int 0))
6668		      (label_ref (match_operand 0 "" ""))
6669		      (pc)))]
6670  "TARGET_ARM && TARGET_HARD_FLOAT"
6671  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6672)
6673
6674(define_expand "bunge"
6675  [(set (pc)
6676	(if_then_else (unge (match_dup 1) (const_int 0))
6677		      (label_ref (match_operand 0 "" ""))
6678		      (pc)))]
6679  "TARGET_ARM && TARGET_HARD_FLOAT"
6680  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6681)
6682
6683(define_expand "bunle"
6684  [(set (pc)
6685	(if_then_else (unle (match_dup 1) (const_int 0))
6686		      (label_ref (match_operand 0 "" ""))
6687		      (pc)))]
6688  "TARGET_ARM && TARGET_HARD_FLOAT"
6689  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6690)
6691
6692;; The following two patterns need two branch instructions, since there is
6693;; no single instruction that will handle all cases.
6694(define_expand "buneq"
6695  [(set (pc)
6696	(if_then_else (uneq (match_dup 1) (const_int 0))
6697		      (label_ref (match_operand 0 "" ""))
6698		      (pc)))]
6699  "TARGET_ARM && TARGET_HARD_FLOAT"
6700  "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6701)
6702
6703(define_expand "bltgt"
6704  [(set (pc)
6705	(if_then_else (ltgt (match_dup 1) (const_int 0))
6706		      (label_ref (match_operand 0 "" ""))
6707		      (pc)))]
6708  "TARGET_ARM && TARGET_HARD_FLOAT"
6709  "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6710)
6711
6712;;
6713;; Patterns to match conditional branch insns.
6714;;
6715
6716; Special pattern to match UNEQ.
6717(define_insn "*arm_buneq"
6718  [(set (pc)
6719	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6720		      (label_ref (match_operand 0 "" ""))
6721		      (pc)))]
6722  "TARGET_ARM && TARGET_HARD_FLOAT"
6723  "*
6724  if (arm_ccfsm_state != 0)
6725    abort ();
6726
6727  return \"bvs\\t%l0\;beq\\t%l0\";
6728  "
6729  [(set_attr "conds" "jump_clob")
6730   (set_attr "length" "8")]
6731)
6732
6733; Special pattern to match LTGT.
6734(define_insn "*arm_bltgt"
6735  [(set (pc)
6736	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6737		      (label_ref (match_operand 0 "" ""))
6738		      (pc)))]
6739  "TARGET_ARM && TARGET_HARD_FLOAT"
6740  "*
6741  if (arm_ccfsm_state != 0)
6742    abort ();
6743
6744  return \"bmi\\t%l0\;bgt\\t%l0\";
6745  "
6746  [(set_attr "conds" "jump_clob")
6747   (set_attr "length" "8")]
6748)
6749
6750(define_insn "*arm_cond_branch"
6751  [(set (pc)
6752	(if_then_else (match_operator 1 "arm_comparison_operator"
6753		       [(match_operand 2 "cc_register" "") (const_int 0)])
6754		      (label_ref (match_operand 0 "" ""))
6755		      (pc)))]
6756  "TARGET_ARM"
6757  "*
6758  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6759    {
6760      arm_ccfsm_state += 2;
6761      return \"\";
6762    }
6763  return \"b%d1\\t%l0\";
6764  "
6765  [(set_attr "conds" "use")]
6766)
6767
6768; Special pattern to match reversed UNEQ.
6769(define_insn "*arm_buneq_reversed"
6770  [(set (pc)
6771	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6772		      (pc)
6773		      (label_ref (match_operand 0 "" ""))))]
6774  "TARGET_ARM && TARGET_HARD_FLOAT"
6775  "*
6776  if (arm_ccfsm_state != 0)
6777    abort ();
6778
6779  return \"bmi\\t%l0\;bgt\\t%l0\";
6780  "
6781  [(set_attr "conds" "jump_clob")
6782   (set_attr "length" "8")]
6783)
6784
6785; Special pattern to match reversed LTGT.
6786(define_insn "*arm_bltgt_reversed"
6787  [(set (pc)
6788	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6789		      (pc)
6790		      (label_ref (match_operand 0 "" ""))))]
6791  "TARGET_ARM && TARGET_HARD_FLOAT"
6792  "*
6793  if (arm_ccfsm_state != 0)
6794    abort ();
6795
6796  return \"bvs\\t%l0\;beq\\t%l0\";
6797  "
6798  [(set_attr "conds" "jump_clob")
6799   (set_attr "length" "8")]
6800)
6801
6802(define_insn "*arm_cond_branch_reversed"
6803  [(set (pc)
6804	(if_then_else (match_operator 1 "arm_comparison_operator"
6805		       [(match_operand 2 "cc_register" "") (const_int 0)])
6806		      (pc)
6807		      (label_ref (match_operand 0 "" ""))))]
6808  "TARGET_ARM"
6809  "*
6810  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6811    {
6812      arm_ccfsm_state += 2;
6813      return \"\";
6814    }
6815  return \"b%D1\\t%l0\";
6816  "
6817  [(set_attr "conds" "use")]
6818)
6819
6820
6821
6822; scc insns
6823
6824(define_expand "seq"
6825  [(set (match_operand:SI 0 "s_register_operand" "")
6826	(eq:SI (match_dup 1) (const_int 0)))]
6827  "TARGET_ARM"
6828  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6829)
6830
6831(define_expand "sne"
6832  [(set (match_operand:SI 0 "s_register_operand" "")
6833	(ne:SI (match_dup 1) (const_int 0)))]
6834  "TARGET_ARM"
6835  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6836)
6837
6838(define_expand "sgt"
6839  [(set (match_operand:SI 0 "s_register_operand" "")
6840	(gt:SI (match_dup 1) (const_int 0)))]
6841  "TARGET_ARM"
6842  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6843)
6844
6845(define_expand "sle"
6846  [(set (match_operand:SI 0 "s_register_operand" "")
6847	(le:SI (match_dup 1) (const_int 0)))]
6848  "TARGET_ARM"
6849  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6850)
6851
6852(define_expand "sge"
6853  [(set (match_operand:SI 0 "s_register_operand" "")
6854	(ge:SI (match_dup 1) (const_int 0)))]
6855  "TARGET_ARM"
6856  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6857)
6858
6859(define_expand "slt"
6860  [(set (match_operand:SI 0 "s_register_operand" "")
6861	(lt:SI (match_dup 1) (const_int 0)))]
6862  "TARGET_ARM"
6863  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6864)
6865
6866(define_expand "sgtu"
6867  [(set (match_operand:SI 0 "s_register_operand" "")
6868	(gtu:SI (match_dup 1) (const_int 0)))]
6869  "TARGET_ARM"
6870  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6871)
6872
6873(define_expand "sleu"
6874  [(set (match_operand:SI 0 "s_register_operand" "")
6875	(leu:SI (match_dup 1) (const_int 0)))]
6876  "TARGET_ARM"
6877  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6878)
6879
6880(define_expand "sgeu"
6881  [(set (match_operand:SI 0 "s_register_operand" "")
6882	(geu:SI (match_dup 1) (const_int 0)))]
6883  "TARGET_ARM"
6884  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6885)
6886
6887(define_expand "sltu"
6888  [(set (match_operand:SI 0 "s_register_operand" "")
6889	(ltu:SI (match_dup 1) (const_int 0)))]
6890  "TARGET_ARM"
6891  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6892)
6893
6894(define_expand "sunordered"
6895  [(set (match_operand:SI 0 "s_register_operand" "")
6896	(unordered:SI (match_dup 1) (const_int 0)))]
6897  "TARGET_ARM && TARGET_HARD_FLOAT"
6898  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6899				      arm_compare_op1);"
6900)
6901
6902(define_expand "sordered"
6903  [(set (match_operand:SI 0 "s_register_operand" "")
6904	(ordered:SI (match_dup 1) (const_int 0)))]
6905  "TARGET_ARM && TARGET_HARD_FLOAT"
6906  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6907				      arm_compare_op1);"
6908)
6909
6910(define_expand "sungt"
6911  [(set (match_operand:SI 0 "s_register_operand" "")
6912	(ungt:SI (match_dup 1) (const_int 0)))]
6913  "TARGET_ARM && TARGET_HARD_FLOAT"
6914  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6915				      arm_compare_op1);"
6916)
6917
6918(define_expand "sunge"
6919  [(set (match_operand:SI 0 "s_register_operand" "")
6920	(unge:SI (match_dup 1) (const_int 0)))]
6921  "TARGET_ARM && TARGET_HARD_FLOAT"
6922  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6923				      arm_compare_op1);"
6924)
6925
6926(define_expand "sunlt"
6927  [(set (match_operand:SI 0 "s_register_operand" "")
6928	(unlt:SI (match_dup 1) (const_int 0)))]
6929  "TARGET_ARM && TARGET_HARD_FLOAT"
6930  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6931				      arm_compare_op1);"
6932)
6933
6934(define_expand "sunle"
6935  [(set (match_operand:SI 0 "s_register_operand" "")
6936	(unle:SI (match_dup 1) (const_int 0)))]
6937  "TARGET_ARM && TARGET_HARD_FLOAT"
6938  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6939				      arm_compare_op1);"
6940)
6941
6942;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6943;;; simple ARM instructions. 
6944;
6945; (define_expand "suneq"
6946;   [(set (match_operand:SI 0 "s_register_operand" "")
6947; 	(uneq:SI (match_dup 1) (const_int 0)))]
6948;   "TARGET_ARM && TARGET_HARD_FLOAT"
6949;   "abort ();"
6950; )
6951;
6952; (define_expand "sltgt"
6953;   [(set (match_operand:SI 0 "s_register_operand" "")
6954; 	(ltgt:SI (match_dup 1) (const_int 0)))]
6955;   "TARGET_ARM && TARGET_HARD_FLOAT"
6956;   "abort ();"
6957; )
6958
6959(define_insn "*mov_scc"
6960  [(set (match_operand:SI 0 "s_register_operand" "=r")
6961	(match_operator:SI 1 "arm_comparison_operator"
6962	 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6963  "TARGET_ARM"
6964  "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6965  [(set_attr "conds" "use")
6966   (set_attr "length" "8")]
6967)
6968
6969(define_insn "*mov_negscc"
6970  [(set (match_operand:SI 0 "s_register_operand" "=r")
6971	(neg:SI (match_operator:SI 1 "arm_comparison_operator"
6972		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6973  "TARGET_ARM"
6974  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6975  [(set_attr "conds" "use")
6976   (set_attr "length" "8")]
6977)
6978
6979(define_insn "*mov_notscc"
6980  [(set (match_operand:SI 0 "s_register_operand" "=r")
6981	(not:SI (match_operator:SI 1 "arm_comparison_operator"
6982		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6983  "TARGET_ARM"
6984  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6985  [(set_attr "conds" "use")
6986   (set_attr "length" "8")]
6987)
6988
6989
6990;; Conditional move insns
6991
6992(define_expand "movsicc"
6993  [(set (match_operand:SI 0 "s_register_operand" "")
6994	(if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6995			 (match_operand:SI 2 "arm_not_operand" "")
6996			 (match_operand:SI 3 "arm_not_operand" "")))]
6997  "TARGET_ARM"
6998  "
6999  {
7000    enum rtx_code code = GET_CODE (operands[1]);
7001    rtx ccreg;
7002
7003    if (code == UNEQ || code == LTGT)
7004      FAIL;
7005
7006    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7007    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7008  }"
7009)
7010
7011(define_expand "movsfcc"
7012  [(set (match_operand:SF 0 "s_register_operand" "")
7013	(if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7014			 (match_operand:SF 2 "s_register_operand" "")
7015			 (match_operand:SF 3 "nonmemory_operand" "")))]
7016  "TARGET_ARM"
7017  "
7018  {
7019    enum rtx_code code = GET_CODE (operands[1]);
7020    rtx ccreg;
7021
7022    if (code == UNEQ || code == LTGT)
7023      FAIL;
7024
7025    /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7026       Otherwise, ensure it is a valid FP add operand.  */
7027    if ((!TARGET_HARD_FLOAT)
7028        || (!fpa_add_operand (operands[3], SFmode)))
7029      operands[3] = force_reg (SFmode, operands[3]);
7030
7031    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7032    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7033  }"
7034)
7035
7036(define_expand "movdfcc"
7037  [(set (match_operand:DF 0 "s_register_operand" "")
7038	(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7039			 (match_operand:DF 2 "s_register_operand" "")
7040			 (match_operand:DF 3 "fpa_add_operand" "")))]
7041  "TARGET_ARM && TARGET_HARD_FLOAT"
7042  "
7043  {
7044    enum rtx_code code = GET_CODE (operands[1]);
7045    rtx ccreg;
7046
7047    if (code == UNEQ || code == LTGT)
7048      FAIL;
7049
7050    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7051    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7052  }"
7053)
7054
7055(define_insn "*movsicc_insn"
7056  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7057	(if_then_else:SI
7058	 (match_operator 3 "arm_comparison_operator"
7059	  [(match_operand 4 "cc_register" "") (const_int 0)])
7060	 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7061	 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7062  "TARGET_ARM"
7063  "@
7064   mov%D3\\t%0, %2
7065   mvn%D3\\t%0, #%B2
7066   mov%d3\\t%0, %1
7067   mvn%d3\\t%0, #%B1
7068   mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7069   mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7070   mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7071   mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7072  [(set_attr "length" "4,4,4,4,8,8,8,8")
7073   (set_attr "conds" "use")]
7074)
7075
7076(define_insn "*movsfcc_soft_insn"
7077  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7078	(if_then_else:SF (match_operator 3 "arm_comparison_operator"
7079			  [(match_operand 4 "cc_register" "") (const_int 0)])
7080			 (match_operand:SF 1 "s_register_operand" "0,r")
7081			 (match_operand:SF 2 "s_register_operand" "r,0")))]
7082  "TARGET_ARM && TARGET_SOFT_FLOAT"
7083  "@
7084   mov%D3\\t%0, %2
7085   mov%d3\\t%0, %1"
7086  [(set_attr "conds" "use")]
7087)
7088
7089
7090;; Jump and linkage insns
7091
7092(define_expand "jump"
7093  [(set (pc)
7094	(label_ref (match_operand 0 "" "")))]
7095  "TARGET_EITHER"
7096  ""
7097)
7098
7099(define_insn "*arm_jump"
7100  [(set (pc)
7101	(label_ref (match_operand 0 "" "")))]
7102  "TARGET_ARM"
7103  "*
7104  {
7105    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7106      {
7107        arm_ccfsm_state += 2;
7108        return \"\";
7109      }
7110    return \"b%?\\t%l0\";
7111  }
7112  "
7113  [(set_attr "predicable" "yes")]
7114)
7115
7116(define_insn "*thumb_jump"
7117  [(set (pc)
7118	(label_ref (match_operand 0 "" "")))]
7119  "TARGET_THUMB"
7120  "*
7121  if (get_attr_length (insn) == 2)
7122    return \"b\\t%l0\";
7123  return \"bl\\t%l0\\t%@ far jump\";
7124  "
7125  [(set (attr "far_jump")
7126        (if_then_else
7127	    (eq_attr "length" "4")
7128	    (const_string "yes")
7129	    (const_string "no")))
7130   (set (attr "length") 
7131        (if_then_else
7132	    (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7133		 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7134  	    (const_int 2)
7135	    (const_int 4)))]
7136)
7137
7138(define_expand "call"
7139  [(parallel [(call (match_operand 0 "memory_operand" "")
7140	            (match_operand 1 "general_operand" ""))
7141	      (use (match_operand 2 "" ""))
7142	      (clobber (reg:SI LR_REGNUM))])]
7143  "TARGET_EITHER"
7144  "
7145  {
7146    rtx callee;
7147    
7148    /* In an untyped call, we can get NULL for operand 2.  */
7149    if (operands[2] == NULL_RTX)
7150      operands[2] = const0_rtx;
7151      
7152    /* This is to decide if we should generate indirect calls by loading the
7153       32 bit address of the callee into a register before performing the
7154       branch and link.  operand[2] encodes the long_call/short_call
7155       attribute of the function being called.  This attribute is set whenever
7156       __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7157       is used, and the short_call attribute can also be set if function is
7158       declared as static or if it has already been defined in the current
7159       compilation unit.  See arm.c and arm.h for info about this.  The third
7160       parameter to arm_is_longcall_p is used to tell it which pattern
7161       invoked it.  */
7162    callee  = XEXP (operands[0], 0);
7163    
7164    if (GET_CODE (callee) != REG
7165       && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7166      XEXP (operands[0], 0) = force_reg (Pmode, callee);
7167  }"
7168)
7169
7170(define_insn "*call_reg"
7171  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7172         (match_operand 1 "" ""))
7173   (use (match_operand 2 "" ""))
7174   (clobber (reg:SI LR_REGNUM))]
7175  "TARGET_ARM"
7176  "*
7177  return output_call (operands);
7178  "
7179  ;; length is worst case, normally it is only two
7180  [(set_attr "length" "12")
7181   (set_attr "type" "call")]
7182)
7183
7184(define_insn "*call_mem"
7185  [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7186	 (match_operand 1 "" ""))
7187   (use (match_operand 2 "" ""))
7188   (clobber (reg:SI LR_REGNUM))]
7189  "TARGET_ARM"
7190  "*
7191  return output_call_mem (operands);
7192  "
7193  [(set_attr "length" "12")
7194   (set_attr "type" "call")]
7195)
7196
7197(define_insn "*call_indirect"
7198  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7199	 (match_operand 1 "" ""))
7200   (use (match_operand 2 "" ""))
7201   (clobber (reg:SI LR_REGNUM))]
7202  "TARGET_THUMB"
7203  "*
7204  {
7205    if (TARGET_CALLER_INTERWORKING)
7206      return \"bl\\t%__interwork_call_via_%0\";
7207    else
7208      return \"bl\\t%__call_via_%0\";
7209  }"
7210  [(set_attr "type" "call")]
7211)
7212
7213(define_insn "*call_value_indirect"
7214  [(set (match_operand 0 "" "")
7215	(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7216	      (match_operand 2 "" "")))
7217   (use (match_operand 3 "" ""))
7218   (clobber (reg:SI LR_REGNUM))]
7219  "TARGET_THUMB"
7220  "*
7221  {
7222    if (TARGET_CALLER_INTERWORKING)
7223      return \"bl\\t%__interwork_call_via_%1\";
7224    else
7225      return \"bl\\t%__call_via_%1\";
7226  }"
7227  [(set_attr "type" "call")]
7228)
7229
7230(define_expand "call_value"
7231  [(parallel [(set (match_operand       0 "" "")
7232	           (call (match_operand 1 "memory_operand" "")
7233		         (match_operand 2 "general_operand" "")))
7234	      (use (match_operand 3 "" ""))
7235	      (clobber (reg:SI LR_REGNUM))])]
7236  "TARGET_EITHER"
7237  "
7238  {
7239    rtx callee = XEXP (operands[1], 0);
7240    
7241    /* In an untyped call, we can get NULL for operand 2.  */
7242    if (operands[3] == 0)
7243      operands[3] = const0_rtx;
7244      
7245    /* See the comment in define_expand \"call\".  */
7246    if (GET_CODE (callee) != REG
7247	&& arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7248      XEXP (operands[1], 0) = force_reg (Pmode, callee);
7249  }"
7250)
7251
7252(define_insn "*call_value_reg"
7253  [(set (match_operand 0 "" "")
7254        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7255	      (match_operand 2 "" "")))
7256   (use (match_operand 3 "" ""))
7257   (clobber (reg:SI LR_REGNUM))]
7258  "TARGET_ARM"
7259  "*
7260  return output_call (&operands[1]);
7261  "
7262  [(set_attr "length" "12")
7263   (set_attr "type" "call")]
7264)
7265
7266(define_insn "*call_value_mem"
7267  [(set (match_operand 0 "" "")
7268	(call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7269	      (match_operand 2 "" "")))
7270   (use (match_operand 3 "" ""))
7271   (clobber (reg:SI LR_REGNUM))]
7272  "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7273  "*
7274  return output_call_mem (&operands[1]);
7275  "
7276  [(set_attr "length" "12")
7277   (set_attr "type" "call")]
7278)
7279
7280;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7281;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7282
7283(define_insn "*call_symbol"
7284  [(call (mem:SI (match_operand:SI 0 "" ""))
7285	 (match_operand 1 "" ""))
7286   (use (match_operand 2 "" ""))
7287   (clobber (reg:SI LR_REGNUM))]
7288  "TARGET_ARM
7289   && (GET_CODE (operands[0]) == SYMBOL_REF)
7290   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7291  "*
7292  {
7293    return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7294  }"
7295  [(set_attr "type" "call")]
7296)
7297
7298(define_insn "*call_value_symbol"
7299  [(set (match_operand 0 "s_register_operand" "")
7300	(call (mem:SI (match_operand:SI 1 "" ""))
7301	(match_operand:SI 2 "" "")))
7302   (use (match_operand 3 "" ""))
7303   (clobber (reg:SI LR_REGNUM))]
7304  "TARGET_ARM
7305   && (GET_CODE (operands[1]) == SYMBOL_REF)
7306   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7307  "*
7308  {
7309    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7310  }"
7311  [(set_attr "type" "call")]
7312)
7313
7314(define_insn "*call_insn"
7315  [(call (mem:SI (match_operand:SI 0 "" ""))
7316	 (match_operand:SI 1 "" ""))
7317   (use (match_operand 2 "" ""))
7318   (clobber (reg:SI LR_REGNUM))]
7319  "TARGET_THUMB
7320   && GET_CODE (operands[0]) == SYMBOL_REF
7321   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7322  "bl\\t%a0"
7323  [(set_attr "length" "4")
7324   (set_attr "type" "call")]
7325)
7326
7327(define_insn "*call_value_insn"
7328  [(set (match_operand 0 "register_operand" "")
7329	(call (mem:SI (match_operand 1 "" ""))
7330	      (match_operand 2 "" "")))
7331   (use (match_operand 3 "" ""))
7332   (clobber (reg:SI LR_REGNUM))]
7333  "TARGET_THUMB
7334   && GET_CODE (operands[1]) == SYMBOL_REF
7335   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7336  "bl\\t%a1"
7337  [(set_attr "length" "4")
7338   (set_attr "type" "call")]
7339)
7340
7341;; We may also be able to do sibcalls for Thumb, but it's much harder...
7342(define_expand "sibcall"
7343  [(parallel [(call (match_operand 0 "memory_operand" "")
7344		    (match_operand 1 "general_operand" ""))
7345	      (return)
7346	      (use (match_operand 2 "" ""))])]
7347  "TARGET_ARM"
7348  "
7349  {
7350    if (operands[2] == NULL_RTX)
7351      operands[2] = const0_rtx;
7352  }"
7353)
7354
7355(define_expand "sibcall_value"
7356  [(parallel [(set (match_operand 0 "register_operand" "")
7357		   (call (match_operand 1 "memory_operand" "")
7358			 (match_operand 2 "general_operand" "")))
7359	      (return)
7360	      (use (match_operand 3 "" ""))])]
7361  "TARGET_ARM"
7362  "
7363  {
7364    if (operands[3] == NULL_RTX)
7365      operands[3] = const0_rtx;
7366  }"
7367)
7368
7369(define_insn "*sibcall_insn"
7370 [(call (mem:SI (match_operand:SI 0 "" "X"))
7371	(match_operand 1 "" ""))
7372  (return)
7373  (use (match_operand 2 "" ""))]
7374  "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7375  "*
7376  return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7377  "
7378  [(set_attr "type" "call")]
7379)
7380
7381(define_insn "*sibcall_value_insn"
7382 [(set (match_operand 0 "s_register_operand" "")
7383       (call (mem:SI (match_operand:SI 1 "" "X"))
7384	     (match_operand 2 "" "")))
7385  (return)
7386  (use (match_operand 3 "" ""))]
7387  "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7388  "*
7389  return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7390  "
7391  [(set_attr "type" "call")]
7392)
7393
7394;; Often the return insn will be the same as loading from memory, so set attr
7395(define_insn "return"
7396  [(return)]
7397  "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7398  "*
7399  {
7400    if (arm_ccfsm_state == 2)
7401      {
7402        arm_ccfsm_state += 2;
7403        return \"\";
7404      }
7405    return output_return_instruction (const_true_rtx, TRUE, FALSE);
7406  }"
7407  [(set_attr "type" "load")
7408   (set_attr "length" "12")
7409   (set_attr "predicable" "yes")]
7410)
7411
7412(define_insn "*cond_return"
7413  [(set (pc)
7414        (if_then_else (match_operator 0 "arm_comparison_operator"
7415		       [(match_operand 1 "cc_register" "") (const_int 0)])
7416                      (return)
7417                      (pc)))]
7418  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7419  "*
7420  {
7421    if (arm_ccfsm_state == 2)
7422      {
7423        arm_ccfsm_state += 2;
7424        return \"\";
7425      }
7426    return output_return_instruction (operands[0], TRUE, FALSE);
7427  }"
7428  [(set_attr "conds" "use")
7429   (set_attr "length" "12")
7430   (set_attr "type" "load")]
7431)
7432
7433(define_insn "*cond_return_inverted"
7434  [(set (pc)
7435        (if_then_else (match_operator 0 "arm_comparison_operator"
7436		       [(match_operand 1 "cc_register" "") (const_int 0)])
7437                      (pc)
7438		      (return)))]
7439  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7440  "*
7441  {
7442    if (arm_ccfsm_state == 2)
7443      {
7444        arm_ccfsm_state += 2;
7445        return \"\";
7446      }
7447    return output_return_instruction (operands[0], TRUE, TRUE);
7448  }"
7449  [(set_attr "conds" "use")
7450   (set_attr "type" "load")]
7451)
7452
7453;; Generate a sequence of instructions to determine if the processor is
7454;; in 26-bit or 32-bit mode, and return the appropriate return address
7455;; mask.
7456
7457(define_expand "return_addr_mask"
7458  [(set (match_dup 1)
7459      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7460		       (const_int 0)))
7461   (set (match_operand:SI 0 "s_register_operand" "")
7462      (if_then_else:SI (eq (match_dup 1) (const_int 0))
7463		       (const_int -1)
7464		       (const_int 67108860)))] ; 0x03fffffc
7465  "TARGET_ARM"
7466  "
7467  operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7468  ")
7469
7470(define_insn "*check_arch2"
7471  [(set (match_operand:CC_NOOV 0 "cc_register" "")
7472      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7473		       (const_int 0)))]
7474  "TARGET_ARM"
7475  "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7476  [(set_attr "length" "8")
7477   (set_attr "conds" "set")]
7478)
7479
7480;; Call subroutine returning any type.
7481
7482(define_expand "untyped_call"
7483  [(parallel [(call (match_operand 0 "" "")
7484		    (const_int 0))
7485	      (match_operand 1 "" "")
7486	      (match_operand 2 "" "")])]
7487  "TARGET_ARM"
7488  "
7489  {
7490    int i;
7491
7492    emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7493
7494    for (i = 0; i < XVECLEN (operands[2], 0); i++)
7495      {
7496	rtx set = XVECEXP (operands[2], 0, i);
7497
7498	emit_move_insn (SET_DEST (set), SET_SRC (set));
7499      }
7500
7501    /* The optimizer does not know that the call sets the function value
7502       registers we stored in the result block.  We avoid problems by
7503       claiming that all hard registers are used and clobbered at this
7504       point.  */
7505    emit_insn (gen_blockage ());
7506
7507    DONE;
7508  }"
7509)
7510
7511;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7512;; all of memory.  This blocks insns from being moved across this point.
7513
7514(define_insn "blockage"
7515  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7516  "TARGET_EITHER"
7517  ""
7518  [(set_attr "length" "0")
7519   (set_attr "type" "block")]
7520)
7521
7522(define_expand "casesi"
7523  [(match_operand:SI 0 "s_register_operand" "")	; index to jump on
7524   (match_operand:SI 1 "const_int_operand" "")	; lower bound
7525   (match_operand:SI 2 "const_int_operand" "")	; total range
7526   (match_operand:SI 3 "" "")			; table label
7527   (match_operand:SI 4 "" "")]			; Out of range label
7528  "TARGET_ARM"
7529  "
7530  {
7531    rtx reg;
7532    if (operands[1] != const0_rtx)
7533      {
7534	reg = gen_reg_rtx (SImode);
7535
7536	emit_insn (gen_addsi3 (reg, operands[0],
7537			       GEN_INT (-INTVAL (operands[1]))));
7538	operands[0] = reg;
7539      }
7540
7541    if (!const_ok_for_arm (INTVAL (operands[2])))
7542      operands[2] = force_reg (SImode, operands[2]);
7543
7544    emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7545					 operands[4]));
7546    DONE;
7547  }"
7548)
7549
7550;; The USE in this pattern is needed to tell flow analysis that this is
7551;; a CASESI insn.  It has no other purpose.
7552(define_insn "casesi_internal"
7553  [(parallel [(set (pc)
7554	       (if_then_else
7555		(leu (match_operand:SI 0 "s_register_operand" "r")
7556		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
7557		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7558				 (label_ref (match_operand 2 "" ""))))
7559		(label_ref (match_operand 3 "" ""))))
7560	      (clobber (reg:CC CC_REGNUM))
7561	      (use (label_ref (match_dup 2)))])]
7562  "TARGET_ARM"
7563  "*
7564    if (flag_pic)
7565      return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7566    return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7567  "
7568  [(set_attr "conds" "clob")
7569   (set_attr "length" "12")]
7570)
7571
7572(define_expand "indirect_jump"
7573  [(set (pc)
7574	(match_operand:SI 0 "s_register_operand" ""))]
7575  "TARGET_EITHER"
7576  ""
7577)
7578
7579(define_insn "*arm_indirect_jump"
7580  [(set (pc)
7581	(match_operand:SI 0 "s_register_operand" "r"))]
7582  "TARGET_ARM"
7583  "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7584  [(set_attr "predicable" "yes")]
7585)
7586
7587;; Although not supported by the define_expand above,
7588;; cse/combine may generate this form.
7589(define_insn "*load_indirect_jump"
7590  [(set (pc)
7591	(match_operand:SI 0 "memory_operand" "m"))]
7592  "TARGET_ARM"
7593  "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7594  [(set_attr "type" "load")
7595   (set_attr "pool_range" "4096")
7596   (set_attr "neg_pool_range" "4084")
7597   (set_attr "predicable" "yes")]
7598)
7599
7600(define_insn "*thumb_indirect_jump"
7601  [(set (pc)
7602	(match_operand:SI 0 "register_operand" "l*r"))]
7603  "TARGET_THUMB"
7604  "mov\\tpc, %0"
7605  [(set_attr "conds" "clob")
7606   (set_attr "length" "2")]
7607)
7608
7609
7610;; Misc insns
7611
7612(define_insn "nop"
7613  [(const_int 0)]
7614  "TARGET_EITHER"
7615  "*
7616  if (TARGET_ARM)
7617    return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7618  return  \"mov\\tr8, r8\";
7619  "
7620  [(set (attr "length")
7621	(if_then_else (eq_attr "is_thumb" "yes")
7622		      (const_int 2)
7623		      (const_int 4)))]
7624)
7625
7626
7627;; Patterns to allow combination of arithmetic, cond code and shifts
7628
7629(define_insn "*arith_shiftsi"
7630  [(set (match_operand:SI 0 "s_register_operand" "=r")
7631        (match_operator:SI 1 "shiftable_operator"
7632          [(match_operator:SI 3 "shift_operator"
7633             [(match_operand:SI 4 "s_register_operand" "r")
7634              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7635           (match_operand:SI 2 "s_register_operand" "r")]))]
7636  "TARGET_ARM"
7637  "%i1%?\\t%0, %2, %4%S3"
7638  [(set_attr "predicable" "yes")
7639   (set_attr "shift" "4")
7640   ]
7641)
7642
7643(define_split
7644  [(set (match_operand:SI 0 "s_register_operand" "")
7645	(match_operator:SI 1 "shiftable_operator"
7646	 [(match_operator:SI 2 "shiftable_operator"
7647	   [(match_operator:SI 3 "shift_operator"
7648	     [(match_operand:SI 4 "s_register_operand" "")
7649	      (match_operand:SI 5 "reg_or_int_operand" "")])
7650	    (match_operand:SI 6 "s_register_operand" "")])
7651	  (match_operand:SI 7 "arm_rhs_operand" "")]))
7652   (clobber (match_operand:SI 8 "s_register_operand" ""))]
7653  "TARGET_ARM"
7654  [(set (match_dup 8)
7655	(match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7656			 (match_dup 6)]))
7657   (set (match_dup 0)
7658	(match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7659  "")
7660
7661(define_insn "*arith_shiftsi_compare0"
7662  [(set (reg:CC_NOOV CC_REGNUM)
7663        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7664		          [(match_operator:SI 3 "shift_operator"
7665		            [(match_operand:SI 4 "s_register_operand" "r")
7666		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
7667		           (match_operand:SI 2 "s_register_operand" "r")])
7668			 (const_int 0)))
7669   (set (match_operand:SI 0 "s_register_operand" "=r")
7670	(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7671			 (match_dup 2)]))]
7672  "TARGET_ARM"
7673  "%i1%?s\\t%0, %2, %4%S3"
7674  [(set_attr "conds" "set")
7675   (set_attr "shift" "4")
7676   ]
7677)
7678
7679(define_insn "*arith_shiftsi_compare0_scratch"
7680  [(set (reg:CC_NOOV CC_REGNUM)
7681        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7682		          [(match_operator:SI 3 "shift_operator"
7683		            [(match_operand:SI 4 "s_register_operand" "r")
7684		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
7685		           (match_operand:SI 2 "s_register_operand" "r")])
7686			 (const_int 0)))
7687   (clobber (match_scratch:SI 0 "=r"))]
7688  "TARGET_ARM"
7689  "%i1%?s\\t%0, %2, %4%S3"
7690  [(set_attr "conds" "set")
7691   (set_attr "shift" "4")
7692   ]
7693)
7694
7695(define_insn "*sub_shiftsi"
7696  [(set (match_operand:SI 0 "s_register_operand" "=r")
7697	(minus:SI (match_operand:SI 1 "s_register_operand" "r")
7698		  (match_operator:SI 2 "shift_operator"
7699		   [(match_operand:SI 3 "s_register_operand" "r")
7700		    (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7701  "TARGET_ARM"
7702  "sub%?\\t%0, %1, %3%S2"
7703  [(set_attr "predicable" "yes")
7704   (set_attr "shift" "3")
7705   ]
7706)
7707
7708(define_insn "*sub_shiftsi_compare0"
7709  [(set (reg:CC_NOOV CC_REGNUM)
7710	(compare:CC_NOOV
7711	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7712		   (match_operator:SI 2 "shift_operator"
7713		    [(match_operand:SI 3 "s_register_operand" "r")
7714		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7715	 (const_int 0)))
7716   (set (match_operand:SI 0 "s_register_operand" "=r")
7717	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7718						 (match_dup 4)])))]
7719  "TARGET_ARM"
7720  "sub%?s\\t%0, %1, %3%S2"
7721  [(set_attr "conds" "set")
7722   (set_attr "shift" "3") 
7723   ]
7724)
7725
7726(define_insn "*sub_shiftsi_compare0_scratch"
7727  [(set (reg:CC_NOOV CC_REGNUM)
7728	(compare:CC_NOOV
7729	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7730		   (match_operator:SI 2 "shift_operator"
7731		    [(match_operand:SI 3 "s_register_operand" "r")
7732		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7733	 (const_int 0)))
7734   (clobber (match_scratch:SI 0 "=r"))]
7735  "TARGET_ARM"
7736  "sub%?s\\t%0, %1, %3%S2"
7737  [(set_attr "conds" "set")
7738   (set_attr "shift" "3") 
7739   ]
7740)
7741
7742
7743
7744(define_insn "*and_scc"
7745  [(set (match_operand:SI 0 "s_register_operand" "=r")
7746	(and:SI (match_operator:SI 1 "arm_comparison_operator"
7747		 [(match_operand 3 "cc_register" "") (const_int 0)])
7748		(match_operand:SI 2 "s_register_operand" "r")))]
7749  "TARGET_ARM"
7750  "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7751  [(set_attr "conds" "use")
7752   (set_attr "length" "8")]
7753)
7754
7755(define_insn "*ior_scc"
7756  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7757	(ior:SI (match_operator:SI 2 "arm_comparison_operator"
7758		 [(match_operand 3 "cc_register" "") (const_int 0)])
7759		(match_operand:SI 1 "s_register_operand" "0,?r")))]
7760  "TARGET_ARM"
7761  "@
7762   orr%d2\\t%0, %1, #1
7763   mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7764  [(set_attr "conds" "use")
7765   (set_attr "length" "4,8")]
7766)
7767
7768(define_insn "*compare_scc"
7769  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7770	(match_operator:SI 1 "arm_comparison_operator"
7771	 [(match_operand:SI 2 "s_register_operand" "r,r")
7772	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7773   (clobber (reg:CC CC_REGNUM))]
7774  "TARGET_ARM"
7775  "*
7776    if (operands[3] == const0_rtx)
7777      {
7778	if (GET_CODE (operands[1]) == LT)
7779	  return \"mov\\t%0, %2, lsr #31\";
7780
7781	if (GET_CODE (operands[1]) == GE)
7782	  return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7783
7784	if (GET_CODE (operands[1]) == EQ)
7785	  return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
7786      }
7787
7788    if (GET_CODE (operands[1]) == NE)
7789      {
7790        if (which_alternative == 1)
7791	  return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7792        return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7793      }
7794    if (which_alternative == 1)
7795      output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7796    else
7797      output_asm_insn (\"cmp\\t%2, %3\", operands);
7798    return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7799  "
7800  [(set_attr "conds" "clob")
7801   (set_attr "length" "12")]
7802)
7803
7804(define_insn "*cond_move"
7805  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7806	(if_then_else:SI (match_operator 3 "equality_operator"
7807			  [(match_operator 4 "arm_comparison_operator"
7808			    [(match_operand 5 "cc_register" "") (const_int 0)])
7809			   (const_int 0)])
7810			 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7811			 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7812  "TARGET_ARM"
7813  "*
7814    if (GET_CODE (operands[3]) == NE)
7815      {
7816        if (which_alternative != 1)
7817	  output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7818        if (which_alternative != 0)
7819	  output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7820        return \"\";
7821      }
7822    if (which_alternative != 0)
7823      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7824    if (which_alternative != 1)
7825      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7826    return \"\";
7827  "
7828  [(set_attr "conds" "use")
7829   (set_attr "length" "4,4,8")]
7830)
7831
7832(define_insn "*cond_arith"
7833  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7834        (match_operator:SI 5 "shiftable_operator" 
7835	 [(match_operator:SI 4 "arm_comparison_operator"
7836           [(match_operand:SI 2 "s_register_operand" "r,r")
7837	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7838          (match_operand:SI 1 "s_register_operand" "0,?r")]))
7839   (clobber (reg:CC CC_REGNUM))]
7840  "TARGET_ARM"
7841  "*
7842    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7843      return \"%i5\\t%0, %1, %2, lsr #31\";
7844
7845    output_asm_insn (\"cmp\\t%2, %3\", operands);
7846    if (GET_CODE (operands[5]) == AND)
7847      output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7848    else if (GET_CODE (operands[5]) == MINUS)
7849      output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7850    else if (which_alternative != 0)
7851      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7852    return \"%i5%d4\\t%0, %1, #1\";
7853  "
7854  [(set_attr "conds" "clob")
7855   (set_attr "length" "12")]
7856)
7857
7858(define_insn "*cond_sub"
7859  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7860        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7861		  (match_operator:SI 4 "arm_comparison_operator"
7862                   [(match_operand:SI 2 "s_register_operand" "r,r")
7863		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7864   (clobber (reg:CC CC_REGNUM))]
7865  "TARGET_ARM"
7866  "*
7867    output_asm_insn (\"cmp\\t%2, %3\", operands);
7868    if (which_alternative != 0)
7869      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7870    return \"sub%d4\\t%0, %1, #1\";
7871  "
7872  [(set_attr "conds" "clob")
7873   (set_attr "length" "8,12")]
7874)
7875
7876(define_insn "*cmp_ite0"
7877  [(set (match_operand 6 "dominant_cc_register" "")
7878	(compare
7879	 (if_then_else:SI
7880	  (match_operator 4 "arm_comparison_operator"
7881	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7882	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7883	  (match_operator:SI 5 "arm_comparison_operator"
7884	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7885	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7886	  (const_int 0))
7887	 (const_int 0)))]
7888  "TARGET_ARM"
7889  "*
7890  {
7891    static const char * const opcodes[4][2] =
7892    {
7893      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7894       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7895      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7896       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7897      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7898       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7899      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7900       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7901    };
7902    int swap =
7903      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7904
7905    return opcodes[which_alternative][swap];
7906  }"
7907  [(set_attr "conds" "set")
7908   (set_attr "length" "8")]
7909)
7910
7911(define_insn "*cmp_ite1"
7912  [(set (match_operand 6 "dominant_cc_register" "")
7913	(compare
7914	 (if_then_else:SI
7915	  (match_operator 4 "arm_comparison_operator"
7916	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7917	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7918	  (match_operator:SI 5 "arm_comparison_operator"
7919	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7920	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7921	  (const_int 1))
7922	 (const_int 0)))]
7923  "TARGET_ARM"
7924  "*
7925  {
7926    static const char * const opcodes[4][2] =
7927    {
7928      {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7929       \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7930      {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7931       \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7932      {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7933       \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7934      {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7935       \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7936    };
7937    int swap =
7938      comparison_dominates_p (GET_CODE (operands[5]),
7939			      reverse_condition (GET_CODE (operands[4])));
7940
7941    return opcodes[which_alternative][swap];
7942  }"
7943  [(set_attr "conds" "set")
7944   (set_attr "length" "8")]
7945)
7946
7947(define_insn "*cmp_and"
7948  [(set (match_operand 6 "dominant_cc_register" "")
7949	(compare
7950	 (and:SI
7951	  (match_operator 4 "arm_comparison_operator"
7952	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7953	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7954	  (match_operator:SI 5 "arm_comparison_operator"
7955	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7956	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7957	 (const_int 0)))]
7958  "TARGET_ARM"
7959  "*
7960  {
7961    static const char *const opcodes[4][2] =
7962    {
7963      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7964       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7965      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7966       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7967      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7968       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7969      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7970       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7971    };
7972    int swap =
7973      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7974
7975    return opcodes[which_alternative][swap];
7976  }"
7977  [(set_attr "conds" "set")
7978   (set_attr "predicable" "no")
7979   (set_attr "length" "8")]
7980)
7981
7982(define_insn "*cmp_ior"
7983  [(set (match_operand 6 "dominant_cc_register" "")
7984	(compare
7985	 (ior:SI
7986	  (match_operator 4 "arm_comparison_operator"
7987	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7988	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7989	  (match_operator:SI 5 "arm_comparison_operator"
7990	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7991	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7992	 (const_int 0)))]
7993  "TARGET_ARM"
7994  "*
7995{
7996  static const char *const opcodes[4][2] =
7997  {
7998    {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7999     \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8000    {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8001     \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8002    {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8003     \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8004    {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8005     \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8006  };
8007  int swap =
8008    comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8009
8010  return opcodes[which_alternative][swap];
8011}
8012"
8013  [(set_attr "conds" "set")
8014   (set_attr "length" "8")]
8015)
8016
8017(define_insn_and_split "*ior_scc_scc"
8018  [(set (match_operand:SI 0 "s_register_operand" "=r")
8019	(ior:SI (match_operator:SI 3 "arm_comparison_operator"
8020		 [(match_operand:SI 1 "s_register_operand" "r")
8021		  (match_operand:SI 2 "arm_add_operand" "rIL")])
8022		(match_operator:SI 6 "arm_comparison_operator"
8023		 [(match_operand:SI 4 "s_register_operand" "r")
8024		  (match_operand:SI 5 "arm_add_operand" "rIL")])))
8025   (clobber (reg:CC CC_REGNUM))]
8026  "TARGET_ARM
8027   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8028       != CCmode)"
8029  "#"
8030  "TARGET_ARM && reload_completed"
8031  [(set (match_dup 7)
8032	(compare
8033	 (ior:SI
8034	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8035	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8036	 (const_int 0)))
8037   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8038  "operands[7]
8039     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8040						  DOM_CC_X_OR_Y),
8041		    CC_REGNUM);"
8042  [(set_attr "conds" "clob")
8043   (set_attr "length" "16")])
8044
8045; If the above pattern is followed by a CMP insn, then the compare is 
8046; redundant, since we can rework the conditional instruction that follows.
8047(define_insn_and_split "*ior_scc_scc_cmp"
8048  [(set (match_operand 0 "dominant_cc_register" "")
8049	(compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8050			  [(match_operand:SI 1 "s_register_operand" "r")
8051			   (match_operand:SI 2 "arm_add_operand" "rIL")])
8052			 (match_operator:SI 6 "arm_comparison_operator"
8053			  [(match_operand:SI 4 "s_register_operand" "r")
8054			   (match_operand:SI 5 "arm_add_operand" "rIL")]))
8055		 (const_int 0)))
8056   (set (match_operand:SI 7 "s_register_operand" "=r")
8057	(ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8058		(match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8059  "TARGET_ARM"
8060  "#"
8061  "TARGET_ARM && reload_completed"
8062  [(set (match_dup 0)
8063	(compare
8064	 (ior:SI
8065	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8066	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8067	 (const_int 0)))
8068   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8069  ""
8070  [(set_attr "conds" "set")
8071   (set_attr "length" "16")])
8072
8073(define_insn_and_split "*and_scc_scc"
8074  [(set (match_operand:SI 0 "s_register_operand" "=r")
8075	(and:SI (match_operator:SI 3 "arm_comparison_operator"
8076		 [(match_operand:SI 1 "s_register_operand" "r")
8077		  (match_operand:SI 2 "arm_add_operand" "rIL")])
8078		(match_operator:SI 6 "arm_comparison_operator"
8079		 [(match_operand:SI 4 "s_register_operand" "r")
8080		  (match_operand:SI 5 "arm_add_operand" "rIL")])))
8081   (clobber (reg:CC CC_REGNUM))]
8082  "TARGET_ARM
8083   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8084       != CCmode)"
8085  "#"
8086  "TARGET_ARM && reload_completed
8087   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8088       != CCmode)"
8089  [(set (match_dup 7)
8090	(compare
8091	 (and:SI
8092	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8093	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8094	 (const_int 0)))
8095   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8096  "operands[7]
8097     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8098						  DOM_CC_X_AND_Y),
8099		    CC_REGNUM);"
8100  [(set_attr "conds" "clob")
8101   (set_attr "length" "16")])
8102
8103; If the above pattern is followed by a CMP insn, then the compare is 
8104; redundant, since we can rework the conditional instruction that follows.
8105(define_insn_and_split "*and_scc_scc_cmp"
8106  [(set (match_operand 0 "dominant_cc_register" "")
8107	(compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8108			  [(match_operand:SI 1 "s_register_operand" "r")
8109			   (match_operand:SI 2 "arm_add_operand" "rIL")])
8110			 (match_operator:SI 6 "arm_comparison_operator"
8111			  [(match_operand:SI 4 "s_register_operand" "r")
8112			   (match_operand:SI 5 "arm_add_operand" "rIL")]))
8113		 (const_int 0)))
8114   (set (match_operand:SI 7 "s_register_operand" "=r")
8115	(and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8116		(match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8117  "TARGET_ARM"
8118  "#"
8119  "TARGET_ARM && reload_completed"
8120  [(set (match_dup 0)
8121	(compare
8122	 (and:SI
8123	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8124	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8125	 (const_int 0)))
8126   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8127  ""
8128  [(set_attr "conds" "set")
8129   (set_attr "length" "16")])
8130
8131;; If there is no dominance in the comparison, then we can still save an
8132;; instruction in the AND case, since we can know that the second compare
8133;; need only zero the value if false (if true, then the value is already
8134;; correct).
8135(define_insn_and_split "*and_scc_scc_nodom"
8136  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8137	(and:SI (match_operator:SI 3 "arm_comparison_operator"
8138		 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8139		  (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8140		(match_operator:SI 6 "arm_comparison_operator"
8141		 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8142		  (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8143   (clobber (reg:CC CC_REGNUM))]
8144  "TARGET_ARM
8145   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8146       == CCmode)"
8147  "#"
8148  "TARGET_ARM && reload_completed"
8149  [(parallel [(set (match_dup 0)
8150		   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8151	      (clobber (reg:CC CC_REGNUM))])
8152   (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8153   (set (match_dup 0)
8154	(if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8155			 (match_dup 0)
8156			 (const_int 0)))]
8157  "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8158					      operands[4], operands[5]),
8159			      CC_REGNUM);
8160   operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8161				  operands[5]);"
8162  [(set_attr "conds" "clob")
8163   (set_attr "length" "20")])
8164
8165(define_split
8166  [(set (reg:CC_NOOV CC_REGNUM)
8167	(compare:CC_NOOV (ior:SI
8168			  (and:SI (match_operand:SI 0 "s_register_operand" "")
8169				  (const_int 1))
8170			  (match_operator:SI 1 "comparison_operator"
8171			   [(match_operand:SI 2 "s_register_operand" "")
8172			    (match_operand:SI 3 "arm_add_operand" "")]))
8173			 (const_int 0)))
8174   (clobber (match_operand:SI 4 "s_register_operand" ""))]
8175  "TARGET_ARM"
8176  [(set (match_dup 4)
8177	(ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8178		(match_dup 0)))
8179   (set (reg:CC_NOOV CC_REGNUM)
8180	(compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8181			 (const_int 0)))]
8182  "")
8183
8184(define_split
8185  [(set (reg:CC_NOOV CC_REGNUM)
8186	(compare:CC_NOOV (ior:SI
8187			  (match_operator:SI 1 "comparison_operator"
8188			   [(match_operand:SI 2 "s_register_operand" "")
8189			    (match_operand:SI 3 "arm_add_operand" "")])
8190			  (and:SI (match_operand:SI 0 "s_register_operand" "")
8191				  (const_int 1)))
8192			 (const_int 0)))
8193   (clobber (match_operand:SI 4 "s_register_operand" ""))]
8194  "TARGET_ARM"
8195  [(set (match_dup 4)
8196	(ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8197		(match_dup 0)))
8198   (set (reg:CC_NOOV CC_REGNUM)
8199	(compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8200			 (const_int 0)))]
8201  "")
8202
8203(define_insn "*negscc"
8204  [(set (match_operand:SI 0 "s_register_operand" "=r")
8205	(neg:SI (match_operator 3 "arm_comparison_operator"
8206		 [(match_operand:SI 1 "s_register_operand" "r")
8207		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8208   (clobber (reg:CC CC_REGNUM))]
8209  "TARGET_ARM"
8210  "*
8211  if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8212    return \"mov\\t%0, %1, asr #31\";
8213
8214  if (GET_CODE (operands[3]) == NE)
8215    return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8216
8217  if (GET_CODE (operands[3]) == GT)
8218    return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8219
8220  output_asm_insn (\"cmp\\t%1, %2\", operands);
8221  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8222  return \"mvn%d3\\t%0, #0\";
8223  "
8224  [(set_attr "conds" "clob")
8225   (set_attr "length" "12")]
8226)
8227
8228(define_insn "movcond"
8229  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8230	(if_then_else:SI
8231	 (match_operator 5 "arm_comparison_operator"
8232	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
8233	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8234	 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8235	 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8236   (clobber (reg:CC CC_REGNUM))]
8237  "TARGET_ARM"
8238  "*
8239  if (GET_CODE (operands[5]) == LT
8240      && (operands[4] == const0_rtx))
8241    {
8242      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8243	{
8244	  if (operands[2] == const0_rtx)
8245	    return \"and\\t%0, %1, %3, asr #31\";
8246	  return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8247	}
8248      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8249	{
8250	  if (operands[1] == const0_rtx)
8251	    return \"bic\\t%0, %2, %3, asr #31\";
8252	  return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8253	}
8254      /* The only case that falls through to here is when both ops 1 & 2
8255	 are constants.  */
8256    }
8257
8258  if (GET_CODE (operands[5]) == GE
8259      && (operands[4] == const0_rtx))
8260    {
8261      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8262	{
8263	  if (operands[2] == const0_rtx)
8264	    return \"bic\\t%0, %1, %3, asr #31\";
8265	  return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8266	}
8267      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8268	{
8269	  if (operands[1] == const0_rtx)
8270	    return \"and\\t%0, %2, %3, asr #31\";
8271	  return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8272	}
8273      /* The only case that falls through to here is when both ops 1 & 2
8274	 are constants.  */
8275    }
8276  if (GET_CODE (operands[4]) == CONST_INT
8277      && !const_ok_for_arm (INTVAL (operands[4])))
8278    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8279  else
8280    output_asm_insn (\"cmp\\t%3, %4\", operands);
8281  if (which_alternative != 0)
8282    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8283  if (which_alternative != 1)
8284    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8285  return \"\";
8286  "
8287  [(set_attr "conds" "clob")
8288   (set_attr "length" "8,8,12")]
8289)
8290
8291(define_insn "*ifcompare_plus_move"
8292  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8293	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8294			  [(match_operand:SI 4 "s_register_operand" "r,r")
8295			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8296			 (plus:SI
8297			  (match_operand:SI 2 "s_register_operand" "r,r")
8298			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8299			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8300   (clobber (reg:CC CC_REGNUM))]
8301  "TARGET_ARM"
8302  "#"
8303  [(set_attr "conds" "clob")
8304   (set_attr "length" "8,12")]
8305)
8306
8307(define_insn "*if_plus_move"
8308  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8309	(if_then_else:SI
8310	 (match_operator 4 "arm_comparison_operator"
8311	  [(match_operand 5 "cc_register" "") (const_int 0)])
8312	 (plus:SI
8313	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8314	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8315	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8316  "TARGET_ARM"
8317  "@
8318   add%d4\\t%0, %2, %3
8319   sub%d4\\t%0, %2, #%n3
8320   add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8321   sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8322  [(set_attr "conds" "use")
8323   (set_attr "length" "4,4,8,8")
8324   (set_attr "type" "*,*,*,*")]
8325)
8326
8327(define_insn "*ifcompare_move_plus"
8328  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8329	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8330			  [(match_operand:SI 4 "s_register_operand" "r,r")
8331			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8332			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8333			 (plus:SI
8334			  (match_operand:SI 2 "s_register_operand" "r,r")
8335			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8336   (clobber (reg:CC CC_REGNUM))]
8337  "TARGET_ARM"
8338  "#"
8339  [(set_attr "conds" "clob")
8340   (set_attr "length" "8,12")]
8341)
8342
8343(define_insn "*if_move_plus"
8344  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8345	(if_then_else:SI
8346	 (match_operator 4 "arm_comparison_operator"
8347	  [(match_operand 5 "cc_register" "") (const_int 0)])
8348	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8349	 (plus:SI
8350	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8351	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8352  "TARGET_ARM"
8353  "@
8354   add%D4\\t%0, %2, %3
8355   sub%D4\\t%0, %2, #%n3
8356   add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8357   sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8358  [(set_attr "conds" "use")
8359   (set_attr "length" "4,4,8,8")
8360   (set_attr "type" "*,*,*,*")]
8361)
8362
8363(define_insn "*ifcompare_arith_arith"
8364  [(set (match_operand:SI 0 "s_register_operand" "=r")
8365	(if_then_else:SI (match_operator 9 "arm_comparison_operator"
8366			  [(match_operand:SI 5 "s_register_operand" "r")
8367			   (match_operand:SI 6 "arm_add_operand" "rIL")])
8368			 (match_operator:SI 8 "shiftable_operator"
8369			  [(match_operand:SI 1 "s_register_operand" "r")
8370			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
8371			 (match_operator:SI 7 "shiftable_operator"
8372			  [(match_operand:SI 3 "s_register_operand" "r")
8373			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8374   (clobber (reg:CC CC_REGNUM))]
8375  "TARGET_ARM"
8376  "#"
8377  [(set_attr "conds" "clob")
8378   (set_attr "length" "12")]
8379)
8380
8381(define_insn "*if_arith_arith"
8382  [(set (match_operand:SI 0 "s_register_operand" "=r")
8383	(if_then_else:SI (match_operator 5 "arm_comparison_operator"
8384			  [(match_operand 8 "cc_register" "") (const_int 0)])
8385			 (match_operator:SI 6 "shiftable_operator"
8386			  [(match_operand:SI 1 "s_register_operand" "r")
8387			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
8388			 (match_operator:SI 7 "shiftable_operator"
8389			  [(match_operand:SI 3 "s_register_operand" "r")
8390			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8391  "TARGET_ARM"
8392  "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8393  [(set_attr "conds" "use")
8394   (set_attr "length" "8")]
8395)
8396
8397(define_insn "*ifcompare_arith_move"
8398  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8399	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8400			  [(match_operand:SI 2 "s_register_operand" "r,r")
8401			   (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8402			 (match_operator:SI 7 "shiftable_operator"
8403			  [(match_operand:SI 4 "s_register_operand" "r,r")
8404			   (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8405			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8406   (clobber (reg:CC CC_REGNUM))]
8407  "TARGET_ARM"
8408  "*
8409  /* If we have an operation where (op x 0) is the identity operation and
8410     the conditional operator is LT or GE and we are comparing against zero and
8411     everything is in registers then we can do this in two instructions.  */
8412  if (operands[3] == const0_rtx
8413      && GET_CODE (operands[7]) != AND
8414      && GET_CODE (operands[5]) == REG
8415      && GET_CODE (operands[1]) == REG 
8416      && REGNO (operands[1]) == REGNO (operands[4])
8417      && REGNO (operands[4]) != REGNO (operands[0]))
8418    {
8419      if (GET_CODE (operands[6]) == LT)
8420	return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8421      else if (GET_CODE (operands[6]) == GE)
8422	return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8423    }
8424  if (GET_CODE (operands[3]) == CONST_INT
8425      && !const_ok_for_arm (INTVAL (operands[3])))
8426    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8427  else
8428    output_asm_insn (\"cmp\\t%2, %3\", operands);
8429  output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8430  if (which_alternative != 0)
8431    return \"mov%D6\\t%0, %1\";
8432  return \"\";
8433  "
8434  [(set_attr "conds" "clob")
8435   (set_attr "length" "8,12")]
8436)
8437
8438(define_insn "*if_arith_move"
8439  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8440	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
8441			  [(match_operand 6 "cc_register" "") (const_int 0)])
8442			 (match_operator:SI 5 "shiftable_operator"
8443			  [(match_operand:SI 2 "s_register_operand" "r,r")
8444			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8445			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8446  "TARGET_ARM"
8447  "@
8448   %I5%d4\\t%0, %2, %3
8449   %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8450  [(set_attr "conds" "use")
8451   (set_attr "length" "4,8")
8452   (set_attr "type" "*,*")]
8453)
8454
8455(define_insn "*ifcompare_move_arith"
8456  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8457	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
8458			  [(match_operand:SI 4 "s_register_operand" "r,r")
8459			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8460			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8461			 (match_operator:SI 7 "shiftable_operator"
8462			  [(match_operand:SI 2 "s_register_operand" "r,r")
8463			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8464   (clobber (reg:CC CC_REGNUM))]
8465  "TARGET_ARM"
8466  "*
8467  /* If we have an operation where (op x 0) is the identity operation and
8468     the conditional operator is LT or GE and we are comparing against zero and
8469     everything is in registers then we can do this in two instructions */
8470  if (operands[5] == const0_rtx
8471      && GET_CODE (operands[7]) != AND
8472      && GET_CODE (operands[3]) == REG
8473      && GET_CODE (operands[1]) == REG 
8474      && REGNO (operands[1]) == REGNO (operands[2])
8475      && REGNO (operands[2]) != REGNO (operands[0]))
8476    {
8477      if (GET_CODE (operands[6]) == GE)
8478	return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8479      else if (GET_CODE (operands[6]) == LT)
8480	return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8481    }
8482
8483  if (GET_CODE (operands[5]) == CONST_INT
8484      && !const_ok_for_arm (INTVAL (operands[5])))
8485    output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8486  else
8487    output_asm_insn (\"cmp\\t%4, %5\", operands);
8488
8489  if (which_alternative != 0)
8490    output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8491  return \"%I7%D6\\t%0, %2, %3\";
8492  "
8493  [(set_attr "conds" "clob")
8494   (set_attr "length" "8,12")]
8495)
8496
8497(define_insn "*if_move_arith"
8498  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8499	(if_then_else:SI
8500	 (match_operator 4 "arm_comparison_operator"
8501	  [(match_operand 6 "cc_register" "") (const_int 0)])
8502	 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8503	 (match_operator:SI 5 "shiftable_operator"
8504	  [(match_operand:SI 2 "s_register_operand" "r,r")
8505	   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8506  "TARGET_ARM"
8507  "@
8508   %I5%D4\\t%0, %2, %3
8509   %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8510  [(set_attr "conds" "use")
8511   (set_attr "length" "4,8")
8512   (set_attr "type" "*,*")]
8513)
8514
8515(define_insn "*ifcompare_move_not"
8516  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8517	(if_then_else:SI
8518	 (match_operator 5 "arm_comparison_operator"
8519	  [(match_operand:SI 3 "s_register_operand" "r,r")
8520	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8521	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8522	 (not:SI
8523	  (match_operand:SI 2 "s_register_operand" "r,r"))))
8524   (clobber (reg:CC CC_REGNUM))]
8525  "TARGET_ARM"
8526  "#"
8527  [(set_attr "conds" "clob")
8528   (set_attr "length" "8,12")]
8529)
8530
8531(define_insn "*if_move_not"
8532  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8533	(if_then_else:SI
8534	 (match_operator 4 "arm_comparison_operator"
8535	  [(match_operand 3 "cc_register" "") (const_int 0)])
8536	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8537	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8538  "TARGET_ARM"
8539  "@
8540   mvn%D4\\t%0, %2
8541   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8542   mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8543  [(set_attr "conds" "use")
8544   (set_attr "length" "4,8,8")]
8545)
8546
8547(define_insn "*ifcompare_not_move"
8548  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8549	(if_then_else:SI 
8550	 (match_operator 5 "arm_comparison_operator"
8551	  [(match_operand:SI 3 "s_register_operand" "r,r")
8552	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8553	 (not:SI
8554	  (match_operand:SI 2 "s_register_operand" "r,r"))
8555	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8556   (clobber (reg:CC CC_REGNUM))]
8557  "TARGET_ARM"
8558  "#"
8559  [(set_attr "conds" "clob")
8560   (set_attr "length" "8,12")]
8561)
8562
8563(define_insn "*if_not_move"
8564  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8565	(if_then_else:SI
8566	 (match_operator 4 "arm_comparison_operator"
8567	  [(match_operand 3 "cc_register" "") (const_int 0)])
8568	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8569	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8570  "TARGET_ARM"
8571  "@
8572   mvn%d4\\t%0, %2
8573   mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8574   mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8575  [(set_attr "conds" "use")
8576   (set_attr "length" "4,8,8")]
8577)
8578
8579(define_insn "*ifcompare_shift_move"
8580  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8581	(if_then_else:SI
8582	 (match_operator 6 "arm_comparison_operator"
8583	  [(match_operand:SI 4 "s_register_operand" "r,r")
8584	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8585	 (match_operator:SI 7 "shift_operator"
8586	  [(match_operand:SI 2 "s_register_operand" "r,r")
8587	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8588	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8589   (clobber (reg:CC CC_REGNUM))]
8590  "TARGET_ARM"
8591  "#"
8592  [(set_attr "conds" "clob")
8593   (set_attr "length" "8,12")]
8594)
8595
8596(define_insn "*if_shift_move"
8597  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8598	(if_then_else:SI
8599	 (match_operator 5 "arm_comparison_operator"
8600	  [(match_operand 6 "cc_register" "") (const_int 0)])
8601	 (match_operator:SI 4 "shift_operator"
8602	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
8603	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8604	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8605  "TARGET_ARM"
8606  "@
8607   mov%d5\\t%0, %2%S4
8608   mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8609   mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8610  [(set_attr "conds" "use")
8611   (set_attr "shift" "2")
8612   (set_attr "length" "4,8,8")]
8613)
8614
8615(define_insn "*ifcompare_move_shift"
8616  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8617	(if_then_else:SI
8618	 (match_operator 6 "arm_comparison_operator"
8619	  [(match_operand:SI 4 "s_register_operand" "r,r")
8620	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8621	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8622	 (match_operator:SI 7 "shift_operator"
8623	  [(match_operand:SI 2 "s_register_operand" "r,r")
8624	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8625   (clobber (reg:CC CC_REGNUM))]
8626  "TARGET_ARM"
8627  "#"
8628  [(set_attr "conds" "clob")
8629   (set_attr "length" "8,12")]
8630)
8631
8632(define_insn "*if_move_shift"
8633  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8634	(if_then_else:SI
8635	 (match_operator 5 "arm_comparison_operator"
8636	  [(match_operand 6 "cc_register" "") (const_int 0)])
8637	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8638	 (match_operator:SI 4 "shift_operator"
8639	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
8640	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8641  "TARGET_ARM"
8642  "@
8643   mov%D5\\t%0, %2%S4
8644   mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8645   mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8646  [(set_attr "conds" "use")
8647   (set_attr "shift" "2")
8648   (set_attr "length" "4,8,8")]
8649)
8650
8651(define_insn "*ifcompare_shift_shift"
8652  [(set (match_operand:SI 0 "s_register_operand" "=r")
8653	(if_then_else:SI
8654	 (match_operator 7 "arm_comparison_operator"
8655	  [(match_operand:SI 5 "s_register_operand" "r")
8656	   (match_operand:SI 6 "arm_add_operand" "rIL")])
8657	 (match_operator:SI 8 "shift_operator"
8658	  [(match_operand:SI 1 "s_register_operand" "r")
8659	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
8660	 (match_operator:SI 9 "shift_operator"
8661	  [(match_operand:SI 3 "s_register_operand" "r")
8662	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8663   (clobber (reg:CC CC_REGNUM))]
8664  "TARGET_ARM"
8665  "#"
8666  [(set_attr "conds" "clob")
8667   (set_attr "length" "12")]
8668)
8669
8670(define_insn "*if_shift_shift"
8671  [(set (match_operand:SI 0 "s_register_operand" "=r")
8672	(if_then_else:SI
8673	 (match_operator 5 "arm_comparison_operator"
8674	  [(match_operand 8 "cc_register" "") (const_int 0)])
8675	 (match_operator:SI 6 "shift_operator"
8676	  [(match_operand:SI 1 "s_register_operand" "r")
8677	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
8678	 (match_operator:SI 7 "shift_operator"
8679	  [(match_operand:SI 3 "s_register_operand" "r")
8680	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8681  "TARGET_ARM"
8682  "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8683  [(set_attr "conds" "use")
8684   (set_attr "shift" "1")
8685   (set_attr "length" "8")]
8686)
8687
8688(define_insn "*ifcompare_not_arith"
8689  [(set (match_operand:SI 0 "s_register_operand" "=r")
8690	(if_then_else:SI
8691	 (match_operator 6 "arm_comparison_operator"
8692	  [(match_operand:SI 4 "s_register_operand" "r")
8693	   (match_operand:SI 5 "arm_add_operand" "rIL")])
8694	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8695	 (match_operator:SI 7 "shiftable_operator"
8696	  [(match_operand:SI 2 "s_register_operand" "r")
8697	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8698   (clobber (reg:CC CC_REGNUM))]
8699  "TARGET_ARM"
8700  "#"
8701  [(set_attr "conds" "clob")
8702   (set_attr "length" "12")]
8703)
8704
8705(define_insn "*if_not_arith"
8706  [(set (match_operand:SI 0 "s_register_operand" "=r")
8707	(if_then_else:SI
8708	 (match_operator 5 "arm_comparison_operator"
8709	  [(match_operand 4 "cc_register" "") (const_int 0)])
8710	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8711	 (match_operator:SI 6 "shiftable_operator"
8712	  [(match_operand:SI 2 "s_register_operand" "r")
8713	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8714  "TARGET_ARM"
8715  "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8716  [(set_attr "conds" "use")
8717   (set_attr "length" "8")]
8718)
8719
8720(define_insn "*ifcompare_arith_not"
8721  [(set (match_operand:SI 0 "s_register_operand" "=r")
8722	(if_then_else:SI
8723	 (match_operator 6 "arm_comparison_operator"
8724	  [(match_operand:SI 4 "s_register_operand" "r")
8725	   (match_operand:SI 5 "arm_add_operand" "rIL")])
8726	 (match_operator:SI 7 "shiftable_operator"
8727	  [(match_operand:SI 2 "s_register_operand" "r")
8728	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
8729	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8730   (clobber (reg:CC CC_REGNUM))]
8731  "TARGET_ARM"
8732  "#"
8733  [(set_attr "conds" "clob")
8734   (set_attr "length" "12")]
8735)
8736
8737(define_insn "*if_arith_not"
8738  [(set (match_operand:SI 0 "s_register_operand" "=r")
8739	(if_then_else:SI
8740	 (match_operator 5 "arm_comparison_operator"
8741	  [(match_operand 4 "cc_register" "") (const_int 0)])
8742	 (match_operator:SI 6 "shiftable_operator"
8743	  [(match_operand:SI 2 "s_register_operand" "r")
8744	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
8745	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8746  "TARGET_ARM"
8747  "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8748  [(set_attr "conds" "use")
8749   (set_attr "length" "8")]
8750)
8751
8752(define_insn "*ifcompare_neg_move"
8753  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8754	(if_then_else:SI
8755	 (match_operator 5 "arm_comparison_operator"
8756	  [(match_operand:SI 3 "s_register_operand" "r,r")
8757	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8758	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8759	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8760   (clobber (reg:CC CC_REGNUM))]
8761  "TARGET_ARM"
8762  "#"
8763  [(set_attr "conds" "clob")
8764   (set_attr "length" "8,12")]
8765)
8766
8767(define_insn "*if_neg_move"
8768  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8769	(if_then_else:SI
8770	 (match_operator 4 "arm_comparison_operator"
8771	  [(match_operand 3 "cc_register" "") (const_int 0)])
8772	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8773	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8774  "TARGET_ARM"
8775  "@
8776   rsb%d4\\t%0, %2, #0
8777   mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8778   mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8779  [(set_attr "conds" "use")
8780   (set_attr "length" "4,8,8")]
8781)
8782
8783(define_insn "*ifcompare_move_neg"
8784  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8785	(if_then_else:SI
8786	 (match_operator 5 "arm_comparison_operator"
8787	  [(match_operand:SI 3 "s_register_operand" "r,r")
8788	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8789	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8790	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8791   (clobber (reg:CC CC_REGNUM))]
8792  "TARGET_ARM"
8793  "#"
8794  [(set_attr "conds" "clob")
8795   (set_attr "length" "8,12")]
8796)
8797
8798(define_insn "*if_move_neg"
8799  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8800	(if_then_else:SI
8801	 (match_operator 4 "arm_comparison_operator"
8802	  [(match_operand 3 "cc_register" "") (const_int 0)])
8803	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8804	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8805  "TARGET_ARM"
8806  "@
8807   rsb%D4\\t%0, %2, #0
8808   mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8809   mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8810  [(set_attr "conds" "use")
8811   (set_attr "length" "4,8,8")]
8812)
8813
8814(define_insn "*arith_adjacentmem"
8815  [(set (match_operand:SI 0 "s_register_operand" "=r")
8816	(match_operator:SI 1 "shiftable_operator"
8817	 [(match_operand:SI 2 "memory_operand" "m")
8818	  (match_operand:SI 3 "memory_operand" "m")]))
8819   (clobber (match_scratch:SI 4 "=r"))]
8820  "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8821  "*
8822  {
8823    rtx ldm[3];
8824    rtx arith[4];
8825    int val1 = 0, val2 = 0;
8826
8827    if (REGNO (operands[0]) > REGNO (operands[4]))
8828      {
8829	ldm[1] = operands[4];
8830	ldm[2] = operands[0];
8831      }
8832    else
8833      {
8834	ldm[1] = operands[0];
8835	ldm[2] = operands[4];
8836      }
8837    if (GET_CODE (XEXP (operands[2], 0)) != REG)
8838      val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8839    if (GET_CODE (XEXP (operands[3], 0)) != REG)
8840      val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8841    arith[0] = operands[0];
8842    arith[3] = operands[1];
8843    if (val1 < val2)
8844      {
8845	arith[1] = ldm[1];
8846	arith[2] = ldm[2];
8847      }
8848    else
8849      {
8850	arith[1] = ldm[2];
8851	arith[2] = ldm[1];
8852      }
8853   if (val1 && val2)
8854      {
8855	rtx ops[3];
8856	ldm[0] = ops[0] = operands[4];
8857	ops[1] = XEXP (XEXP (operands[2], 0), 0);
8858	ops[2] = XEXP (XEXP (operands[2], 0), 1);
8859	output_add_immediate (ops);
8860	if (val1 < val2)
8861	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8862	else
8863	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8864      }
8865    else if (val1)
8866      {
8867	ldm[0] = XEXP (operands[3], 0);
8868	if (val1 < val2)
8869	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8870	else
8871	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8872      }
8873    else
8874      {
8875	ldm[0] = XEXP (operands[2], 0);
8876	if (val1 < val2)
8877	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8878	else
8879	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8880      }
8881    output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8882    return \"\";
8883  }"
8884  [(set_attr "length" "12")
8885   (set_attr "predicable" "yes")
8886   (set_attr "type" "load")]
8887)
8888
8889;; the arm can support extended pre-inc instructions
8890
8891;; In all these cases, we use operands 0 and 1 for the register being
8892;; incremented because those are the operands that local-alloc will
8893;; tie and these are the pair most likely to be tieable (and the ones
8894;; that will benefit the most).
8895
8896;; We reject the frame pointer if it occurs anywhere in these patterns since
8897;; elimination will cause too many headaches.
8898
8899(define_insn "*strqi_preinc"
8900  [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8901			 (match_operand:SI 2 "index_operand" "rJ")))
8902	(match_operand:QI 3 "s_register_operand" "r"))
8903   (set (match_operand:SI 0 "s_register_operand" "=r")
8904	(plus:SI (match_dup 1) (match_dup 2)))]
8905  "TARGET_ARM
8906   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8907   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8908   && (GET_CODE (operands[2]) != REG
8909       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8910  "str%?b\\t%3, [%0, %2]!"
8911  [(set_attr "type" "store1")
8912   (set_attr "predicable" "yes")]
8913)
8914
8915(define_insn "*strqi_predec"
8916  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8917			  (match_operand:SI 2 "s_register_operand" "r")))
8918	(match_operand:QI 3 "s_register_operand" "r"))
8919   (set (match_operand:SI 0 "s_register_operand" "=r")
8920	(minus:SI (match_dup 1) (match_dup 2)))]
8921  "TARGET_ARM
8922   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8923   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8924   && (GET_CODE (operands[2]) != REG
8925       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8926  "str%?b\\t%3, [%0, -%2]!"
8927  [(set_attr "type" "store1")
8928   (set_attr "predicable" "yes")]
8929)
8930
8931(define_insn "*loadqi_preinc"
8932  [(set (match_operand:QI 3 "s_register_operand" "=r")
8933	(mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8934			 (match_operand:SI 2 "index_operand" "rJ"))))
8935   (set (match_operand:SI 0 "s_register_operand" "=r")
8936	(plus:SI (match_dup 1) (match_dup 2)))]
8937  "TARGET_ARM
8938   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8939   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8940   && (GET_CODE (operands[2]) != REG
8941       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8942  "ldr%?b\\t%3, [%0, %2]!"
8943  [(set_attr "type" "load")
8944   (set_attr "predicable" "yes")]
8945)
8946
8947(define_insn "*loadqi_predec"
8948  [(set (match_operand:QI 3 "s_register_operand" "=r")
8949	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8950			  (match_operand:SI 2 "s_register_operand" "r"))))
8951   (set (match_operand:SI 0 "s_register_operand" "=r")
8952	(minus:SI (match_dup 1) (match_dup 2)))]
8953  "TARGET_ARM
8954   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8955   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8956   && (GET_CODE (operands[2]) != REG
8957       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8958  "ldr%?b\\t%3, [%0, -%2]!"
8959  [(set_attr "type" "load")
8960   (set_attr "predicable" "yes")]
8961)
8962
8963(define_insn "*loadqisi_preinc"
8964  [(set (match_operand:SI 3 "s_register_operand" "=r")
8965	(zero_extend:SI
8966	 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8967			  (match_operand:SI 2 "index_operand" "rJ")))))
8968   (set (match_operand:SI 0 "s_register_operand" "=r")
8969	(plus:SI (match_dup 1) (match_dup 2)))]
8970  "TARGET_ARM
8971   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8972   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8973   && (GET_CODE (operands[2]) != REG
8974       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8975  "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8976  [(set_attr "type" "load")
8977   (set_attr "predicable" "yes")]
8978)
8979
8980(define_insn "*loadqisi_predec"
8981  [(set (match_operand:SI 3 "s_register_operand" "=r")
8982	(zero_extend:SI
8983	 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8984			   (match_operand:SI 2 "s_register_operand" "r")))))
8985   (set (match_operand:SI 0 "s_register_operand" "=r")
8986	(minus:SI (match_dup 1) (match_dup 2)))]
8987  "TARGET_ARM
8988   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8989   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8990   && (GET_CODE (operands[2]) != REG
8991       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8992  "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8993  [(set_attr "type" "load")
8994   (set_attr "predicable" "yes")]
8995)
8996
8997(define_insn "*strsi_preinc"
8998  [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8999			 (match_operand:SI 2 "index_operand" "rJ")))
9000	(match_operand:SI 3 "s_register_operand" "r"))
9001   (set (match_operand:SI 0 "s_register_operand" "=r")
9002	(plus:SI (match_dup 1) (match_dup 2)))]
9003  "TARGET_ARM
9004   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9005   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9006   && (GET_CODE (operands[2]) != REG
9007       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9008  "str%?\\t%3, [%0, %2]!"
9009  [(set_attr "type" "store1")
9010   (set_attr "predicable" "yes")]
9011)
9012
9013(define_insn "*strsi_predec"
9014  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9015			  (match_operand:SI 2 "s_register_operand" "r")))
9016	(match_operand:SI 3 "s_register_operand" "r"))
9017   (set (match_operand:SI 0 "s_register_operand" "=r")
9018	(minus:SI (match_dup 1) (match_dup 2)))]
9019  "TARGET_ARM
9020   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9021   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9022   && (GET_CODE (operands[2]) != REG
9023       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9024  "str%?\\t%3, [%0, -%2]!"
9025  [(set_attr "type" "store1")
9026   (set_attr "predicable" "yes")]
9027)
9028
9029(define_insn "*loadsi_preinc"
9030  [(set (match_operand:SI 3 "s_register_operand" "=r")
9031	(mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9032			 (match_operand:SI 2 "index_operand" "rJ"))))
9033   (set (match_operand:SI 0 "s_register_operand" "=r")
9034	(plus:SI (match_dup 1) (match_dup 2)))]
9035  "TARGET_ARM
9036   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9037   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9038   && (GET_CODE (operands[2]) != REG
9039       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9040  "ldr%?\\t%3, [%0, %2]!"
9041  [(set_attr "type" "load")
9042   (set_attr "predicable" "yes")]
9043)
9044
9045(define_insn "*loadsi_predec"
9046  [(set (match_operand:SI 3 "s_register_operand" "=r")
9047	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9048			  (match_operand:SI 2 "s_register_operand" "r"))))
9049   (set (match_operand:SI 0 "s_register_operand" "=r")
9050	(minus:SI (match_dup 1) (match_dup 2)))]
9051  "TARGET_ARM
9052   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9053   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9054   && (GET_CODE (operands[2]) != REG
9055       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9056  "ldr%?\\t%3, [%0, -%2]!"
9057  [(set_attr "type" "load")
9058   (set_attr "predicable" "yes")]
9059)
9060
9061(define_insn "*loadhi_preinc"
9062  [(set (match_operand:HI 3 "s_register_operand" "=r")
9063	(mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9064			 (match_operand:SI 2 "index_operand" "rJ"))))
9065   (set (match_operand:SI 0 "s_register_operand" "=r")
9066	(plus:SI (match_dup 1) (match_dup 2)))]
9067  "TARGET_ARM
9068   && !BYTES_BIG_ENDIAN
9069   && !TARGET_MMU_TRAPS
9070   && !arm_arch4
9071   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9072   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9073   && (GET_CODE (operands[2]) != REG
9074       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9075  "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
9076  [(set_attr "type" "load")
9077   (set_attr "predicable" "yes")]
9078)
9079
9080(define_insn "*loadhi_predec"
9081  [(set (match_operand:HI 3 "s_register_operand" "=r")
9082	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9083			  (match_operand:SI 2 "s_register_operand" "r"))))
9084   (set (match_operand:SI 0 "s_register_operand" "=r")
9085	(minus:SI (match_dup 1) (match_dup 2)))]
9086  "TARGET_ARM
9087   && !BYTES_BIG_ENDIAN
9088   && !TARGET_MMU_TRAPS
9089   && !arm_arch4
9090   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9091   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9092   && (GET_CODE (operands[2]) != REG
9093       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9094  "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
9095  [(set_attr "type" "load")
9096   (set_attr "predicable" "yes")]
9097)
9098
9099(define_insn "*strqi_shiftpreinc"
9100  [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9101			  [(match_operand:SI 3 "s_register_operand" "r")
9102			   (match_operand:SI 4 "const_shift_operand" "n")])
9103			 (match_operand:SI 1 "s_register_operand" "0")))
9104	(match_operand:QI 5 "s_register_operand" "r"))
9105   (set (match_operand:SI 0 "s_register_operand" "=r")
9106	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9107		 (match_dup 1)))]
9108  "TARGET_ARM
9109   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9110   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9111   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9112  "str%?b\\t%5, [%0, %3%S2]!"
9113  [(set_attr "type" "store1")
9114   (set_attr "predicable" "yes")]
9115)
9116
9117(define_insn "*strqi_shiftpredec"
9118  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9119			  (match_operator:SI 2 "shift_operator"
9120			   [(match_operand:SI 3 "s_register_operand" "r")
9121			    (match_operand:SI 4 "const_shift_operand" "n")])))
9122	(match_operand:QI 5 "s_register_operand" "r"))
9123   (set (match_operand:SI 0 "s_register_operand" "=r")
9124	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9125						 (match_dup 4)])))]
9126  "TARGET_ARM
9127   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9128   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9129   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9130  "str%?b\\t%5, [%0, -%3%S2]!"
9131  [(set_attr "type" "store1")
9132   (set_attr "predicable" "yes")]
9133)
9134
9135(define_insn "*loadqi_shiftpreinc"
9136  [(set (match_operand:QI 5 "s_register_operand" "=r")
9137	(mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9138			  [(match_operand:SI 3 "s_register_operand" "r")
9139			   (match_operand:SI 4 "const_shift_operand" "n")])
9140			 (match_operand:SI 1 "s_register_operand" "0"))))
9141   (set (match_operand:SI 0 "s_register_operand" "=r")
9142	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9143		 (match_dup 1)))]
9144  "TARGET_ARM
9145   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9146   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9147   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9148  "ldr%?b\\t%5, [%0, %3%S2]!"
9149  [(set_attr "type" "load")
9150   (set_attr "predicable" "yes")]
9151)
9152
9153(define_insn "*loadqi_shiftpredec"
9154  [(set (match_operand:QI 5 "s_register_operand" "=r")
9155	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9156			  (match_operator:SI 2 "shift_operator"
9157			   [(match_operand:SI 3 "s_register_operand" "r")
9158			    (match_operand:SI 4 "const_shift_operand" "n")]))))
9159   (set (match_operand:SI 0 "s_register_operand" "=r")
9160	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9161						 (match_dup 4)])))]
9162  "TARGET_ARM
9163   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9164   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9165   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9166  "ldr%?b\\t%5, [%0, -%3%S2]!"
9167  [(set_attr "type" "load")
9168   (set_attr "predicable" "yes")]
9169)
9170
9171(define_insn "*strsi_shiftpreinc"
9172  [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9173			  [(match_operand:SI 3 "s_register_operand" "r")
9174			   (match_operand:SI 4 "const_shift_operand" "n")])
9175			 (match_operand:SI 1 "s_register_operand" "0")))
9176	(match_operand:SI 5 "s_register_operand" "r"))
9177   (set (match_operand:SI 0 "s_register_operand" "=r")
9178	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9179		 (match_dup 1)))]
9180  "TARGET_ARM
9181   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9182   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9183   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9184  "str%?\\t%5, [%0, %3%S2]!"
9185  [(set_attr "type" "store1")
9186   (set_attr "predicable" "yes")]
9187)
9188
9189(define_insn "*strsi_shiftpredec"
9190  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9191			  (match_operator:SI 2 "shift_operator"
9192			   [(match_operand:SI 3 "s_register_operand" "r")
9193			    (match_operand:SI 4 "const_shift_operand" "n")])))
9194	(match_operand:SI 5 "s_register_operand" "r"))
9195   (set (match_operand:SI 0 "s_register_operand" "=r")
9196	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9197						 (match_dup 4)])))]
9198  "TARGET_ARM
9199   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9200   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9201   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9202  "str%?\\t%5, [%0, -%3%S2]!"
9203  [(set_attr "type" "store1")
9204   (set_attr "predicable" "yes")]
9205)
9206
9207(define_insn "*loadsi_shiftpreinc"
9208  [(set (match_operand:SI 5 "s_register_operand" "=r")
9209	(mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9210			  [(match_operand:SI 3 "s_register_operand" "r")
9211			   (match_operand:SI 4 "const_shift_operand" "n")])
9212			 (match_operand:SI 1 "s_register_operand" "0"))))
9213   (set (match_operand:SI 0 "s_register_operand" "=r")
9214	(plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9215		 (match_dup 1)))]
9216  "TARGET_ARM
9217   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9218   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9219   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9220  "ldr%?\\t%5, [%0, %3%S2]!"
9221  [(set_attr "type" "load")
9222   (set_attr "predicable" "yes")]
9223)
9224
9225(define_insn "*loadsi_shiftpredec"
9226  [(set (match_operand:SI 5 "s_register_operand" "=r")
9227	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9228			  (match_operator:SI 2 "shift_operator"
9229			   [(match_operand:SI 3 "s_register_operand" "r")
9230			    (match_operand:SI 4 "const_shift_operand" "n")]))))
9231   (set (match_operand:SI 0 "s_register_operand" "=r")
9232	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9233						 (match_dup 4)])))]
9234  "TARGET_ARM
9235   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9236   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9237   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9238  "ldr%?\\t%5, [%0, -%3%S2]!"
9239  [(set_attr "type" "load")
9240   (set_attr "predicable" "yes")])
9241
9242(define_insn "*loadhi_shiftpreinc"
9243  [(set (match_operand:HI 5 "s_register_operand" "=r")
9244	(mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9245			  [(match_operand:SI 3 "s_register_operand" "r")
9246			   (match_operand:SI 4 "const_shift_operand" "n")])
9247			 (match_operand:SI 1 "s_register_operand" "0"))))
9248   (set (match_operand:SI 0 "s_register_operand" "=r")
9249	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
9250		 (match_dup 1)))]
9251  "TARGET_ARM
9252   && !BYTES_BIG_ENDIAN
9253   && !TARGET_MMU_TRAPS
9254   && !arm_arch4
9255   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9256   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9257   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9258  "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9259  [(set_attr "type" "load")
9260   (set_attr "predicable" "yes")]
9261)
9262
9263(define_insn "*loadhi_shiftpredec"
9264  [(set (match_operand:HI 5 "s_register_operand" "=r")
9265	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9266			  (match_operator:SI 2 "shift_operator"
9267			   [(match_operand:SI 3 "s_register_operand" "r")
9268			    (match_operand:SI 4 "const_shift_operand" "n")]))))
9269   (set (match_operand:SI 0 "s_register_operand" "=r")
9270	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9271						 (match_dup 4)])))]
9272  "TARGET_ARM
9273   && !BYTES_BIG_ENDIAN
9274   && !TARGET_MMU_TRAPS
9275   && !arm_arch4
9276   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9277   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9278   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9279  "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9280  [(set_attr "type" "load")
9281   (set_attr "predicable" "yes")]
9282)
9283
9284; It can also support extended post-inc expressions, but combine doesn't
9285; try these....
9286; It doesn't seem worth adding peepholes for anything but the most common
9287; cases since, unlike combine, the increment must immediately follow the load
9288; for this pattern to match.
9289; We must watch to see that the source/destination register isn't also the
9290; same as the base address register, and that if the index is a register,
9291; that it is not the same as the base address register.  In such cases the
9292; instruction that we would generate would have UNPREDICTABLE behavior so 
9293; we cannot use it.
9294
9295(define_peephole
9296  [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9297	(match_operand:QI 2 "s_register_operand" "r"))
9298   (set (match_dup 0)
9299	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9300  "TARGET_ARM
9301   && (REGNO (operands[2]) != REGNO (operands[0]))
9302   && (GET_CODE (operands[1]) != REG
9303       || (REGNO (operands[1]) != REGNO (operands[0])))"
9304  "str%?b\\t%2, [%0], %1"
9305)
9306
9307(define_peephole
9308  [(set (match_operand:QI 0 "s_register_operand" "=r")
9309	(mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9310   (set (match_dup 1)
9311	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9312  "TARGET_ARM
9313   && REGNO (operands[0]) != REGNO(operands[1])
9314   && (GET_CODE (operands[2]) != REG
9315       || REGNO(operands[0]) != REGNO (operands[2]))"
9316  "ldr%?b\\t%0, [%1], %2"
9317)
9318
9319(define_peephole
9320  [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9321	(match_operand:SI 2 "s_register_operand" "r"))
9322   (set (match_dup 0)
9323	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9324  "TARGET_ARM
9325   && (REGNO (operands[2]) != REGNO (operands[0]))
9326   && (GET_CODE (operands[1]) != REG
9327       || (REGNO (operands[1]) != REGNO (operands[0])))"
9328  "str%?\\t%2, [%0], %1"
9329)
9330
9331(define_peephole
9332  [(set (match_operand:HI 0 "s_register_operand" "=r")
9333	(mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9334   (set (match_dup 1)
9335	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9336  "TARGET_ARM
9337   && !BYTES_BIG_ENDIAN
9338   && !TARGET_MMU_TRAPS
9339   && !arm_arch4
9340   && REGNO (operands[0]) != REGNO(operands[1])
9341   && (GET_CODE (operands[2]) != REG
9342       || REGNO(operands[0]) != REGNO (operands[2]))"
9343  "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9344)
9345
9346(define_peephole
9347  [(set (match_operand:SI 0 "s_register_operand" "=r")
9348	(mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9349   (set (match_dup 1)
9350	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9351  "TARGET_ARM
9352   && REGNO (operands[0]) != REGNO(operands[1])
9353   && (GET_CODE (operands[2]) != REG
9354       || REGNO(operands[0]) != REGNO (operands[2]))"
9355  "ldr%?\\t%0, [%1], %2"
9356)
9357
9358(define_peephole
9359  [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9360			 (match_operand:SI 1 "index_operand" "rJ")))
9361	(match_operand:QI 2 "s_register_operand" "r"))
9362   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9363  "TARGET_ARM
9364   && (REGNO (operands[2]) != REGNO (operands[0]))
9365   && (GET_CODE (operands[1]) != REG
9366       || (REGNO (operands[1]) != REGNO (operands[0])))"
9367  "str%?b\\t%2, [%0, %1]!"
9368)
9369
9370(define_peephole
9371  [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9372			  [(match_operand:SI 0 "s_register_operand" "r")
9373			   (match_operand:SI 1 "const_int_operand" "n")])
9374			 (match_operand:SI 2 "s_register_operand" "+r")))
9375	(match_operand:QI 3 "s_register_operand" "r"))
9376   (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9377			       (match_dup 2)))]
9378  "TARGET_ARM
9379   && (REGNO (operands[3]) != REGNO (operands[2]))
9380   && (REGNO (operands[0]) != REGNO (operands[2]))"
9381  "str%?b\\t%3, [%2, %0%S4]!"
9382)
9383
9384; This pattern is never tried by combine, so do it as a peephole
9385
9386(define_peephole2
9387  [(set (match_operand:SI 0 "s_register_operand" "")
9388	(match_operand:SI 1 "s_register_operand" ""))
9389   (set (reg:CC CC_REGNUM)
9390	(compare:CC (match_dup 1) (const_int 0)))]
9391  "TARGET_ARM
9392   && (!TARGET_CIRRUS
9393       || (!cirrus_fp_register (operands[0], SImode)
9394           && !cirrus_fp_register (operands[1], SImode)))
9395  "
9396  [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9397	      (set (match_dup 0) (match_dup 1))])]
9398  ""
9399)
9400
9401; Peepholes to spot possible load- and store-multiples, if the ordering is
9402; reversed, check that the memory references aren't volatile.
9403
9404(define_peephole
9405  [(set (match_operand:SI 0 "s_register_operand" "=r")
9406        (match_operand:SI 4 "memory_operand" "m"))
9407   (set (match_operand:SI 1 "s_register_operand" "=r")
9408        (match_operand:SI 5 "memory_operand" "m"))
9409   (set (match_operand:SI 2 "s_register_operand" "=r")
9410        (match_operand:SI 6 "memory_operand" "m"))
9411   (set (match_operand:SI 3 "s_register_operand" "=r")
9412        (match_operand:SI 7 "memory_operand" "m"))]
9413  "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9414  "*
9415  return emit_ldm_seq (operands, 4);
9416  "
9417)
9418
9419(define_peephole
9420  [(set (match_operand:SI 0 "s_register_operand" "=r")
9421        (match_operand:SI 3 "memory_operand" "m"))
9422   (set (match_operand:SI 1 "s_register_operand" "=r")
9423        (match_operand:SI 4 "memory_operand" "m"))
9424   (set (match_operand:SI 2 "s_register_operand" "=r")
9425        (match_operand:SI 5 "memory_operand" "m"))]
9426  "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9427  "*
9428  return emit_ldm_seq (operands, 3);
9429  "
9430)
9431
9432(define_peephole
9433  [(set (match_operand:SI 0 "s_register_operand" "=r")
9434        (match_operand:SI 2 "memory_operand" "m"))
9435   (set (match_operand:SI 1 "s_register_operand" "=r")
9436        (match_operand:SI 3 "memory_operand" "m"))]
9437  "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9438  "*
9439  return emit_ldm_seq (operands, 2);
9440  "
9441)
9442
9443(define_peephole
9444  [(set (match_operand:SI 4 "memory_operand" "=m")
9445        (match_operand:SI 0 "s_register_operand" "r"))
9446   (set (match_operand:SI 5 "memory_operand" "=m")
9447        (match_operand:SI 1 "s_register_operand" "r"))
9448   (set (match_operand:SI 6 "memory_operand" "=m")
9449        (match_operand:SI 2 "s_register_operand" "r"))
9450   (set (match_operand:SI 7 "memory_operand" "=m")
9451        (match_operand:SI 3 "s_register_operand" "r"))]
9452  "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9453  "*
9454  return emit_stm_seq (operands, 4);
9455  "
9456)
9457
9458(define_peephole
9459  [(set (match_operand:SI 3 "memory_operand" "=m")
9460        (match_operand:SI 0 "s_register_operand" "r"))
9461   (set (match_operand:SI 4 "memory_operand" "=m")
9462        (match_operand:SI 1 "s_register_operand" "r"))
9463   (set (match_operand:SI 5 "memory_operand" "=m")
9464        (match_operand:SI 2 "s_register_operand" "r"))]
9465  "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9466  "*
9467  return emit_stm_seq (operands, 3);
9468  "
9469)
9470
9471(define_peephole
9472  [(set (match_operand:SI 2 "memory_operand" "=m")
9473        (match_operand:SI 0 "s_register_operand" "r"))
9474   (set (match_operand:SI 3 "memory_operand" "=m")
9475        (match_operand:SI 1 "s_register_operand" "r"))]
9476  "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9477  "*
9478  return emit_stm_seq (operands, 2);
9479  "
9480)
9481
9482(define_split
9483  [(set (match_operand:SI 0 "s_register_operand" "")
9484	(and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9485		       (const_int 0))
9486		(neg:SI (match_operator:SI 2 "arm_comparison_operator"
9487			 [(match_operand:SI 3 "s_register_operand" "")
9488			  (match_operand:SI 4 "arm_rhs_operand" "")]))))
9489   (clobber (match_operand:SI 5 "s_register_operand" ""))]
9490  "TARGET_ARM"
9491  [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9492   (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9493			      (match_dup 5)))]
9494  ""
9495)
9496
9497;; This split can be used because CC_Z mode implies that the following
9498;; branch will be an equality, or an unsigned inequality, so the sign
9499;; extension is not needed.
9500
9501(define_split
9502  [(set (reg:CC_Z CC_REGNUM)
9503	(compare:CC_Z
9504	 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9505		    (const_int 24))
9506	 (match_operand 1 "const_int_operand" "")))
9507   (clobber (match_scratch:SI 2 ""))]
9508  "TARGET_ARM
9509   && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9510       == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9511  [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9512   (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9513  "
9514  operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9515  "
9516)
9517
9518(define_expand "prologue"
9519  [(clobber (const_int 0))]
9520  "TARGET_EITHER"
9521  "if (TARGET_ARM)
9522     arm_expand_prologue ();
9523   else
9524     thumb_expand_prologue ();
9525  DONE;
9526  "
9527)
9528
9529(define_expand "epilogue"
9530  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9531  "TARGET_EITHER"
9532  "
9533  if (TARGET_THUMB)
9534    thumb_expand_epilogue ();
9535  else if (USE_RETURN_INSN (FALSE))
9536    {
9537      emit_jump_insn (gen_return ());
9538      DONE;
9539    }
9540  emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9541	gen_rtvec (1,
9542		gen_rtx_RETURN (VOIDmode)),
9543	VUNSPEC_EPILOGUE));
9544  DONE;
9545  "
9546)
9547
9548;; Note - although unspec_volatile's USE all hard registers,
9549;; USEs are ignored after relaod has completed.  Thus we need
9550;; to add an unspec of the link register to ensure that flow
9551;; does not think that it is unused by the sibcall branch that
9552;; will replace the standard function epilogue.
9553(define_insn "sibcall_epilogue"
9554  [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9555              (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9556  "TARGET_ARM"
9557  "*
9558  if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9559    return output_return_instruction (const_true_rtx, FALSE, FALSE);
9560  return arm_output_epilogue (next_nonnote_insn (insn));
9561  "
9562;; Length is absolute worst case
9563  [(set_attr "length" "44")
9564   (set_attr "type" "block")
9565   ;; We don't clobber the conditions, but the potential length of this
9566   ;; operation is sufficient to make conditionalizing the sequence 
9567   ;; unlikely to be profitable.
9568   (set_attr "conds" "clob")]
9569)
9570
9571(define_insn "*epilogue_insns"
9572  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9573  "TARGET_EITHER"
9574  "*
9575  if (TARGET_ARM)
9576    return arm_output_epilogue (NULL);
9577  else /* TARGET_THUMB */
9578    return thumb_unexpanded_epilogue ();
9579  "
9580  ; Length is absolute worst case
9581  [(set_attr "length" "44")
9582   (set_attr "type" "block")
9583   ;; We don't clobber the conditions, but the potential length of this
9584   ;; operation is sufficient to make conditionalizing the sequence 
9585   ;; unlikely to be profitable.
9586   (set_attr "conds" "clob")]
9587)
9588
9589(define_expand "eh_epilogue"
9590  [(use (match_operand:SI 0 "register_operand" ""))
9591   (use (match_operand:SI 1 "register_operand" ""))
9592   (use (match_operand:SI 2 "register_operand" ""))]
9593  "TARGET_EITHER"
9594  "
9595  {
9596    cfun->machine->eh_epilogue_sp_ofs = operands[1];
9597    if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9598      {
9599	rtx ra = gen_rtx_REG (Pmode, 2);
9600
9601	emit_move_insn (ra, operands[2]);
9602	operands[2] = ra;
9603      }
9604    /* This is a hack -- we may have crystalized the function type too
9605       early.  */
9606    cfun->machine->func_type = 0;
9607  }"
9608)
9609
9610;; This split is only used during output to reduce the number of patterns
9611;; that need assembler instructions adding to them.  We allowed the setting
9612;; of the conditions to be implicit during rtl generation so that
9613;; the conditional compare patterns would work.  However this conflicts to
9614;; some extent with the conditional data operations, so we have to split them
9615;; up again here.
9616
9617(define_split
9618  [(set (match_operand:SI 0 "s_register_operand" "")
9619	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9620			  [(match_operand 2 "" "") (match_operand 3 "" "")])
9621			 (match_dup 0)
9622			 (match_operand 4 "" "")))
9623   (clobber (reg:CC CC_REGNUM))]
9624  "TARGET_ARM && reload_completed"
9625  [(set (match_dup 5) (match_dup 6))
9626   (cond_exec (match_dup 7)
9627	      (set (match_dup 0) (match_dup 4)))]
9628  "
9629  {
9630    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9631					     operands[2], operands[3]);
9632    enum rtx_code rc = GET_CODE (operands[1]);
9633
9634    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9635    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9636    if (mode == CCFPmode || mode == CCFPEmode)
9637      rc = reverse_condition_maybe_unordered (rc);
9638    else
9639      rc = reverse_condition (rc);
9640
9641    operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9642  }"
9643)
9644
9645(define_split
9646  [(set (match_operand:SI 0 "s_register_operand" "")
9647	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9648			  [(match_operand 2 "" "") (match_operand 3 "" "")])
9649			 (match_operand 4 "" "")
9650			 (match_dup 0)))
9651   (clobber (reg:CC CC_REGNUM))]
9652  "TARGET_ARM && reload_completed"
9653  [(set (match_dup 5) (match_dup 6))
9654   (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9655	      (set (match_dup 0) (match_dup 4)))]
9656  "
9657  {
9658    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9659					     operands[2], operands[3]);
9660
9661    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9662    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9663  }"
9664)
9665
9666(define_split
9667  [(set (match_operand:SI 0 "s_register_operand" "")
9668	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9669			  [(match_operand 2 "" "") (match_operand 3 "" "")])
9670			 (match_operand 4 "" "")
9671			 (match_operand 5 "" "")))
9672   (clobber (reg:CC CC_REGNUM))]
9673  "TARGET_ARM && reload_completed"
9674  [(set (match_dup 6) (match_dup 7))
9675   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9676	      (set (match_dup 0) (match_dup 4)))
9677   (cond_exec (match_dup 8)
9678	      (set (match_dup 0) (match_dup 5)))]
9679  "
9680  {
9681    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9682					     operands[2], operands[3]);
9683    enum rtx_code rc = GET_CODE (operands[1]);
9684
9685    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9686    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9687    if (mode == CCFPmode || mode == CCFPEmode)
9688      rc = reverse_condition_maybe_unordered (rc);
9689    else
9690      rc = reverse_condition (rc);
9691
9692    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9693  }"
9694)
9695
9696(define_split
9697  [(set (match_operand:SI 0 "s_register_operand" "")
9698	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
9699			  [(match_operand:SI 2 "s_register_operand" "")
9700			   (match_operand:SI 3 "arm_add_operand" "")])
9701			 (match_operand:SI 4 "arm_rhs_operand" "")
9702			 (not:SI
9703			  (match_operand:SI 5 "s_register_operand" ""))))
9704   (clobber (reg:CC CC_REGNUM))]
9705  "TARGET_ARM && reload_completed"
9706  [(set (match_dup 6) (match_dup 7))
9707   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9708	      (set (match_dup 0) (match_dup 4)))
9709   (cond_exec (match_dup 8)
9710	      (set (match_dup 0) (not:SI (match_dup 5))))]
9711  "
9712  {
9713    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9714					     operands[2], operands[3]);
9715    enum rtx_code rc = GET_CODE (operands[1]);
9716
9717    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9718    operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
9719    if (mode == CCFPmode || mode == CCFPEmode)
9720      rc = reverse_condition_maybe_unordered (rc);
9721    else
9722      rc = reverse_condition (rc);
9723
9724    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9725  }"
9726)
9727
9728(define_insn "*cond_move_not"
9729  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9730	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
9731			  [(match_operand 3 "cc_register" "") (const_int 0)])
9732			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9733			 (not:SI
9734			  (match_operand:SI 2 "s_register_operand" "r,r"))))]
9735  "TARGET_ARM"
9736  "@
9737   mvn%D4\\t%0, %2
9738   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9739  [(set_attr "conds" "use")
9740   (set_attr "length" "4,8")]
9741)
9742
9743;; The next two patterns occur when an AND operation is followed by a
9744;; scc insn sequence 
9745
9746(define_insn "*sign_extract_onebit"
9747  [(set (match_operand:SI 0 "s_register_operand" "=r")
9748	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9749			 (const_int 1)
9750			 (match_operand:SI 2 "const_int_operand" "n")))
9751    (clobber (reg:CC CC_REGNUM))]
9752  "TARGET_ARM"
9753  "*
9754    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9755    output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9756    return \"mvnne\\t%0, #0\";
9757  "
9758  [(set_attr "conds" "clob")
9759   (set_attr "length" "8")]
9760)
9761
9762(define_insn "*not_signextract_onebit"
9763  [(set (match_operand:SI 0 "s_register_operand" "=r")
9764	(not:SI
9765	 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9766			  (const_int 1)
9767			  (match_operand:SI 2 "const_int_operand" "n"))))
9768   (clobber (reg:CC CC_REGNUM))]
9769  "TARGET_ARM"
9770  "*
9771    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9772    output_asm_insn (\"tst\\t%1, %2\", operands);
9773    output_asm_insn (\"mvneq\\t%0, #0\", operands);
9774    return \"movne\\t%0, #0\";
9775  "
9776  [(set_attr "conds" "clob")
9777   (set_attr "length" "12")]
9778)
9779
9780;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9781;; expressions.  For simplicity, the first register is also in the unspec
9782;; part.
9783(define_insn "*push_multi"
9784  [(match_parallel 2 "multi_register_push"
9785    [(set (match_operand:BLK 0 "memory_operand" "=m")
9786	  (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9787		      UNSPEC_PUSH_MULT))])]
9788  "TARGET_ARM"
9789  "*
9790  {
9791    int num_saves = XVECLEN (operands[2], 0);
9792     
9793    /* For the StrongARM at least it is faster to
9794       use STR to store only a single register.  */
9795    if (num_saves == 1)
9796      output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9797    else
9798      {
9799	int i;
9800	char pattern[100];
9801
9802	strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9803
9804	for (i = 1; i < num_saves; i++)
9805	  {
9806	    strcat (pattern, \", %|\");
9807	    strcat (pattern,
9808		    reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9809	  }
9810
9811	strcat (pattern, \"}\");
9812	output_asm_insn (pattern, operands);
9813      }
9814
9815    return \"\";
9816  }"
9817  [(set_attr "type" "store4")]
9818)
9819
9820(define_insn "stack_tie"
9821  [(set (mem:BLK (scratch))
9822	(unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9823		     (match_operand:SI 1 "s_register_operand" "r")]
9824		    UNSPEC_PRLG_STK))]
9825  ""
9826  ""
9827  [(set_attr "length" "0")]
9828)
9829
9830;; Similarly for the floating point registers
9831(define_insn "*push_fp_multi"
9832  [(match_parallel 2 "multi_register_push"
9833    [(set (match_operand:BLK 0 "memory_operand" "=m")
9834	  (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9835		      UNSPEC_PUSH_MULT))])]
9836  "TARGET_ARM"
9837  "*
9838  {
9839    char pattern[100];
9840
9841    sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9842    output_asm_insn (pattern, operands);
9843    return \"\";
9844  }"
9845  [(set_attr "type" "f_store")]
9846)
9847
9848;; Special patterns for dealing with the constant pool
9849
9850(define_insn "align_4"
9851  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9852  "TARGET_EITHER"
9853  "*
9854  assemble_align (32);
9855  return \"\";
9856  "
9857)
9858
9859(define_insn "align_8"
9860  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9861  "TARGET_REALLY_IWMMXT"
9862  "*
9863  assemble_align (64);
9864  return \"\";
9865  "
9866)
9867
9868(define_insn "consttable_end"
9869  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9870  "TARGET_EITHER"
9871  "*
9872  making_const_table = FALSE;
9873  return \"\";
9874  "
9875)
9876
9877(define_insn "consttable_1"
9878  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9879  "TARGET_THUMB"
9880  "*
9881  making_const_table = TRUE;
9882  assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9883  assemble_zeros (3);
9884  return \"\";
9885  "
9886  [(set_attr "length" "4")]
9887)
9888
9889(define_insn "consttable_2"
9890  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9891  "TARGET_THUMB"
9892  "*
9893  making_const_table = TRUE;
9894  assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9895  assemble_zeros (2);
9896  return \"\";
9897  "
9898  [(set_attr "length" "4")]
9899)
9900
9901(define_insn "consttable_4"
9902  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9903  "TARGET_EITHER"
9904  "*
9905  {
9906    making_const_table = TRUE;
9907    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9908      {
9909      case MODE_FLOAT:
9910      {
9911        REAL_VALUE_TYPE r;
9912        REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9913        assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9914        break;
9915      }
9916      default:
9917        assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9918        break;
9919      }
9920    return \"\";
9921  }"
9922  [(set_attr "length" "4")]
9923)
9924
9925(define_insn "consttable_8"
9926  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9927  "TARGET_EITHER"
9928  "*
9929  {
9930    making_const_table = TRUE;
9931    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9932      {
9933       case MODE_FLOAT:
9934        {
9935          REAL_VALUE_TYPE r;
9936          REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9937          assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9938          break;
9939        }
9940      default:
9941        assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9942        break;
9943      }
9944    return \"\";
9945  }"
9946  [(set_attr "length" "8")]
9947)
9948
9949;; Miscellaneous Thumb patterns
9950
9951(define_expand "tablejump"
9952  [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9953	      (use (label_ref (match_operand 1 "" "")))])]
9954  "TARGET_THUMB"
9955  "
9956  if (flag_pic)
9957    {
9958      /* Hopefully, CSE will eliminate this copy.  */
9959      rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9960      rtx reg2 = gen_reg_rtx (SImode);
9961
9962      emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9963      operands[0] = reg2;
9964    }
9965  "
9966)
9967
9968(define_insn "*thumb_tablejump"
9969  [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9970   (use (label_ref (match_operand 1 "" "")))]
9971  "TARGET_THUMB"
9972  "mov\\t%|pc, %0"
9973  [(set_attr "length" "2")]
9974)
9975
9976;; V5 Instructions,
9977
9978(define_insn "clzsi2"
9979  [(set (match_operand:SI 0 "s_register_operand" "=r")
9980	(clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
9981  "TARGET_ARM && arm_arch5"
9982  "clz%?\\t%0, %1"
9983  [(set_attr "predicable" "yes")])
9984
9985(define_expand "ffssi2"
9986  [(set (match_operand:SI 0 "s_register_operand" "")
9987	(ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9988  "TARGET_ARM && arm_arch5"
9989  "
9990  {
9991    rtx t1, t2, t3;
9992
9993    t1 = gen_reg_rtx (SImode);
9994    t2 = gen_reg_rtx (SImode);
9995    t3 = gen_reg_rtx (SImode);
9996
9997    emit_insn (gen_negsi2 (t1, operands[1]));
9998    emit_insn (gen_andsi3 (t2, operands[1], t1));
9999    emit_insn (gen_clzsi2 (t3, t2));
10000    emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10001    DONE;
10002  }"
10003)
10004
10005(define_expand "ctzsi2"
10006  [(set (match_operand:SI 0 "s_register_operand" "")
10007	(ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10008  "TARGET_ARM && arm_arch5"
10009  "
10010  {
10011    rtx t1, t2, t3;
10012
10013    t1 = gen_reg_rtx (SImode);
10014    t2 = gen_reg_rtx (SImode);
10015    t3 = gen_reg_rtx (SImode);
10016
10017    emit_insn (gen_negsi2 (t1, operands[1]));
10018    emit_insn (gen_andsi3 (t2, operands[1], t1));
10019    emit_insn (gen_clzsi2 (t3, t2));
10020    emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10021    DONE;
10022  }"
10023)
10024
10025;; V5E instructions.
10026
10027(define_insn "prefetch"
10028  [(prefetch (match_operand:SI 0 "address_operand" "p")
10029	     (match_operand:SI 1 "" "")
10030	     (match_operand:SI 2 "" ""))]
10031  "TARGET_ARM && arm_arch5e"
10032  "pld\\t%a0")
10033
10034;; General predication pattern
10035
10036(define_cond_exec
10037  [(match_operator 0 "arm_comparison_operator"
10038    [(match_operand 1 "cc_register" "")
10039     (const_int 0)])]
10040  "TARGET_ARM"
10041  ""
10042)
10043
10044(define_insn "prologue_use"
10045  [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10046  ""
10047  "%@ %0 needed for prologue"
10048)
10049
10050;; Load the FPA co-processor patterns
10051(include "fpa.md")
10052;; Load the Maverick co-processor patterns
10053(include "cirrus.md")
10054;; Load the Intel Wireless Multimedia Extension patterns
10055(include "iwmmxt.md")
10056