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