arm.md revision 96263
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)"
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) 0))]
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) (subreg:QI (match_dup 2) 0))]
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  }"
4355)
4356
4357(define_expand "storehi_single_op"
4358  [(set (match_operand:HI 0 "memory_operand" "")
4359	(match_operand:HI 1 "general_operand" ""))]
4360  "TARGET_ARM && arm_arch4"
4361  "
4362  if (!s_register_operand (operands[1], HImode))
4363    operands[1] = copy_to_mode_reg (HImode, operands[1]);
4364  "
4365)
4366
4367(define_expand "movhi"
4368  [(set (match_operand:HI 0 "general_operand" "")
4369	(match_operand:HI 1 "general_operand" ""))]
4370  "TARGET_EITHER"
4371  "
4372  if (TARGET_ARM)
4373    {
4374      if (!no_new_pseudos)
4375        {
4376          if (GET_CODE (operands[0]) == MEM)
4377	    {
4378	      if (arm_arch4)
4379	        {
4380	          emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4381	          DONE;
4382	        }
4383	      if (GET_CODE (operands[1]) == CONST_INT)
4384	        emit_insn (gen_storeinthi (operands[0], operands[1]));
4385	      else
4386	        {
4387	          if (GET_CODE (operands[1]) == MEM)
4388		    operands[1] = force_reg (HImode, operands[1]);
4389	          if (BYTES_BIG_ENDIAN)
4390		    emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4391	          else
4392		   emit_insn (gen_storehi (operands[1], operands[0]));
4393	        }
4394	      DONE;
4395	    }
4396          /* Sign extend a constant, and keep it in an SImode reg.  */
4397          else if (GET_CODE (operands[1]) == CONST_INT)
4398	    {
4399	      rtx reg = gen_reg_rtx (SImode);
4400	      HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4401
4402	      /* If the constant is already valid, leave it alone.  */
4403	      if (!const_ok_for_arm (val))
4404	        {
4405	          /* If setting all the top bits will make the constant 
4406		     loadable in a single instruction, then set them.  
4407		     Otherwise, sign extend the number.  */
4408
4409	          if (const_ok_for_arm (~(val | ~0xffff)))
4410		    val |= ~0xffff;
4411	          else if (val & 0x8000)
4412		    val |= ~0xffff;
4413	        }
4414
4415	      emit_insn (gen_movsi (reg, GEN_INT (val)));
4416	      operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
4417	    }
4418          else if (!arm_arch4)
4419	    {
4420	     /* Note: We do not have to worry about TARGET_MMU_TRAPS
4421	        for v4 and up architectures because LDRH instructions will
4422	        be used to access the HI values, and these cannot generate
4423	        unaligned word access faults in the MMU.  */
4424	      if (GET_CODE (operands[1]) == MEM)
4425	        {
4426	          if (TARGET_MMU_TRAPS)
4427		    {
4428		      rtx base;
4429		      rtx offset = const0_rtx;
4430		      rtx reg = gen_reg_rtx (SImode);
4431
4432		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4433		           || (GET_CODE (base) == PLUS
4434			       && (GET_CODE (offset = XEXP (base, 1))
4435				   == CONST_INT)
4436                               && ((INTVAL(offset) & 1) != 1)
4437			       && GET_CODE (base = XEXP (base, 0)) == REG))
4438		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4439		        {
4440		          HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4441		          rtx new;
4442
4443		          new = gen_rtx_MEM (SImode,
4444				   	     plus_constant (base, new_offset));
4445	                  MEM_COPY_ATTRIBUTES (new, operands[1]);
4446		          emit_insn (gen_movsi (reg, new));
4447		          if (((INTVAL (offset) & 2) != 0)
4448			      ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4449			    {
4450			      rtx reg2 = gen_reg_rtx (SImode);
4451
4452			      emit_insn (gen_lshrsi3 (reg2, reg,
4453					 GEN_INT (16)));
4454			      reg = reg2;
4455			    }
4456		        }
4457		      else
4458		        emit_insn (gen_movhi_bytes (reg, operands[1]));
4459
4460		      operands[1] = gen_lowpart (HImode, reg);
4461		    }
4462	          else if (BYTES_BIG_ENDIAN)
4463		    {
4464		      rtx base;
4465		      rtx offset = const0_rtx;
4466
4467		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4468		           || (GET_CODE (base) == PLUS
4469			      && (GET_CODE (offset = XEXP (base, 1))
4470				  == CONST_INT)
4471			      && GET_CODE (base = XEXP (base, 0)) == REG))
4472		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4473		        {
4474		          rtx reg = gen_reg_rtx (SImode);
4475		          rtx new;
4476
4477		          if ((INTVAL (offset) & 2) == 2)
4478			    {
4479			      HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4480			      new = gen_rtx_MEM (SImode,
4481				  	         plus_constant (base,
4482								new_offset));
4483                              MEM_COPY_ATTRIBUTES (new, operands[1]);
4484			      emit_insn (gen_movsi (reg, new));
4485			    }
4486		          else
4487			    {
4488			      new = gen_rtx_MEM (SImode,
4489						 XEXP (operands[1], 0));
4490	                      MEM_COPY_ATTRIBUTES (new, operands[1]);
4491			      emit_insn (gen_rotated_loadsi (reg, new));
4492			    }
4493
4494		          operands[1] = gen_lowpart (HImode, reg);
4495		        }
4496		      else
4497		        {
4498		          emit_insn (gen_movhi_bigend (operands[0],
4499						       operands[1]));
4500		          DONE;
4501		        }
4502		    }
4503	       }
4504	   }
4505        }
4506      /* Handle loading a large integer during reload */
4507      else if (GET_CODE (operands[1]) == CONST_INT
4508	       && !const_ok_for_arm (INTVAL (operands[1]))
4509	       && !const_ok_for_arm (~INTVAL (operands[1])))
4510        {
4511          /* Writing a constant to memory needs a scratch, which should
4512	     be handled with SECONDARY_RELOADs.  */
4513          if (GET_CODE (operands[0]) != REG)
4514	    abort ();
4515
4516          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4517          emit_insn (gen_movsi (operands[0], operands[1]));
4518          DONE;
4519       }
4520    }
4521  else /* TARGET_THUMB */
4522    {
4523      if (!no_new_pseudos)
4524        {
4525          if (GET_CODE (operands[0]) != REG)
4526	    operands[1] = force_reg (HImode, operands[1]);
4527
4528          /* ??? We shouldn't really get invalid addresses here, but this can
4529	     happen if we are passed a SP (never OK for HImode/QImode) or 
4530	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4531	     HImode/QImode) relative address.  */
4532          /* ??? This should perhaps be fixed elsewhere, for instance, in
4533	     fixup_stack_1, by checking for other kinds of invalid addresses,
4534	     e.g. a bare reference to a virtual register.  This may confuse the
4535	     alpha though, which must handle this case differently.  */
4536          if (GET_CODE (operands[0]) == MEM
4537	      && !memory_address_p (GET_MODE (operands[0]),
4538				    XEXP (operands[0], 0)))
4539	    operands[0]
4540	      = replace_equiv_address (operands[0],
4541				       copy_to_reg (XEXP (operands[0], 0)));
4542   
4543          if (GET_CODE (operands[1]) == MEM
4544	      && !memory_address_p (GET_MODE (operands[1]),
4545				    XEXP (operands[1], 0)))
4546	    operands[1]
4547	      = replace_equiv_address (operands[1],
4548				       copy_to_reg (XEXP (operands[1], 0)));
4549        }
4550      /* Handle loading a large integer during reload */
4551      else if (GET_CODE (operands[1]) == CONST_INT
4552	        && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4553        {
4554          /* Writing a constant to memory needs a scratch, which should
4555	     be handled with SECONDARY_RELOADs.  */
4556          if (GET_CODE (operands[0]) != REG)
4557	    abort ();
4558
4559          operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4560          emit_insn (gen_movsi (operands[0], operands[1]));
4561          DONE;
4562        }
4563    }
4564  "
4565)
4566
4567(define_insn "*thumb_movhi_insn"
4568  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4569	(match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4570  "TARGET_THUMB
4571   && (   register_operand (operands[0], HImode)
4572       || register_operand (operands[1], HImode))"
4573  "*
4574  switch (which_alternative)
4575    {
4576    case 0: return \"add	%0, %1, #0\";
4577    case 2: return \"strh	%1, %0\";
4578    case 3: return \"mov	%0, %1\";
4579    case 4: return \"mov	%0, %1\";
4580    case 5: return \"mov	%0, %1\";
4581    default: abort ();
4582    case 1:
4583      /* The stack pointer can end up being taken as an index register.
4584          Catch this case here and deal with it.  */
4585      if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4586	  && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4587	  && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4588        {
4589	  rtx ops[2];
4590          ops[0] = operands[0];
4591          ops[1] = XEXP (XEXP (operands[1], 0), 0);
4592      
4593          output_asm_insn (\"mov	%0, %1\", ops);
4594
4595          XEXP (XEXP (operands[1], 0), 0) = operands[0];
4596    
4597	}
4598      return \"ldrh	%0, %1\";
4599    }"
4600  [(set_attr "length" "2,4,2,2,2,2")
4601   (set_attr "type" "*,load,store1,*,*,*")
4602   (set_attr "pool_range" "*,64,*,*,*,*")]
4603)
4604
4605
4606(define_insn "rotated_loadsi"
4607  [(set (match_operand:SI            0 "s_register_operand"        "=r")
4608	(rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4609		   (const_int 16)))]
4610  "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4611  "*
4612  {
4613    rtx ops[2];
4614
4615    ops[0] = operands[0];
4616    ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4617    output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4618    return \"\";
4619  }"
4620  [(set_attr "type" "load")
4621   (set_attr "predicable" "yes")]
4622)
4623
4624(define_expand "movhi_bytes"
4625  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4626   (set (match_dup 3)
4627	(zero_extend:SI (match_dup 6)))
4628   (set (match_operand:SI 0 "" "")
4629	 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4630  "TARGET_ARM"
4631  "
4632  {
4633    rtx mem1, mem2;
4634    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4635
4636    mem1 = gen_rtx_MEM (QImode, addr);
4637    MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4638    mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4639    MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4640    operands[0] = gen_lowpart (SImode, operands[0]);
4641    operands[1] = mem1;
4642    operands[2] = gen_reg_rtx (SImode);
4643    operands[3] = gen_reg_rtx (SImode);
4644    operands[6] = mem2;
4645
4646    if (BYTES_BIG_ENDIAN)
4647      {
4648	operands[4] = operands[2];
4649	operands[5] = operands[3];
4650      }
4651    else
4652      {
4653	operands[4] = operands[3];
4654	operands[5] = operands[2];
4655      }
4656  }"
4657)
4658
4659(define_expand "movhi_bigend"
4660  [(set (match_dup 2)
4661	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4662		   (const_int 16)))
4663   (set (match_dup 3)
4664	(ashiftrt:SI (match_dup 2) (const_int 16)))
4665   (set (match_operand:HI 0 "s_register_operand" "")
4666	(subreg:HI (match_dup 3) 0))]
4667  "TARGET_ARM"
4668  "
4669  operands[2] = gen_reg_rtx (SImode);
4670  operands[3] = gen_reg_rtx (SImode);
4671  "
4672)
4673
4674;; Pattern to recognise insn generated default case above
4675(define_insn "*movhi_insn_arch4"
4676  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4677	(match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4678  "TARGET_ARM
4679   && arm_arch4
4680   && (GET_CODE (operands[1]) != CONST_INT
4681       || const_ok_for_arm (INTVAL (operands[1]))
4682       || const_ok_for_arm (~INTVAL (operands[1])))"
4683  "@
4684   mov%?\\t%0, %1\\t%@ movhi
4685   mvn%?\\t%0, #%B1\\t%@ movhi
4686   str%?h\\t%1, %0\\t%@ movhi 
4687   ldr%?h\\t%0, %1\\t%@ movhi"
4688  [(set_attr "type" "*,*,store1,load")
4689   (set_attr "predicable" "yes")
4690   (set_attr "pool_range" "*,*,*,256")
4691   (set_attr "neg_pool_range" "*,*,*,244")]
4692)
4693
4694(define_insn "*movhi_insn_littleend"
4695  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4696	(match_operand:HI 1 "general_operand"  "rI,K,m"))]
4697  "TARGET_ARM
4698   && !arm_arch4
4699   && !BYTES_BIG_ENDIAN
4700   && !TARGET_MMU_TRAPS
4701   && (GET_CODE (operands[1]) != CONST_INT
4702       || const_ok_for_arm (INTVAL (operands[1]))
4703       || const_ok_for_arm (~INTVAL (operands[1])))"
4704  "@
4705   mov%?\\t%0, %1\\t%@ movhi
4706   mvn%?\\t%0, #%B1\\t%@ movhi
4707   ldr%?\\t%0, %1\\t%@ movhi"
4708  [(set_attr "type" "*,*,load")
4709   (set_attr "predicable" "yes")
4710   (set_attr "pool_range" "4096")
4711   (set_attr "neg_pool_range" "4084")]
4712)
4713
4714(define_insn "*movhi_insn_bigend"
4715  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4716	(match_operand:HI 1 "general_operand"    "rI,K,m"))]
4717  "TARGET_ARM
4718   && !arm_arch4
4719   && BYTES_BIG_ENDIAN
4720   && !TARGET_MMU_TRAPS
4721   && (GET_CODE (operands[1]) != CONST_INT
4722       || const_ok_for_arm (INTVAL (operands[1]))
4723       || const_ok_for_arm (~INTVAL (operands[1])))"
4724  "@
4725   mov%?\\t%0, %1\\t%@ movhi
4726   mvn%?\\t%0, #%B1\\t%@ movhi
4727   ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4728  [(set_attr "type" "*,*,load")
4729   (set_attr "predicable" "yes")
4730   (set_attr "length" "4,4,8")
4731   (set_attr "pool_range" "*,*,4092")
4732   (set_attr "neg_pool_range" "*,*,4084")]
4733)
4734
4735(define_insn "*loadhi_si_bigend"
4736  [(set (match_operand:SI                       0 "s_register_operand" "=r")
4737	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4738		   (const_int 16)))]
4739  "TARGET_ARM
4740   && BYTES_BIG_ENDIAN
4741   && !TARGET_MMU_TRAPS"
4742  "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4743  [(set_attr "type" "load")
4744   (set_attr "predicable" "yes")
4745   (set_attr "pool_range" "4096")
4746   (set_attr "neg_pool_range" "4084")]
4747)
4748
4749(define_insn "*movhi_bytes"
4750  [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4751	(match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4752  "TARGET_ARM && TARGET_MMU_TRAPS"
4753  "@
4754   mov%?\\t%0, %1\\t%@ movhi
4755   mvn%?\\t%0, #%B1\\t%@ movhi"
4756  [(set_attr "predicable" "yes")]
4757)
4758
4759(define_insn "thumb_movhi_clobber"
4760  [(set (match_operand:HI     0 "memory_operand"   "=m")
4761	(match_operand:HI     1 "register_operand" "l"))
4762   (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4763  "TARGET_THUMB"
4764  "*
4765  abort ();"
4766)
4767	
4768;; We use a DImode scratch because we may occasionally need an additional
4769;; temporary if the address isn't offsettable -- push_reload doesn't seem
4770;; to take any notice of the "o" constraints on reload_memory_operand operand.
4771(define_expand "reload_outhi"
4772  [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4773	      (match_operand:HI 1 "s_register_operand"        "r")
4774	      (match_operand:DI 2 "s_register_operand"        "=&l")])]
4775  "TARGET_EITHER"
4776  "if (TARGET_ARM)
4777     arm_reload_out_hi (operands);
4778   else
4779     thumb_reload_out_hi (operands);
4780  DONE;
4781  "
4782)
4783
4784(define_expand "reload_inhi"
4785  [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4786	      (match_operand:HI 1 "arm_reload_memory_operand" "o")
4787	      (match_operand:DI 2 "s_register_operand" "=&r")])]
4788  "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4789  "
4790  if (TARGET_ARM)
4791    arm_reload_in_hi (operands);
4792  else
4793    thumb_reload_out_hi (operands);
4794  DONE;
4795")
4796
4797(define_expand "movqi"
4798  [(set (match_operand:QI 0 "general_operand" "")
4799        (match_operand:QI 1 "general_operand" ""))]
4800  "TARGET_EITHER"
4801  "
4802  if (TARGET_ARM)
4803    {
4804      /* Everything except mem = const or mem = mem can be done easily */
4805
4806      if (!no_new_pseudos)
4807        {
4808          if (GET_CODE (operands[1]) == CONST_INT)
4809	    {
4810	      rtx reg = gen_reg_rtx (SImode);
4811
4812	      emit_insn (gen_movsi (reg, operands[1]));
4813	      operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4814	    }
4815         if (GET_CODE (operands[0]) == MEM)
4816	   operands[1] = force_reg (QImode, operands[1]);
4817       }
4818    }
4819  else /* TARGET_THUMB */
4820    {
4821      if (!no_new_pseudos)
4822        {
4823          if (GET_CODE (operands[0]) != REG)
4824	    operands[1] = force_reg (QImode, operands[1]);
4825
4826          /* ??? We shouldn't really get invalid addresses here, but this can
4827	     happen if we are passed a SP (never OK for HImode/QImode) or
4828	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4829	     HImode/QImode) relative address.  */
4830          /* ??? This should perhaps be fixed elsewhere, for instance, in
4831	     fixup_stack_1, by checking for other kinds of invalid addresses,
4832	     e.g. a bare reference to a virtual register.  This may confuse the
4833	     alpha though, which must handle this case differently.  */
4834          if (GET_CODE (operands[0]) == MEM
4835	      && !memory_address_p (GET_MODE (operands[0]),
4836		  		     XEXP (operands[0], 0)))
4837	    operands[0]
4838	      = replace_equiv_address (operands[0],
4839				       copy_to_reg (XEXP (operands[0], 0)));
4840          if (GET_CODE (operands[1]) == MEM
4841	      && !memory_address_p (GET_MODE (operands[1]),
4842				    XEXP (operands[1], 0)))
4843	     operands[1]
4844	       = replace_equiv_address (operands[1],
4845					copy_to_reg (XEXP (operands[1], 0)));
4846        }
4847      /* Handle loading a large integer during reload */
4848      else if (GET_CODE (operands[1]) == CONST_INT
4849	       && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4850        {
4851          /* Writing a constant to memory needs a scratch, which should
4852	     be handled with SECONDARY_RELOADs.  */
4853          if (GET_CODE (operands[0]) != REG)
4854	    abort ();
4855
4856          operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4857          emit_insn (gen_movsi (operands[0], operands[1]));
4858          DONE;
4859       }
4860    }
4861  "
4862)
4863
4864
4865(define_insn "*arm_movqi_insn"
4866  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4867	(match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4868  "TARGET_ARM
4869   && (   register_operand (operands[0], QImode)
4870       || register_operand (operands[1], QImode))"
4871  "@
4872   mov%?\\t%0, %1
4873   mvn%?\\t%0, #%B1
4874   ldr%?b\\t%0, %1
4875   str%?b\\t%1, %0"
4876  [(set_attr "type" "*,*,load,store1")
4877   (set_attr "predicable" "yes")]
4878)
4879
4880(define_insn "*thumb_movqi_insn"
4881  [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4882	(match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4883  "TARGET_THUMB
4884   && (   register_operand (operands[0], QImode)
4885       || register_operand (operands[1], QImode))"
4886  "@
4887   add\\t%0, %1, #0
4888   ldrb\\t%0, %1
4889   strb\\t%1, %0
4890   mov\\t%0, %1
4891   mov\\t%0, %1
4892   mov\\t%0, %1"
4893  [(set_attr "length" "2")
4894   (set_attr "type" "*,load,store1,*,*,*")
4895   (set_attr "pool_range" "*,32,*,*,*,*")]
4896)
4897
4898(define_expand "movsf"
4899  [(set (match_operand:SF 0 "general_operand" "")
4900	(match_operand:SF 1 "general_operand" ""))]
4901  "TARGET_EITHER"
4902  "
4903  if (TARGET_ARM)
4904    {
4905      if (GET_CODE (operands[0]) == MEM)
4906        operands[1] = force_reg (SFmode, operands[1]);
4907    }
4908  else /* TARGET_THUMB */
4909    {
4910      if (!no_new_pseudos)
4911        {
4912           if (GET_CODE (operands[0]) != REG)
4913	     operands[1] = force_reg (SFmode, operands[1]);
4914        }
4915    }
4916  "
4917)
4918
4919(define_split
4920  [(set (match_operand:SF 0 "nonimmediate_operand" "")
4921	(match_operand:SF 1 "immediate_operand" ""))]
4922  "TARGET_ARM
4923   && !TARGET_HARD_FLOAT
4924   && reload_completed
4925   && GET_CODE (operands[1]) == CONST_DOUBLE"
4926  [(set (match_dup 2) (match_dup 3))]
4927  "
4928  operands[2] = gen_lowpart (SImode, operands[0]);
4929  operands[3] = gen_lowpart (SImode, operands[1]);
4930  if (operands[2] == 0 || operands[3] == 0)
4931    FAIL;
4932  "
4933)
4934
4935(define_insn "*arm_movsf_hard_insn"
4936  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4937	(match_operand:SF 1 "general_operand"      "fG,H,mE,f,r,f,r,mE,r"))]
4938  "TARGET_ARM
4939   && TARGET_HARD_FLOAT
4940   && (GET_CODE (operands[0]) != MEM
4941       || register_operand (operands[1], SFmode))"
4942  "@
4943   mvf%?s\\t%0, %1
4944   mnf%?s\\t%0, #%N1
4945   ldf%?s\\t%0, %1
4946   stf%?s\\t%1, %0
4947   str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4948   stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4949   mov%?\\t%0, %1
4950   ldr%?\\t%0, %1\\t%@ float
4951   str%?\\t%1, %0\\t%@ float"
4952  [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4953   (set_attr "predicable" "yes")
4954   (set_attr "type"
4955	 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4956   (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4957   (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4958)
4959
4960;; Exactly the same as above, except that all `f' cases are deleted.
4961;; This is necessary to prevent reload from ever trying to use a `f' reg
4962;; when -msoft-float.
4963
4964(define_insn "*arm_movsf_soft_insn"
4965  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4966	(match_operand:SF 1 "general_operand"  "r,mE,r"))]
4967  "TARGET_ARM
4968   && TARGET_SOFT_FLOAT
4969   && (GET_CODE (operands[0]) != MEM
4970       || register_operand (operands[1], SFmode))"
4971  "@
4972   mov%?\\t%0, %1
4973   ldr%?\\t%0, %1\\t%@ float
4974   str%?\\t%1, %0\\t%@ float"
4975  [(set_attr "length" "4,4,4")
4976   (set_attr "predicable" "yes")
4977   (set_attr "type" "*,load,store1")
4978   (set_attr "pool_range" "*,4096,*")
4979   (set_attr "neg_pool_range" "*,4084,*")]
4980)
4981
4982;;; ??? This should have alternatives for constants.
4983(define_insn "*thumb_movsf_insn"
4984  [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4985	(match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4986  "TARGET_THUMB
4987   && (   register_operand (operands[0], SFmode) 
4988       || register_operand (operands[1], SFmode))"
4989  "@
4990   add\\t%0, %1, #0
4991   ldmia\\t%1, {%0}
4992   stmia\\t%0, {%1}
4993   ldr\\t%0, %1
4994   str\\t%1, %0
4995   mov\\t%0, %1
4996   mov\\t%0, %1"
4997  [(set_attr "length" "2")
4998   (set_attr "type" "*,load,store1,load,store1,*,*")
4999   (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5000)
5001
5002(define_expand "movdf"
5003  [(set (match_operand:DF 0 "general_operand" "")
5004	(match_operand:DF 1 "general_operand" ""))]
5005  "TARGET_EITHER"
5006  "
5007  if (TARGET_ARM)
5008    {
5009      if (GET_CODE (operands[0]) == MEM)
5010        operands[1] = force_reg (DFmode, operands[1]);
5011    }
5012  else /* TARGET_THUMB */
5013    {
5014      if (!no_new_pseudos)
5015        {
5016          if (GET_CODE (operands[0]) != REG)
5017	    operands[1] = force_reg (DFmode, operands[1]);
5018        }
5019    }
5020  "
5021)
5022
5023;; Reloading a df mode value stored in integer regs to memory can require a
5024;; scratch reg.
5025(define_expand "reload_outdf"
5026  [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5027   (match_operand:DF 1 "s_register_operand" "r")
5028   (match_operand:SI 2 "s_register_operand" "=&r")]
5029  "TARGET_ARM"
5030  "
5031  {
5032    enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5033
5034    if (code == REG)
5035      operands[2] = XEXP (operands[0], 0);
5036    else if (code == POST_INC || code == PRE_DEC)
5037      {
5038	operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5039	operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5040	emit_insn (gen_movdi (operands[0], operands[1]));
5041	DONE;
5042      }
5043    else if (code == PRE_INC)
5044      {
5045	rtx reg = XEXP (XEXP (operands[0], 0), 0);
5046
5047	emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5048	operands[2] = reg;
5049      }
5050    else if (code == POST_DEC)
5051      operands[2] = XEXP (XEXP (operands[0], 0), 0);
5052    else
5053      emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5054			     XEXP (XEXP (operands[0], 0), 1)));
5055
5056    emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5057			    operands[1]));
5058
5059    if (code == POST_DEC)
5060      emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5061
5062    DONE;
5063  }"
5064)
5065
5066(define_insn "*movdf_hard_insn"
5067  [(set (match_operand:DF 0 "nonimmediate_operand"
5068						"=r,Q,r,m,r, f, f,f, m,!f,!r")
5069	(match_operand:DF 1 "general_operand"
5070						"Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5071  "TARGET_ARM
5072   && TARGET_HARD_FLOAT
5073   && (GET_CODE (operands[0]) != MEM
5074       || register_operand (operands[1], DFmode))"
5075  "*
5076  {
5077  switch (which_alternative)
5078    {
5079    default:
5080    case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5081    case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5082    case 2: case 3: case 4: return output_move_double (operands);
5083    case 5: return \"mvf%?d\\t%0, %1\";
5084    case 6: return \"mnf%?d\\t%0, #%N1\";
5085    case 7: return \"ldf%?d\\t%0, %1\";
5086    case 8: return \"stf%?d\\t%1, %0\";
5087    case 9: return output_mov_double_fpu_from_arm (operands);
5088    case 10: return output_mov_double_arm_from_fpu (operands);
5089    }
5090  }
5091  "
5092  [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5093   (set_attr "predicable" "yes")
5094   (set_attr "type"
5095    "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5096   (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
5097   (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
5098)
5099
5100;; Software floating point version.  This is essentially the same as movdi.
5101;; Do not use `f' as a constraint to prevent reload from ever trying to use
5102;; an `f' reg.
5103
5104(define_insn "*movdf_soft_insn"
5105  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5106	(match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5107  "TARGET_ARM && TARGET_SOFT_FLOAT
5108  "
5109  "* return output_move_double (operands);"
5110  [(set_attr "length" "8,8,8")
5111   (set_attr "type" "*,load,store2")
5112   (set_attr "pool_range" "1020")
5113   (set_attr "neg_pool_range" "1008")]
5114)
5115
5116;;; ??? This should have alternatives for constants.
5117;;; ??? This was originally identical to the movdi_insn pattern.
5118;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5119;;; thumb_reorg with a memory reference.
5120(define_insn "*thumb_movdf_insn"
5121  [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5122	(match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5123  "TARGET_THUMB
5124   && (   register_operand (operands[0], DFmode)
5125       || register_operand (operands[1], DFmode))"
5126  "*
5127  switch (which_alternative)
5128    {
5129    default:
5130    case 0:
5131      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5132	return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5133      return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5134    case 1:
5135      return \"ldmia\\t%1, {%0, %H0}\";
5136    case 2:
5137      return \"stmia\\t%0, {%1, %H1}\";
5138    case 3:
5139      return thumb_load_double_from_address (operands);
5140    case 4:
5141      operands[2] = gen_rtx (MEM, SImode,
5142			     plus_constant (XEXP (operands[0], 0), 4));
5143      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5144      return \"\";
5145    case 5:
5146      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5147	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5148      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5149    }
5150  "
5151  [(set_attr "length" "4,2,2,6,4,4")
5152   (set_attr "type" "*,load,store2,load,store2,*")
5153   (set_attr "pool_range" "*,*,*,1020,*,*")]
5154)
5155
5156
5157(define_expand "movxf"
5158  [(set (match_operand:XF 0 "general_operand" "")
5159	(match_operand:XF 1 "general_operand" ""))]
5160  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5161  "")
5162
5163;; Even when the XFmode patterns aren't enabled, we enable this after
5164;; reloading so that we can push floating point registers in the prologue.
5165
5166(define_insn "*movxf_hard_insn"
5167  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5168	(match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5169  "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5170  "*
5171  switch (which_alternative)
5172    {
5173    default:
5174    case 0: return \"mvf%?e\\t%0, %1\";
5175    case 1: return \"mnf%?e\\t%0, #%N1\";
5176    case 2: return \"ldf%?e\\t%0, %1\";
5177    case 3: return \"stf%?e\\t%1, %0\";
5178    case 4: return output_mov_long_double_fpu_from_arm (operands);
5179    case 5: return output_mov_long_double_arm_from_fpu (operands);
5180    case 6: return output_mov_long_double_arm_from_arm (operands);
5181    }
5182  "
5183  [(set_attr "length" "4,4,4,4,8,8,12")
5184   (set_attr "predicable" "yes")
5185   (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5186   (set_attr "pool_range" "*,*,1024,*,*,*,*")
5187   (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5188)
5189
5190
5191;; load- and store-multiple insns
5192;; The arm can load/store any set of registers, provided that they are in
5193;; ascending order; but that is beyond GCC so stick with what it knows.
5194
5195(define_expand "load_multiple"
5196  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5197                          (match_operand:SI 1 "" ""))
5198                     (use (match_operand:SI 2 "" ""))])]
5199  "TARGET_ARM"
5200  "
5201  /* Support only fixed point registers.  */
5202  if (GET_CODE (operands[2]) != CONST_INT
5203      || INTVAL (operands[2]) > 14
5204      || INTVAL (operands[2]) < 2
5205      || GET_CODE (operands[1]) != MEM
5206      || GET_CODE (operands[0]) != REG
5207      || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5208      || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5209    FAIL;
5210
5211  operands[3]
5212    = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5213			     force_reg (SImode, XEXP (operands[1], 0)),
5214			     TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5215			     MEM_IN_STRUCT_P(operands[1]),
5216	                     MEM_SCALAR_P (operands[1]));
5217  "
5218)
5219
5220;; Load multiple with write-back
5221
5222(define_insn "*ldmsi_postinc4"
5223  [(match_parallel 0 "load_multiple_operation"
5224    [(set (match_operand:SI 1 "s_register_operand" "=r")
5225	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5226		   (const_int 16)))
5227     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5228	  (mem:SI (match_dup 2)))
5229     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5230	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5231     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5232	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5233     (set (match_operand:SI 6 "arm_hard_register_operand" "")
5234	  (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5235  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5236  "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5237  [(set_attr "type" "load")
5238   (set_attr "predicable" "yes")]
5239)
5240
5241(define_insn "*ldmsi_postinc3"
5242  [(match_parallel 0 "load_multiple_operation"
5243    [(set (match_operand:SI 1 "s_register_operand" "=r")
5244	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5245		   (const_int 12)))
5246     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5247	  (mem:SI (match_dup 2)))
5248     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5249	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5250     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5251	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5252  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5253  "ldm%?ia\\t%1!, {%3, %4, %5}"
5254  [(set_attr "type" "load")
5255   (set_attr "predicable" "yes")]
5256)
5257
5258(define_insn "*ldmsi_postinc2"
5259  [(match_parallel 0 "load_multiple_operation"
5260    [(set (match_operand:SI 1 "s_register_operand" "=r")
5261	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5262		   (const_int 8)))
5263     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5264	  (mem:SI (match_dup 2)))
5265     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5266	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5267  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5268  "ldm%?ia\\t%1!, {%3, %4}"
5269  [(set_attr "type" "load")
5270   (set_attr "predicable" "yes")]
5271)
5272
5273;; Ordinary load multiple
5274
5275(define_insn "*ldmsi4"
5276  [(match_parallel 0 "load_multiple_operation"
5277    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5278	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5279     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5280	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5281     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5282	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5283     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5284	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5285  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5286  "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5287  [(set_attr "type" "load")
5288   (set_attr "predicable" "yes")]
5289)
5290
5291(define_insn "*ldmsi3"
5292  [(match_parallel 0 "load_multiple_operation"
5293    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5294	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5295     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5296	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5297     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5298	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5299  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5300  "ldm%?ia\\t%1, {%2, %3, %4}"
5301  [(set_attr "type" "load")
5302   (set_attr "predicable" "yes")]
5303)
5304
5305(define_insn "*ldmsi2"
5306  [(match_parallel 0 "load_multiple_operation"
5307    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5308	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5309     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5310	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5311  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5312  "ldm%?ia\\t%1, {%2, %3}"
5313  [(set_attr "type" "load")
5314   (set_attr "predicable" "yes")]
5315)
5316
5317(define_expand "store_multiple"
5318  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5319                          (match_operand:SI 1 "" ""))
5320                     (use (match_operand:SI 2 "" ""))])]
5321  "TARGET_ARM"
5322  "
5323  /* Support only fixed point registers */
5324  if (GET_CODE (operands[2]) != CONST_INT
5325      || INTVAL (operands[2]) > 14
5326      || INTVAL (operands[2]) < 2
5327      || GET_CODE (operands[1]) != REG
5328      || GET_CODE (operands[0]) != MEM
5329      || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5330      || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5331    FAIL;
5332
5333  operands[3]
5334    = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5335			      force_reg (SImode, XEXP (operands[0], 0)),
5336			      TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5337			      MEM_IN_STRUCT_P(operands[0]), 
5338	                      MEM_SCALAR_P (operands[0]));
5339  "
5340)
5341
5342;; Store multiple with write-back
5343
5344(define_insn "*stmsi_postinc4"
5345  [(match_parallel 0 "store_multiple_operation"
5346    [(set (match_operand:SI 1 "s_register_operand" "=r")
5347	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5348		   (const_int 16)))
5349     (set (mem:SI (match_dup 2))
5350	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5351     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5352	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5353     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5354	  (match_operand:SI 5 "arm_hard_register_operand" ""))
5355     (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5356	  (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5357  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5358  "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5359  [(set_attr "predicable" "yes")
5360   (set_attr "type" "store4")]
5361)
5362
5363(define_insn "*stmsi_postinc3"
5364  [(match_parallel 0 "store_multiple_operation"
5365    [(set (match_operand:SI 1 "s_register_operand" "=r")
5366	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5367		   (const_int 12)))
5368     (set (mem:SI (match_dup 2))
5369	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5370     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5371	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5372     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5373	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5374  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5375  "stm%?ia\\t%1!, {%3, %4, %5}"
5376  [(set_attr "predicable" "yes")
5377   (set_attr "type" "store3")]
5378)
5379
5380(define_insn "*stmsi_postinc2"
5381  [(match_parallel 0 "store_multiple_operation"
5382    [(set (match_operand:SI 1 "s_register_operand" "=r")
5383	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5384		   (const_int 8)))
5385     (set (mem:SI (match_dup 2))
5386	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5387     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5388	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5389  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5390  "stm%?ia\\t%1!, {%3, %4}"
5391  [(set_attr "predicable" "yes")
5392   (set_attr "type" "store2")]
5393)
5394
5395;; Ordinary store multiple
5396
5397(define_insn "*stmsi4"
5398  [(match_parallel 0 "store_multiple_operation"
5399    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5400	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5401     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5402	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5403     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5404	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5405     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5406	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5407  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5408  "stm%?ia\\t%1, {%2, %3, %4, %5}"
5409  [(set_attr "predicable" "yes")
5410   (set_attr "type" "store4")]
5411)
5412
5413(define_insn "*stmsi3"
5414  [(match_parallel 0 "store_multiple_operation"
5415    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5416	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5417     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5418	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5419     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5420	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5421  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5422  "stm%?ia\\t%1, {%2, %3, %4}"
5423  [(set_attr "predicable" "yes")
5424   (set_attr "type" "store3")]
5425)
5426
5427(define_insn "*stmsi2"
5428  [(match_parallel 0 "store_multiple_operation"
5429    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5430	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5431     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5432	  (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5433  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5434  "stm%?ia\\t%1, {%2, %3}"
5435  [(set_attr "predicable" "yes")
5436   (set_attr "type" "store2")]
5437)
5438
5439;; Move a block of memory if it is word aligned and MORE than 2 words long.
5440;; We could let this apply for blocks of less than this, but it clobbers so
5441;; many registers that there is then probably a better way.
5442
5443(define_expand "movstrqi"
5444  [(match_operand:BLK 0 "general_operand" "")
5445   (match_operand:BLK 1 "general_operand" "")
5446   (match_operand:SI 2 "const_int_operand" "")
5447   (match_operand:SI 3 "const_int_operand" "")]
5448  "TARGET_EITHER"
5449  "
5450  if (TARGET_ARM)
5451    {
5452      if (arm_gen_movstrqi (operands))
5453        DONE;
5454      FAIL;
5455    }
5456  else /* TARGET_THUMB */
5457    {
5458      if (   INTVAL (operands[3]) != 4
5459          || INTVAL (operands[2]) > 48)
5460        FAIL;
5461
5462      thumb_expand_movstrqi (operands);
5463      DONE;
5464    }
5465  "
5466)
5467
5468;; Thumb block-move insns
5469
5470(define_insn "movmem12b"
5471  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5472	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5473   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5474	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5475   (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5476	(mem:SI (plus:SI (match_dup 3) (const_int 8))))
5477   (set (match_operand:SI 0 "register_operand" "=l")
5478	(plus:SI (match_dup 2) (const_int 12)))
5479   (set (match_operand:SI 1 "register_operand" "=l")
5480	(plus:SI (match_dup 3) (const_int 12)))
5481   (clobber (match_scratch:SI 4 "=&l"))
5482   (clobber (match_scratch:SI 5 "=&l"))
5483   (clobber (match_scratch:SI 6 "=&l"))]
5484  "TARGET_THUMB"
5485  "* return thumb_output_move_mem_multiple (3, operands);"
5486  [(set_attr "length" "4")
5487   ; This isn't entirely accurate...  It loads as well, but in terms of
5488   ; scheduling the following insn it is better to consider it as a store
5489   (set_attr "type" "store3")]
5490)
5491
5492(define_insn "movmem8b"
5493  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5494	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5495   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5496	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5497   (set (match_operand:SI 0 "register_operand" "=l")
5498	(plus:SI (match_dup 2) (const_int 8)))
5499   (set (match_operand:SI 1 "register_operand" "=l")
5500	(plus:SI (match_dup 3) (const_int 8)))
5501   (clobber (match_scratch:SI 4 "=&l"))
5502   (clobber (match_scratch:SI 5 "=&l"))]
5503  "TARGET_THUMB"
5504  "* return thumb_output_move_mem_multiple (2, operands);"
5505  [(set_attr "length" "4")
5506   ; This isn't entirely accurate...  It loads as well, but in terms of
5507   ; scheduling the following insn it is better to consider it as a store
5508   (set_attr "type" "store2")]
5509)
5510
5511
5512
5513;; Compare & branch insns
5514;; The range calcualations are based as follows:
5515;; For forward branches, the address calculation returns the address of
5516;; the next instruction.  This is 2 beyond the branch instruction.
5517;; For backward branches, the address calculation returns the address of
5518;; the first instruction in this pattern (cmp).  This is 2 before the branch
5519;; instruction for the shortest sequence, and 4 before the branch instruction
5520;; if we have to jump around an unconditional branch.
5521;; To the basic branch range the PC offset must be added (this is +4).
5522;; So for forward branches we have 
5523;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5524;; And for backward branches we have 
5525;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5526;;
5527;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5528;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5529
5530(define_insn "cbranchsi4"
5531  [(set (pc)
5532	(if_then_else
5533	    (match_operator                    0 "arm_comparison_operator"
5534	                    [(match_operand:SI 1 "register_operand"   "l,r")
5535			     (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5536	    (label_ref       (match_operand    3 "" ""))
5537	    (pc)))]
5538  "TARGET_THUMB"
5539  "*
5540  output_asm_insn (\"cmp\\t%1, %2\", operands);
5541  switch (get_attr_length (insn))
5542    {
5543    case 4:  return \"b%d0\\t%l3\";
5544    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5545    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5546    }
5547  "
5548  [(set (attr "far_jump")
5549        (if_then_else
5550	    (eq_attr "length" "8")
5551	    (const_string "yes")
5552            (const_string "no")))
5553   (set (attr "length") 
5554        (if_then_else
5555	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5556	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5557	    (const_int 4)
5558	    (if_then_else
5559	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5560		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5561		(const_int 6)
5562		(const_int 8))))]
5563)
5564
5565(define_insn "*negated_cbranchsi4"
5566  [(set (pc)
5567	(if_then_else
5568	 (match_operator             0 "arm_comparison_operator"
5569	  [(match_operand:SI         1 "register_operand"  "l")
5570	   (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5571	 (label_ref (match_operand   3 "" ""))
5572	 (pc)))]
5573  "TARGET_THUMB"
5574  "*
5575  output_asm_insn (\"cmn\\t%1, %2\", operands);
5576  switch (get_attr_length (insn))
5577    {
5578    case 4:  return \"b%d0\\t%l3\";
5579    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5580    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5581    }
5582  "
5583  [(set (attr "far_jump")
5584        (if_then_else
5585	    (eq_attr "length" "8")
5586	    (const_string "yes")
5587            (const_string "no")))
5588   (set (attr "length") 
5589        (if_then_else
5590	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5591	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5592	    (const_int 4)
5593	    (if_then_else
5594	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5595		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5596		(const_int 6)
5597		(const_int 8))))]
5598)
5599
5600
5601;; Comparison and test insns
5602
5603(define_expand "cmpsi"
5604  [(match_operand:SI 0 "s_register_operand" "")
5605   (match_operand:SI 1 "arm_add_operand" "")]
5606  "TARGET_ARM"
5607  "{
5608    arm_compare_op0 = operands[0];
5609    arm_compare_op1 = operands[1];
5610    DONE;
5611  }"
5612)
5613
5614(define_expand "cmpsf"
5615  [(match_operand:SF 0 "s_register_operand" "")
5616   (match_operand:SF 1 "fpu_rhs_operand" "")]
5617  "TARGET_ARM && TARGET_HARD_FLOAT"
5618  "
5619  arm_compare_op0 = operands[0];
5620  arm_compare_op1 = operands[1];
5621  DONE;
5622  "
5623)
5624
5625(define_expand "cmpdf"
5626  [(match_operand:DF 0 "s_register_operand" "")
5627   (match_operand:DF 1 "fpu_rhs_operand" "")]
5628  "TARGET_ARM && TARGET_HARD_FLOAT"
5629  "
5630  arm_compare_op0 = operands[0];
5631  arm_compare_op1 = operands[1];
5632  DONE;
5633  "
5634)
5635
5636(define_expand "cmpxf"
5637  [(match_operand:XF 0 "s_register_operand" "")
5638   (match_operand:XF 1 "fpu_rhs_operand" "")]
5639  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5640  "
5641  arm_compare_op0 = operands[0];
5642  arm_compare_op1 = operands[1];
5643  DONE;
5644  "
5645)
5646
5647(define_insn "*arm_cmpsi_insn"
5648  [(set (reg:CC CC_REGNUM)
5649	(compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5650		    (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5651  "TARGET_ARM"
5652  "@
5653   cmp%?\\t%0, %1
5654   cmn%?\\t%0, #%n1"
5655  [(set_attr "conds" "set")]
5656)
5657
5658(define_insn "*cmpsi_shiftsi"
5659  [(set (reg:CC CC_REGNUM)
5660	(compare:CC (match_operand:SI   0 "s_register_operand" "r")
5661		    (match_operator:SI  3 "shift_operator"
5662		     [(match_operand:SI 1 "s_register_operand" "r")
5663		      (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5664  "TARGET_ARM"
5665  "cmp%?\\t%0, %1%S3"
5666  [(set_attr "conds" "set")
5667   (set_attr "shift" "1")
5668   ]
5669)
5670
5671(define_insn "*cmpsi_shiftsi_swp"
5672  [(set (reg:CC_SWP CC_REGNUM)
5673	(compare:CC_SWP (match_operator:SI 3 "shift_operator"
5674			 [(match_operand:SI 1 "s_register_operand" "r")
5675			  (match_operand:SI 2 "reg_or_int_operand" "rM")])
5676			(match_operand:SI 0 "s_register_operand" "r")))]
5677  "TARGET_ARM"
5678  "cmp%?\\t%0, %1%S3"
5679  [(set_attr "conds" "set")
5680   (set_attr "shift" "1")
5681   ]
5682)
5683
5684(define_insn "*cmpsi_neg_shiftsi"
5685  [(set (reg:CC CC_REGNUM)
5686	(compare:CC (match_operand:SI 0 "s_register_operand" "r")
5687		    (neg:SI (match_operator:SI 3 "shift_operator"
5688			     [(match_operand:SI 1 "s_register_operand" "r")
5689			      (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5690  "TARGET_ARM"
5691  "cmn%?\\t%0, %1%S3"
5692  [(set_attr "conds" "set")
5693   (set_attr "shift" "1")
5694   ]
5695)
5696
5697(define_insn "*cmpsf_insn"
5698  [(set (reg:CCFP CC_REGNUM)
5699	(compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5700		      (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5701  "TARGET_ARM && TARGET_HARD_FLOAT"
5702  "@
5703   cmf%?\\t%0, %1
5704   cnf%?\\t%0, #%N1"
5705  [(set_attr "conds" "set")
5706   (set_attr "type" "f_2_r")]
5707)
5708
5709(define_insn "*cmpdf_insn"
5710  [(set (reg:CCFP CC_REGNUM)
5711	(compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5712		      (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5713  "TARGET_ARM && TARGET_HARD_FLOAT"
5714  "@
5715   cmf%?\\t%0, %1
5716   cnf%?\\t%0, #%N1"
5717  [(set_attr "conds" "set")
5718   (set_attr "type" "f_2_r")]
5719)
5720
5721(define_insn "*cmpesfdf_df"
5722  [(set (reg:CCFP CC_REGNUM)
5723	(compare:CCFP (float_extend:DF
5724		       (match_operand:SF 0 "s_register_operand" "f,f"))
5725		      (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5726  "TARGET_ARM && TARGET_HARD_FLOAT"
5727  "@
5728   cmf%?\\t%0, %1
5729   cnf%?\\t%0, #%N1"
5730  [(set_attr "conds" "set")
5731   (set_attr "type" "f_2_r")]
5732)
5733
5734(define_insn "*cmpdf_esfdf"
5735  [(set (reg:CCFP CC_REGNUM)
5736	(compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5737		      (float_extend:DF
5738		       (match_operand:SF 1 "s_register_operand" "f"))))]
5739  "TARGET_ARM && TARGET_HARD_FLOAT"
5740  "cmf%?\\t%0, %1"
5741  [(set_attr "conds" "set")
5742   (set_attr "type" "f_2_r")]
5743)
5744
5745(define_insn "*cmpxf_insn"
5746  [(set (reg:CCFP CC_REGNUM)
5747	(compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5748		      (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5749  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5750  "@
5751   cmf%?\\t%0, %1
5752   cnf%?\\t%0, #%N1"
5753  [(set_attr "conds" "set")
5754   (set_attr "type" "f_2_r")]
5755)
5756
5757(define_insn "*cmpsf_trap"
5758  [(set (reg:CCFPE CC_REGNUM)
5759	(compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5760		       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5761  "TARGET_ARM && TARGET_HARD_FLOAT"
5762  "@
5763   cmf%?e\\t%0, %1
5764   cnf%?e\\t%0, #%N1"
5765  [(set_attr "conds" "set")
5766   (set_attr "type" "f_2_r")]
5767)
5768
5769(define_insn "*cmpdf_trap"
5770  [(set (reg:CCFPE CC_REGNUM)
5771	(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5772		       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5773  "TARGET_ARM && TARGET_HARD_FLOAT"
5774  "@
5775   cmf%?e\\t%0, %1
5776   cnf%?e\\t%0, #%N1"
5777  [(set_attr "conds" "set")
5778   (set_attr "type" "f_2_r")]
5779)
5780
5781(define_insn "*cmp_esfdf_df_trap"
5782  [(set (reg:CCFPE CC_REGNUM)
5783	(compare:CCFPE (float_extend:DF
5784			(match_operand:SF 0 "s_register_operand" "f,f"))
5785		       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5786  "TARGET_ARM && TARGET_HARD_FLOAT"
5787  "@
5788   cmf%?e\\t%0, %1
5789   cnf%?e\\t%0, #%N1"
5790  [(set_attr "conds" "set")
5791   (set_attr "type" "f_2_r")]
5792)
5793
5794(define_insn "*cmp_df_esfdf_trap"
5795  [(set (reg:CCFPE CC_REGNUM)
5796	(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5797		       (float_extend:DF
5798			(match_operand:SF 1 "s_register_operand" "f"))))]
5799  "TARGET_ARM && TARGET_HARD_FLOAT"
5800  "cmf%?e\\t%0, %1"
5801  [(set_attr "conds" "set")
5802   (set_attr "type" "f_2_r")]
5803)
5804
5805(define_insn "*cmpxf_trap"
5806  [(set (reg:CCFPE CC_REGNUM)
5807	(compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5808		       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5809  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5810  "@
5811   cmf%?e\\t%0, %1
5812   cnf%?e\\t%0, #%N1"
5813  [(set_attr "conds" "set")
5814   (set_attr "type" "f_2_r")]
5815)
5816
5817; This insn allows redundant compares to be removed by cse, nothing should
5818; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5819; is deleted later on. The match_dup will match the mode here, so that
5820; mode changes of the condition codes aren't lost by this even though we don't
5821; specify what they are.
5822
5823(define_insn "*deleted_compare"
5824  [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5825  "TARGET_ARM"
5826  "\\t%@ deleted compare"
5827  [(set_attr "conds" "set")
5828   (set_attr "length" "0")]
5829)
5830
5831
5832;; Conditional branch insns
5833
5834(define_expand "beq"
5835  [(set (pc)
5836	(if_then_else (eq (match_dup 1) (const_int 0))
5837		      (label_ref (match_operand 0 "" ""))
5838		      (pc)))]
5839  "TARGET_ARM"
5840  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5841)
5842
5843(define_expand "bne"
5844  [(set (pc)
5845	(if_then_else (ne (match_dup 1) (const_int 0))
5846		      (label_ref (match_operand 0 "" ""))
5847		      (pc)))]
5848  "TARGET_ARM"
5849  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5850)
5851
5852(define_expand "bgt"
5853  [(set (pc)
5854	(if_then_else (gt (match_dup 1) (const_int 0))
5855		      (label_ref (match_operand 0 "" ""))
5856		      (pc)))]
5857  "TARGET_ARM"
5858  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5859)
5860
5861(define_expand "ble"
5862  [(set (pc)
5863	(if_then_else (le (match_dup 1) (const_int 0))
5864		      (label_ref (match_operand 0 "" ""))
5865		      (pc)))]
5866  "TARGET_ARM"
5867  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5868)
5869
5870(define_expand "bge"
5871  [(set (pc)
5872	(if_then_else (ge (match_dup 1) (const_int 0))
5873		      (label_ref (match_operand 0 "" ""))
5874		      (pc)))]
5875  "TARGET_ARM"
5876  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5877)
5878
5879(define_expand "blt"
5880  [(set (pc)
5881	(if_then_else (lt (match_dup 1) (const_int 0))
5882		      (label_ref (match_operand 0 "" ""))
5883		      (pc)))]
5884  "TARGET_ARM"
5885  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5886)
5887
5888(define_expand "bgtu"
5889  [(set (pc)
5890	(if_then_else (gtu (match_dup 1) (const_int 0))
5891		      (label_ref (match_operand 0 "" ""))
5892		      (pc)))]
5893  "TARGET_ARM"
5894  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5895)
5896
5897(define_expand "bleu"
5898  [(set (pc)
5899	(if_then_else (leu (match_dup 1) (const_int 0))
5900		      (label_ref (match_operand 0 "" ""))
5901		      (pc)))]
5902  "TARGET_ARM"
5903  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5904)
5905
5906(define_expand "bgeu"
5907  [(set (pc)
5908	(if_then_else (geu (match_dup 1) (const_int 0))
5909		      (label_ref (match_operand 0 "" ""))
5910		      (pc)))]
5911  "TARGET_ARM"
5912  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5913)
5914
5915(define_expand "bltu"
5916  [(set (pc)
5917	(if_then_else (ltu (match_dup 1) (const_int 0))
5918		      (label_ref (match_operand 0 "" ""))
5919		      (pc)))]
5920  "TARGET_ARM"
5921  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5922)
5923
5924(define_expand "bunordered"
5925  [(set (pc)
5926	(if_then_else (unordered (match_dup 1) (const_int 0))
5927		      (label_ref (match_operand 0 "" ""))
5928		      (pc)))]
5929  "TARGET_ARM && TARGET_HARD_FLOAT"
5930  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5931				      arm_compare_op1);"
5932)
5933
5934(define_expand "bordered"
5935  [(set (pc)
5936	(if_then_else (ordered (match_dup 1) (const_int 0))
5937		      (label_ref (match_operand 0 "" ""))
5938		      (pc)))]
5939  "TARGET_ARM && TARGET_HARD_FLOAT"
5940  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5941				      arm_compare_op1);"
5942)
5943
5944(define_expand "bungt"
5945  [(set (pc)
5946	(if_then_else (ungt (match_dup 1) (const_int 0))
5947		      (label_ref (match_operand 0 "" ""))
5948		      (pc)))]
5949  "TARGET_ARM && TARGET_HARD_FLOAT"
5950  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5951)
5952
5953(define_expand "bunlt"
5954  [(set (pc)
5955	(if_then_else (unlt (match_dup 1) (const_int 0))
5956		      (label_ref (match_operand 0 "" ""))
5957		      (pc)))]
5958  "TARGET_ARM && TARGET_HARD_FLOAT"
5959  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5960)
5961
5962(define_expand "bunge"
5963  [(set (pc)
5964	(if_then_else (unge (match_dup 1) (const_int 0))
5965		      (label_ref (match_operand 0 "" ""))
5966		      (pc)))]
5967  "TARGET_ARM && TARGET_HARD_FLOAT"
5968  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5969)
5970
5971(define_expand "bunle"
5972  [(set (pc)
5973	(if_then_else (unle (match_dup 1) (const_int 0))
5974		      (label_ref (match_operand 0 "" ""))
5975		      (pc)))]
5976  "TARGET_ARM && TARGET_HARD_FLOAT"
5977  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5978)
5979
5980;; The following two patterns need two branch instructions, since there is
5981;; no single instruction that will handle all cases.
5982(define_expand "buneq"
5983  [(set (pc)
5984	(if_then_else (uneq (match_dup 1) (const_int 0))
5985		      (label_ref (match_operand 0 "" ""))
5986		      (pc)))]
5987  "TARGET_ARM && TARGET_HARD_FLOAT"
5988  "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5989)
5990
5991(define_expand "bltgt"
5992  [(set (pc)
5993	(if_then_else (ltgt (match_dup 1) (const_int 0))
5994		      (label_ref (match_operand 0 "" ""))
5995		      (pc)))]
5996  "TARGET_ARM && TARGET_HARD_FLOAT"
5997  "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5998)
5999
6000;;
6001;; Patterns to match conditional branch insns.
6002;;
6003
6004; Special pattern to match UNEQ.
6005(define_insn "*arm_buneq"
6006  [(set (pc)
6007	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6008		      (label_ref (match_operand 0 "" ""))
6009		      (pc)))]
6010  "TARGET_ARM && TARGET_HARD_FLOAT"
6011  "*
6012  if (arm_ccfsm_state != 0)
6013    abort ();
6014
6015  return \"bvs\\t%l0;beq\\t%l0\";
6016  "
6017  [(set_attr "conds" "jump_clob")
6018   (set_attr "length" "8")]
6019)
6020
6021; Special pattern to match LTGT.
6022(define_insn "*arm_bltgt"
6023  [(set (pc)
6024	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6025		      (label_ref (match_operand 0 "" ""))
6026		      (pc)))]
6027  "TARGET_ARM && TARGET_HARD_FLOAT"
6028  "*
6029  if (arm_ccfsm_state != 0)
6030    abort ();
6031
6032  return \"bmi\\t%l0;bgt\\t%l0\";
6033  "
6034  [(set_attr "conds" "jump_clob")
6035   (set_attr "length" "8")]
6036)
6037
6038(define_insn "*arm_cond_branch"
6039  [(set (pc)
6040	(if_then_else (match_operator 1 "arm_comparison_operator"
6041		       [(match_operand 2 "cc_register" "") (const_int 0)])
6042		      (label_ref (match_operand 0 "" ""))
6043		      (pc)))]
6044  "TARGET_ARM"
6045  "*
6046  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6047    {
6048      arm_ccfsm_state += 2;
6049      return \"\";
6050    }
6051  return \"b%d1\\t%l0\";
6052  "
6053  [(set_attr "conds" "use")]
6054)
6055
6056; Special pattern to match reversed UNEQ.
6057(define_insn "*arm_buneq_reversed"
6058  [(set (pc)
6059	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6060		      (pc)
6061		      (label_ref (match_operand 0 "" ""))))]
6062  "TARGET_ARM && TARGET_HARD_FLOAT"
6063  "*
6064  if (arm_ccfsm_state != 0)
6065    abort ();
6066
6067  return \"bmi\\t%l0;bgt\\t%l0\";
6068  "
6069  [(set_attr "conds" "jump_clob")
6070   (set_attr "length" "8")]
6071)
6072
6073; Special pattern to match reversed LTGT.
6074(define_insn "*arm_bltgt_reversed"
6075  [(set (pc)
6076	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6077		      (pc)
6078		      (label_ref (match_operand 0 "" ""))))]
6079  "TARGET_ARM && TARGET_HARD_FLOAT"
6080  "*
6081  if (arm_ccfsm_state != 0)
6082    abort ();
6083
6084  return \"bvs\\t%l0;beq\\t%l0\";
6085  "
6086  [(set_attr "conds" "jump_clob")
6087   (set_attr "length" "8")]
6088)
6089
6090(define_insn "*arm_cond_branch_reversed"
6091  [(set (pc)
6092	(if_then_else (match_operator 1 "arm_comparison_operator"
6093		       [(match_operand 2 "cc_register" "") (const_int 0)])
6094		      (pc)
6095		      (label_ref (match_operand 0 "" ""))))]
6096  "TARGET_ARM"
6097  "*
6098  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6099    {
6100      arm_ccfsm_state += 2;
6101      return \"\";
6102    }
6103  return \"b%D1\\t%l0\";
6104  "
6105  [(set_attr "conds" "use")]
6106)
6107
6108
6109
6110; scc insns
6111
6112(define_expand "seq"
6113  [(set (match_operand:SI 0 "s_register_operand" "=r")
6114	(eq:SI (match_dup 1) (const_int 0)))]
6115  "TARGET_ARM"
6116  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6117)
6118
6119(define_expand "sne"
6120  [(set (match_operand:SI 0 "s_register_operand" "=r")
6121	(ne:SI (match_dup 1) (const_int 0)))]
6122  "TARGET_ARM"
6123  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6124)
6125
6126(define_expand "sgt"
6127  [(set (match_operand:SI 0 "s_register_operand" "=r")
6128	(gt:SI (match_dup 1) (const_int 0)))]
6129  "TARGET_ARM"
6130  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6131)
6132
6133(define_expand "sle"
6134  [(set (match_operand:SI 0 "s_register_operand" "=r")
6135	(le:SI (match_dup 1) (const_int 0)))]
6136  "TARGET_ARM"
6137  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6138)
6139
6140(define_expand "sge"
6141  [(set (match_operand:SI 0 "s_register_operand" "=r")
6142	(ge:SI (match_dup 1) (const_int 0)))]
6143  "TARGET_ARM"
6144  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6145)
6146
6147(define_expand "slt"
6148  [(set (match_operand:SI 0 "s_register_operand" "=r")
6149	(lt:SI (match_dup 1) (const_int 0)))]
6150  "TARGET_ARM"
6151  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6152)
6153
6154(define_expand "sgtu"
6155  [(set (match_operand:SI 0 "s_register_operand" "=r")
6156	(gtu:SI (match_dup 1) (const_int 0)))]
6157  "TARGET_ARM"
6158  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6159)
6160
6161(define_expand "sleu"
6162  [(set (match_operand:SI 0 "s_register_operand" "=r")
6163	(leu:SI (match_dup 1) (const_int 0)))]
6164  "TARGET_ARM"
6165  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6166)
6167
6168(define_expand "sgeu"
6169  [(set (match_operand:SI 0 "s_register_operand" "=r")
6170	(geu:SI (match_dup 1) (const_int 0)))]
6171  "TARGET_ARM"
6172  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6173)
6174
6175(define_expand "sltu"
6176  [(set (match_operand:SI 0 "s_register_operand" "=r")
6177	(ltu:SI (match_dup 1) (const_int 0)))]
6178  "TARGET_ARM"
6179  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6180)
6181
6182(define_expand "sunordered"
6183  [(set (match_operand:SI 0 "s_register_operand" "=r")
6184	(unordered:SI (match_dup 1) (const_int 0)))]
6185  "TARGET_ARM && TARGET_HARD_FLOAT"
6186  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6187				      arm_compare_op1);"
6188)
6189
6190(define_expand "sordered"
6191  [(set (match_operand:SI 0 "s_register_operand" "=r")
6192	(ordered:SI (match_dup 1) (const_int 0)))]
6193  "TARGET_ARM && TARGET_HARD_FLOAT"
6194  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6195				      arm_compare_op1);"
6196)
6197
6198(define_expand "sungt"
6199  [(set (match_operand:SI 0 "s_register_operand" "=r")
6200	(ungt:SI (match_dup 1) (const_int 0)))]
6201  "TARGET_ARM && TARGET_HARD_FLOAT"
6202  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6203				      arm_compare_op1);"
6204)
6205
6206(define_expand "sunge"
6207  [(set (match_operand:SI 0 "s_register_operand" "=r")
6208	(unge:SI (match_dup 1) (const_int 0)))]
6209  "TARGET_ARM && TARGET_HARD_FLOAT"
6210  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6211				      arm_compare_op1);"
6212)
6213
6214(define_expand "sunlt"
6215  [(set (match_operand:SI 0 "s_register_operand" "=r")
6216	(unlt:SI (match_dup 1) (const_int 0)))]
6217  "TARGET_ARM && TARGET_HARD_FLOAT"
6218  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6219				      arm_compare_op1);"
6220)
6221
6222(define_expand "sunle"
6223  [(set (match_operand:SI 0 "s_register_operand" "=r")
6224	(unle:SI (match_dup 1) (const_int 0)))]
6225  "TARGET_ARM && TARGET_HARD_FLOAT"
6226  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6227				      arm_compare_op1);"
6228)
6229
6230;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6231;;; simple ARM instructions. 
6232;
6233; (define_expand "suneq"
6234;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6235; 	(uneq:SI (match_dup 1) (const_int 0)))]
6236;   "TARGET_ARM && TARGET_HARD_FLOAT"
6237;   "abort ();"
6238; )
6239;
6240; (define_expand "sltgt"
6241;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6242; 	(ltgt:SI (match_dup 1) (const_int 0)))]
6243;   "TARGET_ARM && TARGET_HARD_FLOAT"
6244;   "abort ();"
6245; )
6246
6247(define_insn "*mov_scc"
6248  [(set (match_operand:SI 0 "s_register_operand" "=r")
6249	(match_operator:SI 1 "arm_comparison_operator"
6250	 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6251  "TARGET_ARM"
6252  "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6253  [(set_attr "conds" "use")
6254   (set_attr "length" "8")]
6255)
6256
6257(define_insn "*mov_negscc"
6258  [(set (match_operand:SI 0 "s_register_operand" "=r")
6259	(neg:SI (match_operator:SI 1 "arm_comparison_operator"
6260		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6261  "TARGET_ARM"
6262  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6263  [(set_attr "conds" "use")
6264   (set_attr "length" "8")]
6265)
6266
6267(define_insn "*mov_notscc"
6268  [(set (match_operand:SI 0 "s_register_operand" "=r")
6269	(not:SI (match_operator:SI 1 "arm_comparison_operator"
6270		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6271  "TARGET_ARM"
6272  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6273  [(set_attr "conds" "use")
6274   (set_attr "length" "8")]
6275)
6276
6277
6278;; Conditional move insns
6279
6280(define_expand "movsicc"
6281  [(set (match_operand:SI 0 "s_register_operand" "")
6282	(if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6283			 (match_operand:SI 2 "arm_not_operand" "")
6284			 (match_operand:SI 3 "arm_not_operand" "")))]
6285  "TARGET_ARM"
6286  "
6287  {
6288    enum rtx_code code = GET_CODE (operands[1]);
6289    rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6290
6291    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6292  }"
6293)
6294
6295(define_expand "movsfcc"
6296  [(set (match_operand:SF 0 "s_register_operand" "")
6297	(if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6298			 (match_operand:SF 2 "s_register_operand" "")
6299			 (match_operand:SF 3 "nonmemory_operand" "")))]
6300  "TARGET_ARM"
6301  "
6302  {
6303    enum rtx_code code = GET_CODE (operands[1]);
6304    rtx ccreg;
6305
6306    /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6307       Otherwise, ensure it is a valid FP add operand */
6308    if ((!TARGET_HARD_FLOAT)
6309        || (!fpu_add_operand (operands[3], SFmode)))
6310      operands[3] = force_reg (SFmode, operands[3]);
6311
6312    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6313    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6314  }"
6315)
6316
6317(define_expand "movdfcc"
6318  [(set (match_operand:DF 0 "s_register_operand" "")
6319	(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6320			 (match_operand:DF 2 "s_register_operand" "")
6321			 (match_operand:DF 3 "fpu_add_operand" "")))]
6322  "TARGET_ARM && TARGET_HARD_FLOAT"
6323  "
6324  {
6325    enum rtx_code code = GET_CODE (operands[1]);
6326    rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6327
6328    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6329  }"
6330)
6331
6332(define_insn "*movsicc_insn"
6333  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6334	(if_then_else:SI
6335	 (match_operator 3 "arm_comparison_operator"
6336	  [(match_operand 4 "cc_register" "") (const_int 0)])
6337	 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6338	 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6339  "TARGET_ARM"
6340  "@
6341   mov%D3\\t%0, %2
6342   mvn%D3\\t%0, #%B2
6343   mov%d3\\t%0, %1
6344   mvn%d3\\t%0, #%B1
6345   mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6346   mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6347   mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6348   mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6349  [(set_attr "length" "4,4,4,4,8,8,8,8")
6350   (set_attr "conds" "use")]
6351)
6352
6353(define_insn "*movsfcc_hard_insn"
6354  [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6355	(if_then_else:SF
6356	 (match_operator 3 "arm_comparison_operator" 
6357	  [(match_operand 4 "cc_register" "") (const_int 0)])
6358	 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6359	 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6360  "TARGET_ARM && TARGET_HARD_FLOAT"
6361  "@
6362   mvf%D3s\\t%0, %2
6363   mnf%D3s\\t%0, #%N2
6364   mvf%d3s\\t%0, %1
6365   mnf%d3s\\t%0, #%N1
6366   mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6367   mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6368   mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6369   mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6370  [(set_attr "length" "4,4,4,4,8,8,8,8")
6371   (set_attr "type" "ffarith")
6372   (set_attr "conds" "use")]
6373)
6374
6375(define_insn "*movsfcc_soft_insn"
6376  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6377	(if_then_else:SF (match_operator 3 "arm_comparison_operator"
6378			  [(match_operand 4 "cc_register" "") (const_int 0)])
6379			 (match_operand:SF 1 "s_register_operand" "0,r")
6380			 (match_operand:SF 2 "s_register_operand" "r,0")))]
6381  "TARGET_ARM && TARGET_SOFT_FLOAT"
6382  "@
6383   mov%D3\\t%0, %2
6384   mov%d3\\t%0, %1"
6385  [(set_attr "conds" "use")]
6386)
6387
6388(define_insn "*movdfcc_insn"
6389  [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6390	(if_then_else:DF
6391	 (match_operator 3 "arm_comparison_operator"
6392	  [(match_operand 4 "cc_register" "") (const_int 0)])
6393	 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6394	 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6395  "TARGET_ARM && TARGET_HARD_FLOAT"
6396  "@
6397   mvf%D3d\\t%0, %2
6398   mnf%D3d\\t%0, #%N2
6399   mvf%d3d\\t%0, %1
6400   mnf%d3d\\t%0, #%N1
6401   mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6402   mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6403   mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6404   mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6405  [(set_attr "length" "4,4,4,4,8,8,8,8")
6406   (set_attr "type" "ffarith")
6407   (set_attr "conds" "use")]
6408)
6409
6410
6411;; Jump and linkage insns
6412
6413(define_expand "jump"
6414  [(set (pc)
6415	(label_ref (match_operand 0 "" "")))]
6416  "TARGET_EITHER"
6417  ""
6418)
6419
6420(define_insn "*arm_jump"
6421  [(set (pc)
6422	(label_ref (match_operand 0 "" "")))]
6423  "TARGET_ARM"
6424  "*
6425  {
6426    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6427      {
6428        arm_ccfsm_state += 2;
6429        return \"\";
6430      }
6431    return \"b%?\\t%l0\";
6432  }
6433  "
6434  [(set_attr "predicable" "yes")]
6435)
6436
6437(define_insn "*thumb_jump"
6438  [(set (pc)
6439	(label_ref (match_operand 0 "" "")))]
6440  "TARGET_THUMB"
6441  "*
6442  if (get_attr_length (insn) == 2)
6443    return \"b\\t%l0\";
6444  return \"bl\\t%l0\\t%@ far jump\";
6445  "
6446  [(set (attr "far_jump")
6447        (if_then_else
6448	    (eq_attr "length" "4")
6449	    (const_string "yes")
6450	    (const_string "no")))
6451   (set (attr "length") 
6452        (if_then_else
6453	    (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6454		 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6455  	    (const_int 2)
6456	    (const_int 4)))]
6457)
6458
6459(define_expand "call"
6460  [(parallel [(call (match_operand 0 "memory_operand" "")
6461	            (match_operand 1 "general_operand" ""))
6462	      (use (match_operand 2 "" ""))
6463	      (clobber (reg:SI LR_REGNUM))])]
6464  "TARGET_EITHER"
6465  "
6466  {
6467    rtx callee;
6468    
6469    /* In an untyped call, we can get NULL for operand 2.  */
6470    if (operands[2] == NULL_RTX)
6471      operands[2] = const0_rtx;
6472      
6473    /* This is to decide if we should generate indirect calls by loading the
6474       32 bit address of the callee into a register before performing the
6475       branch and link.  operand[2] encodes the long_call/short_call
6476       attribute of the function being called.  This attribute is set whenever
6477       __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6478       is used, and the short_call attribute can also be set if function is
6479       declared as static or if it has already been defined in the current
6480       compilation unit.  See arm.c and arm.h for info about this.  The third
6481       parameter to arm_is_longcall_p is used to tell it which pattern
6482       invoked it.  */
6483    callee  = XEXP (operands[0], 0);
6484    
6485    if (GET_CODE (callee) != REG
6486       && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6487      XEXP (operands[0], 0) = force_reg (Pmode, callee);
6488  }"
6489)
6490
6491(define_insn "*call_reg"
6492  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6493         (match_operand 1 "" ""))
6494   (use (match_operand 2 "" ""))
6495   (clobber (reg:SI LR_REGNUM))]
6496  "TARGET_ARM"
6497  "*
6498  return output_call (operands);
6499  "
6500  ;; length is worst case, normally it is only two
6501  [(set_attr "length" "12")
6502   (set_attr "type" "call")]
6503)
6504
6505(define_insn "*call_mem"
6506  [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6507	 (match_operand 1 "" ""))
6508   (use (match_operand 2 "" ""))
6509   (clobber (reg:SI LR_REGNUM))]
6510  "TARGET_ARM"
6511  "*
6512  return output_call_mem (operands);
6513  "
6514  [(set_attr "length" "12")
6515   (set_attr "type" "call")]
6516)
6517
6518(define_insn "*call_indirect"
6519  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6520	 (match_operand 1 "" ""))
6521   (use (match_operand 2 "" ""))
6522   (clobber (reg:SI LR_REGNUM))]
6523  "TARGET_THUMB"
6524  "*
6525  {
6526    if (TARGET_CALLER_INTERWORKING)
6527      return \"bl\\t%__interwork_call_via_%0\";
6528    else
6529      return \"bl\\t%__call_via_%0\";
6530  }"
6531  [(set_attr "type" "call")]
6532)
6533
6534(define_insn "*call_value_indirect"
6535  [(set (match_operand 0 "" "=l")
6536	(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6537	      (match_operand 2 "" "")))
6538   (use (match_operand 3 "" ""))
6539   (clobber (reg:SI LR_REGNUM))]
6540  "TARGET_THUMB"
6541  "*
6542  {
6543    if (TARGET_CALLER_INTERWORKING)
6544      return \"bl\\t%__interwork_call_via_%1\";
6545    else
6546      return \"bl\\t%__call_via_%1\";
6547  }"
6548  [(set_attr "type" "call")]
6549)
6550
6551(define_expand "call_value"
6552  [(parallel [(set (match_operand       0 "" "")
6553	           (call (match_operand 1 "memory_operand" "")
6554		         (match_operand 2 "general_operand" "")))
6555	      (use (match_operand 3 "" ""))
6556	      (clobber (reg:SI LR_REGNUM))])]
6557  "TARGET_EITHER"
6558  "
6559  {
6560    rtx callee = XEXP (operands[1], 0);
6561    
6562    /* In an untyped call, we can get NULL for operand 2.  */
6563    if (operands[3] == 0)
6564      operands[3] = const0_rtx;
6565      
6566    /* See the comment in define_expand \"call\".  */
6567    if (GET_CODE (callee) != REG
6568	&& arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6569      XEXP (operands[1], 0) = force_reg (Pmode, callee);
6570  }"
6571)
6572
6573(define_insn "*call_value_reg"
6574  [(set (match_operand 0 "" "=r,f")
6575        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6576	      (match_operand 2 "" "")))
6577   (use (match_operand 3 "" ""))
6578   (clobber (reg:SI LR_REGNUM))]
6579  "TARGET_ARM"
6580  "*
6581  return output_call (&operands[1]);
6582  "
6583  [(set_attr "length" "12")
6584   (set_attr "type" "call")]
6585)
6586
6587(define_insn "*call_value_mem"
6588  [(set (match_operand 0 "" "=r,f")
6589	(call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6590	      (match_operand 2 "" "")))
6591   (use (match_operand 3 "" ""))
6592   (clobber (reg:SI LR_REGNUM))]
6593  "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6594  "*
6595  return output_call_mem (&operands[1]);
6596  "
6597  [(set_attr "length" "12")
6598   (set_attr "type" "call")]
6599)
6600
6601;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6602;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6603
6604(define_insn "*call_symbol"
6605  [(call (mem:SI (match_operand:SI 0 "" "X"))
6606	 (match_operand 1 "" ""))
6607   (use (match_operand 2 "" ""))
6608   (clobber (reg:SI LR_REGNUM))]
6609  "TARGET_ARM
6610   && (GET_CODE (operands[0]) == SYMBOL_REF)
6611   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6612  "*
6613  {
6614    return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6615  }"
6616  [(set_attr "type" "call")]
6617)
6618
6619(define_insn "*call_value_symbol"
6620  [(set (match_operand 0 "s_register_operand" "=r,f")
6621	(call (mem:SI (match_operand:SI 1 "" "X,X"))
6622	(match_operand:SI 2 "" "")))
6623   (use (match_operand 3 "" ""))
6624   (clobber (reg:SI LR_REGNUM))]
6625  "TARGET_ARM
6626   && (GET_CODE (operands[1]) == SYMBOL_REF)
6627   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6628  "*
6629  {
6630    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6631  }"
6632  [(set_attr "type" "call")]
6633)
6634
6635(define_insn "*call_insn"
6636  [(call (mem:SI (match_operand:SI 0 "" "X"))
6637	 (match_operand:SI 1 "" ""))
6638   (use (match_operand 2 "" ""))
6639   (clobber (reg:SI LR_REGNUM))]
6640  "TARGET_THUMB
6641   && GET_CODE (operands[0]) == SYMBOL_REF
6642   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6643  "bl\\t%a0"
6644  [(set_attr "length" "4")
6645   (set_attr "type" "call")]
6646)
6647
6648(define_insn "*call_value_insn"
6649  [(set (match_operand 0 "register_operand" "=l")
6650	(call (mem:SI (match_operand 1 "" "X"))
6651	      (match_operand 2 "" "")))
6652   (use (match_operand 3 "" ""))
6653   (clobber (reg:SI LR_REGNUM))]
6654  "TARGET_THUMB
6655   && GET_CODE (operands[1]) == SYMBOL_REF
6656   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6657  "bl\\t%a1"
6658  [(set_attr "length" "4")
6659   (set_attr "type" "call")]
6660)
6661
6662;; We may also be able to do sibcalls for Thumb, but it's much harder...
6663(define_expand "sibcall"
6664  [(parallel [(call (match_operand 0 "memory_operand" "")
6665		    (match_operand 1 "general_operand" ""))
6666	      (use (match_operand 2 "" ""))
6667	      (use (reg:SI LR_REGNUM))])]
6668  "TARGET_ARM"
6669  "
6670  {
6671    if (operands[2] == NULL_RTX)
6672      operands[2] = const0_rtx;
6673  }"
6674)
6675
6676(define_expand "sibcall_value"
6677  [(parallel [(set (match_operand 0 "register_operand" "")
6678		   (call (match_operand 1 "memory_operand" "")
6679			 (match_operand 2 "general_operand" "")))
6680	      (use (match_operand 3 "" ""))
6681	      (use (reg:SI LR_REGNUM))])]
6682  "TARGET_ARM"
6683  "
6684  {
6685    if (operands[3] == NULL_RTX)
6686      operands[3] = const0_rtx;
6687  }"
6688)
6689
6690(define_insn "*sibcall_insn"
6691 [(call (mem:SI (match_operand:SI 0 "" "X"))
6692	(match_operand 1 "" ""))
6693  (use (match_operand 2 "" ""))
6694  (use (reg:SI LR_REGNUM))]
6695  "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6696  "*
6697  return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6698  "
6699  [(set_attr "type" "call")]
6700)
6701
6702(define_insn "*sibcall_value_insn"
6703 [(set (match_operand 0 "s_register_operand" "=r,f")
6704       (call (mem:SI (match_operand:SI 1 "" "X,X"))
6705	     (match_operand 2 "" "")))
6706  (use (match_operand 3 "" ""))
6707  (use (reg:SI LR_REGNUM))]
6708  "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6709  "*
6710  return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6711  "
6712  [(set_attr "type" "call")]
6713)
6714
6715;; Often the return insn will be the same as loading from memory, so set attr
6716(define_insn "return"
6717  [(return)]
6718  "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6719  "*
6720  {
6721    if (arm_ccfsm_state == 2)
6722      {
6723        arm_ccfsm_state += 2;
6724        return \"\";
6725      }
6726    return output_return_instruction (NULL, TRUE, FALSE);
6727  }"
6728  [(set_attr "type" "load")
6729   (set_attr "predicable" "yes")]
6730)
6731
6732(define_insn "*cond_return"
6733  [(set (pc)
6734        (if_then_else (match_operator 0 "arm_comparison_operator"
6735		       [(match_operand 1 "cc_register" "") (const_int 0)])
6736                      (return)
6737                      (pc)))]
6738  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6739  "*
6740  {
6741    if (arm_ccfsm_state == 2)
6742      {
6743        arm_ccfsm_state += 2;
6744        return \"\";
6745      }
6746    return output_return_instruction (operands[0], TRUE, FALSE);
6747  }"
6748  [(set_attr "conds" "use")
6749   (set_attr "type" "load")]
6750)
6751
6752(define_insn "*cond_return_inverted"
6753  [(set (pc)
6754        (if_then_else (match_operator 0 "arm_comparison_operator"
6755		       [(match_operand 1 "cc_register" "") (const_int 0)])
6756                      (pc)
6757		      (return)))]
6758  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6759  "*
6760  {
6761    if (arm_ccfsm_state == 2)
6762      {
6763        arm_ccfsm_state += 2;
6764        return \"\";
6765      }
6766    return output_return_instruction (operands[0], TRUE, TRUE);
6767  }"
6768  [(set_attr "conds" "use")
6769   (set_attr "type" "load")]
6770)
6771
6772;; Call subroutine returning any type.
6773
6774(define_expand "untyped_call"
6775  [(parallel [(call (match_operand 0 "" "")
6776		    (const_int 0))
6777	      (match_operand 1 "" "")
6778	      (match_operand 2 "" "")])]
6779  "TARGET_ARM"
6780  "
6781  {
6782    int i;
6783
6784    emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6785
6786    for (i = 0; i < XVECLEN (operands[2], 0); i++)
6787      {
6788	rtx set = XVECEXP (operands[2], 0, i);
6789
6790	emit_move_insn (SET_DEST (set), SET_SRC (set));
6791      }
6792
6793    /* The optimizer does not know that the call sets the function value
6794       registers we stored in the result block.  We avoid problems by
6795       claiming that all hard registers are used and clobbered at this
6796       point.  */
6797    emit_insn (gen_blockage ());
6798
6799    DONE;
6800  }"
6801)
6802
6803;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6804;; all of memory.  This blocks insns from being moved across this point.
6805
6806(define_insn "blockage"
6807  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6808  "TARGET_EITHER"
6809  ""
6810  [(set_attr "length" "0")
6811   (set_attr "type" "block")]
6812)
6813
6814(define_expand "casesi"
6815  [(match_operand:SI 0 "s_register_operand" "")	; index to jump on
6816   (match_operand:SI 1 "const_int_operand" "")	; lower bound
6817   (match_operand:SI 2 "const_int_operand" "")	; total range
6818   (match_operand:SI 3 "" "")			; table label
6819   (match_operand:SI 4 "" "")]			; Out of range label
6820  "TARGET_ARM"
6821  "
6822  {
6823    rtx reg;
6824    if (operands[1] != const0_rtx)
6825      {
6826	reg = gen_reg_rtx (SImode);
6827
6828	emit_insn (gen_addsi3 (reg, operands[0],
6829			       GEN_INT (-INTVAL (operands[1]))));
6830	operands[0] = reg;
6831      }
6832
6833    if (!const_ok_for_arm (INTVAL (operands[2])))
6834      operands[2] = force_reg (SImode, operands[2]);
6835
6836    emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6837					 operands[4]));
6838    DONE;
6839  }"
6840)
6841
6842;; The USE in this pattern is needed to tell flow analysis that this is
6843;; a CASESI insn.  It has no other purpose.
6844(define_insn "casesi_internal"
6845  [(parallel [(set (pc)
6846	       (if_then_else
6847		(leu (match_operand:SI 0 "s_register_operand" "r")
6848		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
6849		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6850				 (label_ref (match_operand 2 "" ""))))
6851		(label_ref (match_operand 3 "" ""))))
6852	      (clobber (reg:CC CC_REGNUM))
6853	      (use (label_ref (match_dup 2)))])]
6854  "TARGET_ARM"
6855  "*
6856    if (flag_pic)
6857      return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6858    return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6859  "
6860  [(set_attr "conds" "clob")
6861   (set_attr "length" "12")]
6862)
6863
6864(define_expand "indirect_jump"
6865  [(set (pc)
6866	(match_operand:SI 0 "s_register_operand" ""))]
6867  "TARGET_EITHER"
6868  ""
6869)
6870
6871(define_insn "*arm_indirect_jump"
6872  [(set (pc)
6873	(match_operand:SI 0 "s_register_operand" "r"))]
6874  "TARGET_ARM"
6875  "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6876  [(set_attr "predicable" "yes")]
6877)
6878
6879;; Although not supported by the define_expand above,
6880;; cse/combine may generate this form.
6881(define_insn "*load_indirect_jump"
6882  [(set (pc)
6883	(match_operand:SI 0 "memory_operand" "m"))]
6884  "TARGET_ARM"
6885  "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6886  [(set_attr "type" "load")
6887   (set_attr "pool_range" "4096")
6888   (set_attr "neg_pool_range" "4084")
6889   (set_attr "predicable" "yes")]
6890)
6891
6892(define_insn "*thumb_indirect_jump"
6893  [(set (pc)
6894	(match_operand:SI 0 "register_operand" "l*r"))]
6895  "TARGET_THUMB"
6896  "mov\\tpc, %0"
6897  [(set_attr "conds" "clob")
6898   (set_attr "length" "2")]
6899)
6900
6901
6902;; Misc insns
6903
6904(define_insn "nop"
6905  [(const_int 0)]
6906  "TARGET_EITHER"
6907  "*
6908  if (TARGET_ARM)
6909    return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6910  return  \"mov\\tr8, r8\";
6911  "
6912  [(set (attr "length")
6913	(if_then_else (eq_attr "is_thumb" "yes")
6914		      (const_int 2)
6915		      (const_int 4)))]
6916)
6917
6918
6919;; Patterns to allow combination of arithmetic, cond code and shifts
6920
6921(define_insn "*arith_shiftsi"
6922  [(set (match_operand:SI 0 "s_register_operand" "=r")
6923        (match_operator:SI 1 "shiftable_operator"
6924          [(match_operator:SI 3 "shift_operator"
6925             [(match_operand:SI 4 "s_register_operand" "r")
6926              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6927           (match_operand:SI 2 "s_register_operand" "r")]))]
6928  "TARGET_ARM"
6929  "%i1%?\\t%0, %2, %4%S3"
6930  [(set_attr "predicable" "yes")
6931   (set_attr "shift" "4")
6932   ]
6933)
6934
6935(define_insn "*arith_shiftsi_compare0"
6936  [(set (reg:CC_NOOV CC_REGNUM)
6937        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6938		          [(match_operator:SI 3 "shift_operator"
6939		            [(match_operand:SI 4 "s_register_operand" "r")
6940		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
6941		           (match_operand:SI 2 "s_register_operand" "r")])
6942			 (const_int 0)))
6943   (set (match_operand:SI 0 "s_register_operand" "=r")
6944	(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6945			 (match_dup 2)]))]
6946  "TARGET_ARM"
6947  "%i1%?s\\t%0, %2, %4%S3"
6948  [(set_attr "conds" "set")
6949   (set_attr "shift" "4")
6950   ]
6951)
6952
6953(define_insn "*arith_shiftsi_compare0_scratch"
6954  [(set (reg:CC_NOOV CC_REGNUM)
6955        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6956		          [(match_operator:SI 3 "shift_operator"
6957		            [(match_operand:SI 4 "s_register_operand" "r")
6958		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
6959		           (match_operand:SI 2 "s_register_operand" "r")])
6960			 (const_int 0)))
6961   (clobber (match_scratch:SI 0 "=r"))]
6962  "TARGET_ARM"
6963  "%i1%?s\\t%0, %2, %4%S3"
6964  [(set_attr "conds" "set")
6965   (set_attr "shift" "4")
6966   ]
6967)
6968
6969(define_insn "*sub_shiftsi"
6970  [(set (match_operand:SI 0 "s_register_operand" "=r")
6971	(minus:SI (match_operand:SI 1 "s_register_operand" "r")
6972		  (match_operator:SI 2 "shift_operator"
6973		   [(match_operand:SI 3 "s_register_operand" "r")
6974		    (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6975  "TARGET_ARM"
6976  "sub%?\\t%0, %1, %3%S2"
6977  [(set_attr "predicable" "yes")
6978   (set_attr "shift" "3")
6979   ]
6980)
6981
6982(define_insn "*sub_shiftsi_compare0"
6983  [(set (reg:CC_NOOV CC_REGNUM)
6984	(compare:CC_NOOV
6985	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6986		   (match_operator:SI 2 "shift_operator"
6987		    [(match_operand:SI 3 "s_register_operand" "r")
6988		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6989	 (const_int 0)))
6990   (set (match_operand:SI 0 "s_register_operand" "=r")
6991	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6992						 (match_dup 4)])))]
6993  "TARGET_ARM"
6994  "sub%?s\\t%0, %1, %3%S2"
6995  [(set_attr "conds" "set")
6996   (set_attr "shift" "3") 
6997   ]
6998)
6999
7000(define_insn "*sub_shiftsi_compare0_scratch"
7001  [(set (reg:CC_NOOV CC_REGNUM)
7002	(compare:CC_NOOV
7003	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7004		   (match_operator:SI 2 "shift_operator"
7005		    [(match_operand:SI 3 "s_register_operand" "r")
7006		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7007	 (const_int 0)))
7008   (clobber (match_scratch:SI 0 "=r"))]
7009  "TARGET_ARM"
7010  "sub%?s\\t%0, %1, %3%S2"
7011  [(set_attr "conds" "set")
7012   (set_attr "shift" "3") 
7013   ]
7014)
7015
7016;; These variants of the above insns can occur if the first operand is the
7017;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
7018;; seem to be a way around it.  Most of the predicates have to be null
7019;; because the format can be generated part way through reload, so
7020;; if we don't match it as soon as it becomes available, reload doesn't know
7021;; how to reload pseudos that haven't got hard registers; the constraints will
7022;; sort everything out.
7023
7024(define_insn "*reload_mulsi3"
7025  [(set (match_operand:SI 0 "" "=&r")
7026	(plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
7027			   [(match_operand:SI 3 "" "r")
7028			    (match_operand:SI 4 "" "rM")])
7029			  (match_operand:SI 2 "" "r"))
7030		 (match_operand:SI 1 "const_int_operand" "n")))]
7031  "TARGET_ARM && reload_in_progress"
7032  "*
7033  output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
7034  operands[2] = operands[1];
7035  operands[1] = operands[0];
7036  return output_add_immediate (operands);
7037  "
7038  [
7039   ; we have no idea how long the add_immediate is, it could be up to 4.
7040   (set_attr "length" "20")]
7041)
7042
7043(define_insn "*reload_mulsi_compare0"
7044  [(set (reg:CC_NOOV CC_REGNUM)
7045	(compare:CC_NOOV (plus:SI
7046			  (plus:SI 
7047			   (match_operator:SI 5 "shift_operator"
7048			    [(match_operand:SI 3 "" "r")
7049			     (match_operand:SI 4 "" "rM")])
7050			   (match_operand:SI 1 "" "r"))
7051			  (match_operand:SI 2 "const_int_operand" "n"))
7052			 (const_int 0)))
7053   (set (match_operand:SI 0 "" "=&r")
7054	(plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
7055			  (match_dup 1))
7056		 (match_dup 2)))]
7057  "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7058  "*
7059    output_add_immediate (operands);
7060    return \"add%?s\\t%0, %0, %3%S5\";
7061  "
7062  [(set_attr "conds" "set")
7063   (set_attr "shift" "3")
7064   (set_attr "length" "20")]
7065)
7066
7067(define_insn "*reload_mulsi_compare0_scratch"
7068  [(set (reg:CC_NOOV CC_REGNUM)
7069	(compare:CC_NOOV (plus:SI
7070			  (plus:SI 
7071			   (match_operator:SI 5 "shift_operator"
7072			    [(match_operand:SI 3 "" "r")
7073			     (match_operand:SI 4 "" "rM")])
7074			   (match_operand:SI 1 "" "r"))
7075			  (match_operand:SI 2 "const_int_operand" "n"))
7076			 (const_int 0)))
7077   (clobber (match_scratch:SI 0 "=&r"))]
7078  "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7079  "*
7080    output_add_immediate (operands);
7081    return \"add%?s\\t%0, %0, %3%S5\";
7082  "
7083  [(set_attr "conds" "set")
7084   (set_attr "shift" "3")
7085   (set_attr "length" "20")]
7086)
7087
7088;; These are similar, but are needed when the mla pattern contains the
7089;; eliminated register as operand 3.
7090
7091(define_insn "*reload_muladdsi"
7092  [(set (match_operand:SI 0 "" "=&r,&r")
7093	(plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
7094				   (match_operand:SI 2 "" "r,r"))
7095			  (match_operand:SI 3 "" "r,r"))
7096		 (match_operand:SI 4 "const_int_operand" "n,n")))]
7097  "TARGET_ARM && reload_in_progress"
7098  "*
7099  output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
7100  operands[2] = operands[4];
7101  operands[1] = operands[0];
7102  return output_add_immediate (operands);
7103  "
7104  [(set_attr "length" "20")
7105   (set_attr "type" "mult")]
7106)
7107
7108(define_insn "*reload_muladdsi_compare0"
7109  [(set (reg:CC_NOOV CC_REGNUM)
7110	(compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7111					    (match_operand:SI 3 "" "r")
7112					    (match_operand:SI 4 "" "r"))
7113					   (match_operand:SI 1 "" "r"))
7114				  (match_operand:SI 2 "const_int_operand" "n"))
7115			 (const_int 0)))
7116   (set (match_operand:SI 0 "" "=&r")
7117	(plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
7118		 (match_dup 2)))]
7119  "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7120  "*
7121    output_add_immediate (operands);
7122    output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
7123    return \"\";
7124  "
7125  [(set_attr "length" "20")
7126   (set_attr "conds" "set")
7127   (set_attr "type" "mult")]
7128)
7129
7130(define_insn "*reload_muladdsi_compare0_scratch"
7131  [(set (reg:CC_NOOV CC_REGNUM)
7132	(compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7133					    (match_operand:SI 3 "" "r")
7134					    (match_operand:SI 4 "" "r"))
7135					   (match_operand:SI 1 "" "r"))
7136				  (match_operand:SI 2 "const_int_operand" "n"))
7137			 (const_int 0)))
7138   (clobber (match_scratch:SI 0 "=&r"))]
7139  "TARGET_ARM && reload_in_progress"
7140  "*
7141    output_add_immediate (operands);
7142    return \"mla%?s\\t%0, %3, %4, %0\";
7143  "
7144  [(set_attr "length" "20")
7145   (set_attr "conds" "set")
7146   (set_attr "type" "mult")]
7147)
7148
7149
7150
7151(define_insn "*and_scc"
7152  [(set (match_operand:SI 0 "s_register_operand" "=r")
7153	(and:SI (match_operator:SI 1 "arm_comparison_operator"
7154		 [(match_operand 3 "cc_register" "") (const_int 0)])
7155		(match_operand:SI 2 "s_register_operand" "r")))]
7156  "TARGET_ARM"
7157  "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7158  [(set_attr "conds" "use")
7159   (set_attr "length" "8")]
7160)
7161
7162(define_insn "*ior_scc"
7163  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7164	(ior:SI (match_operator:SI 2 "arm_comparison_operator"
7165		 [(match_operand 3 "cc_register" "") (const_int 0)])
7166		(match_operand:SI 1 "s_register_operand" "0,?r")))]
7167  "TARGET_ARM"
7168  "@
7169   orr%d2\\t%0, %1, #1
7170   mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7171  [(set_attr "conds" "use")
7172   (set_attr "length" "4,8")]
7173)
7174
7175(define_insn "*compare_scc"
7176  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7177	(match_operator:SI 1 "arm_comparison_operator"
7178	 [(match_operand:SI 2 "s_register_operand" "r,r")
7179	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7180   (clobber (reg:CC CC_REGNUM))]
7181  "TARGET_ARM"
7182  "*
7183    if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7184      return \"mov\\t%0, %2, lsr #31\";
7185
7186    if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7187      return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7188
7189    if (GET_CODE (operands[1]) == NE)
7190      {
7191        if (which_alternative == 1)
7192	  return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7193        return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7194      }
7195    if (which_alternative == 1)
7196      output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7197    else
7198      output_asm_insn (\"cmp\\t%2, %3\", operands);
7199    return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7200  "
7201  [(set_attr "conds" "clob")
7202   (set_attr "length" "12")]
7203)
7204
7205(define_insn "*cond_move"
7206  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7207	(if_then_else:SI (match_operator 3 "equality_operator"
7208			  [(match_operator 4 "arm_comparison_operator"
7209			    [(match_operand 5 "cc_register" "") (const_int 0)])
7210			   (const_int 0)])
7211			 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7212			 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7213  "TARGET_ARM"
7214  "*
7215    if (GET_CODE (operands[3]) == NE)
7216      {
7217        if (which_alternative != 1)
7218	  output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7219        if (which_alternative != 0)
7220	  output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7221        return \"\";
7222      }
7223    if (which_alternative != 0)
7224      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7225    if (which_alternative != 1)
7226      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7227    return \"\";
7228  "
7229  [(set_attr "conds" "use")
7230   (set_attr "length" "4,4,8")]
7231)
7232
7233(define_insn "*cond_arith"
7234  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7235        (match_operator:SI 5 "shiftable_operator" 
7236	 [(match_operator:SI 4 "arm_comparison_operator"
7237           [(match_operand:SI 2 "s_register_operand" "r,r")
7238	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7239          (match_operand:SI 1 "s_register_operand" "0,?r")]))
7240   (clobber (reg:CC CC_REGNUM))]
7241  "TARGET_ARM"
7242  "*
7243    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7244      return \"%i5\\t%0, %1, %2, lsr #31\";
7245
7246    output_asm_insn (\"cmp\\t%2, %3\", operands);
7247    if (GET_CODE (operands[5]) == AND)
7248      output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7249    else if (GET_CODE (operands[5]) == MINUS)
7250      output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7251    else if (which_alternative != 0)
7252      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7253    return \"%i5%d4\\t%0, %1, #1\";
7254  "
7255  [(set_attr "conds" "clob")
7256   (set_attr "length" "12")]
7257)
7258
7259(define_insn "*cond_sub"
7260  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7261        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7262		  (match_operator:SI 4 "arm_comparison_operator"
7263                   [(match_operand:SI 2 "s_register_operand" "r,r")
7264		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7265   (clobber (reg:CC CC_REGNUM))]
7266  "TARGET_ARM"
7267  "*
7268    output_asm_insn (\"cmp\\t%2, %3\", operands);
7269    if (which_alternative != 0)
7270      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7271    return \"sub%d4\\t%0, %1, #1\";
7272  "
7273  [(set_attr "conds" "clob")
7274   (set_attr "length" "8,12")]
7275)
7276
7277(define_insn "*cmp_ite0"
7278  [(set (match_operand 6 "dominant_cc_register" "")
7279	(compare
7280	 (if_then_else:SI
7281	  (match_operator 4 "arm_comparison_operator"
7282	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7283	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7284	  (match_operator:SI 5 "arm_comparison_operator"
7285	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7286	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7287	  (const_int 0))
7288	 (const_int 0)))]
7289  "TARGET_ARM"
7290  "*
7291  {
7292    static const char * const opcodes[4][2] =
7293    {
7294      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7295       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7296      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7297       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7298      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7299       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7300      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7301       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7302    };
7303    int swap =
7304      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7305
7306    return opcodes[which_alternative][swap];
7307  }"
7308  [(set_attr "conds" "set")
7309   (set_attr "length" "8")]
7310)
7311
7312(define_insn "*cmp_ite1"
7313  [(set (match_operand 6 "dominant_cc_register" "")
7314	(compare
7315	 (if_then_else:SI
7316	  (match_operator 4 "arm_comparison_operator"
7317	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7318	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7319	  (match_operator:SI 5 "arm_comparison_operator"
7320	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7321	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7322	  (const_int 1))
7323	 (const_int 0)))]
7324  "TARGET_ARM"
7325  "*
7326  {
7327    static const char * const opcodes[4][2] =
7328    {
7329      {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7330       \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7331      {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7332       \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7333      {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7334       \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7335      {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7336       \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7337    };
7338    int swap =
7339      comparison_dominates_p (GET_CODE (operands[5]),
7340			      reverse_condition (GET_CODE (operands[4])));
7341
7342    return opcodes[which_alternative][swap];
7343  }"
7344  [(set_attr "conds" "set")
7345   (set_attr "length" "8")]
7346)
7347
7348(define_insn "*cmp_and"
7349  [(set (match_operand 6 "dominant_cc_register" "")
7350	(compare
7351	 (and:SI
7352	  (match_operator 4 "arm_comparison_operator"
7353	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7354	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7355	  (match_operator:SI 5 "arm_comparison_operator"
7356	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7357	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7358	 (const_int 0)))]
7359  "TARGET_ARM"
7360  "*
7361  {
7362    static const char *const opcodes[4][2] =
7363    {
7364      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7365       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7366      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7367       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7368      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7369       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7370      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7371       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7372    };
7373    int swap =
7374      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7375
7376    return opcodes[which_alternative][swap];
7377  }"
7378  [(set_attr "conds" "set")
7379   (set_attr "predicable" "no")
7380   (set_attr "length" "8")]
7381)
7382
7383(define_insn "*cmp_ior"
7384  [(set (match_operand 6 "dominant_cc_register" "")
7385	(compare
7386	 (ior:SI
7387	  (match_operator 4 "arm_comparison_operator"
7388	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7389	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7390	  (match_operator:SI 5 "arm_comparison_operator"
7391	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7392	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7393	 (const_int 0)))]
7394  "TARGET_ARM"
7395  "*
7396{
7397  static const char *const opcodes[4][2] =
7398  {
7399    {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7400     \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7401    {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7402     \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7403    {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7404     \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7405    {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7406     \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7407  };
7408  int swap =
7409    comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7410
7411  return opcodes[which_alternative][swap];
7412}
7413"
7414  [(set_attr "conds" "set")
7415   (set_attr "length" "8")]
7416)
7417
7418(define_insn "*negscc"
7419  [(set (match_operand:SI 0 "s_register_operand" "=r")
7420	(neg:SI (match_operator 3 "arm_comparison_operator"
7421		 [(match_operand:SI 1 "s_register_operand" "r")
7422		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7423   (clobber (reg:CC CC_REGNUM))]
7424  "TARGET_ARM"
7425  "*
7426  if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7427    return \"mov\\t%0, %1, asr #31\";
7428
7429  if (GET_CODE (operands[3]) == NE)
7430    return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7431
7432  if (GET_CODE (operands[3]) == GT)
7433    return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7434
7435  output_asm_insn (\"cmp\\t%1, %2\", operands);
7436  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7437  return \"mvn%d3\\t%0, #0\";
7438  "
7439  [(set_attr "conds" "clob")
7440   (set_attr "length" "12")]
7441)
7442
7443(define_insn "movcond"
7444  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7445	(if_then_else:SI
7446	 (match_operator 5 "arm_comparison_operator"
7447	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
7448	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7449	 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7450	 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7451   (clobber (reg:CC CC_REGNUM))]
7452  "TARGET_ARM"
7453  "*
7454  if (GET_CODE (operands[5]) == LT
7455      && (operands[4] == const0_rtx))
7456    {
7457      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7458	{
7459	  if (operands[2] == const0_rtx)
7460	    return \"and\\t%0, %1, %3, asr #31\";
7461	  return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7462	}
7463      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7464	{
7465	  if (operands[1] == const0_rtx)
7466	    return \"bic\\t%0, %2, %3, asr #31\";
7467	  return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7468	}
7469      /* The only case that falls through to here is when both ops 1 & 2
7470	 are constants */
7471    }
7472
7473  if (GET_CODE (operands[5]) == GE
7474      && (operands[4] == const0_rtx))
7475    {
7476      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7477	{
7478	  if (operands[2] == const0_rtx)
7479	    return \"bic\\t%0, %1, %3, asr #31\";
7480	  return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7481	}
7482      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7483	{
7484	  if (operands[1] == const0_rtx)
7485	    return \"and\\t%0, %2, %3, asr #31\";
7486	  return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7487	}
7488      /* The only case that falls through to here is when both ops 1 & 2
7489	 are constants */
7490    }
7491  if (GET_CODE (operands[4]) == CONST_INT
7492      && !const_ok_for_arm (INTVAL (operands[4])))
7493    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7494  else
7495    output_asm_insn (\"cmp\\t%3, %4\", operands);
7496  if (which_alternative != 0)
7497    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7498  if (which_alternative != 1)
7499    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7500  return \"\";
7501  "
7502  [(set_attr "conds" "clob")
7503   (set_attr "length" "8,8,12")]
7504)
7505
7506(define_insn "*ifcompare_plus_move"
7507  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7508	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7509			  [(match_operand:SI 4 "s_register_operand" "r,r")
7510			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7511			 (plus:SI
7512			  (match_operand:SI 2 "s_register_operand" "r,r")
7513			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7514			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7515   (clobber (reg:CC CC_REGNUM))]
7516  "TARGET_ARM"
7517  "#"
7518  [(set_attr "conds" "clob")
7519   (set_attr "length" "8,12")]
7520)
7521
7522(define_insn "*if_plus_move"
7523  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7524	(if_then_else:SI
7525	 (match_operator 4 "arm_comparison_operator"
7526	  [(match_operand 5 "cc_register" "") (const_int 0)])
7527	 (plus:SI
7528	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7529	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7530	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7531  "TARGET_ARM"
7532  "@
7533   add%d4\\t%0, %2, %3
7534   sub%d4\\t%0, %2, #%n3
7535   add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7536   sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7537  [(set_attr "conds" "use")
7538   (set_attr "length" "4,4,8,8")
7539   (set_attr "type" "*,*,*,*")]
7540)
7541
7542(define_insn "*ifcompare_move_plus"
7543  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7544	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7545			  [(match_operand:SI 4 "s_register_operand" "r,r")
7546			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7547			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7548			 (plus:SI
7549			  (match_operand:SI 2 "s_register_operand" "r,r")
7550			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7551   (clobber (reg:CC CC_REGNUM))]
7552  "TARGET_ARM"
7553  "#"
7554  [(set_attr "conds" "clob")
7555   (set_attr "length" "8,12")]
7556)
7557
7558(define_insn "*if_move_plus"
7559  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7560	(if_then_else:SI
7561	 (match_operator 4 "arm_comparison_operator"
7562	  [(match_operand 5 "cc_register" "") (const_int 0)])
7563	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7564	 (plus:SI
7565	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7566	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7567  "TARGET_ARM"
7568  "@
7569   add%D4\\t%0, %2, %3
7570   sub%D4\\t%0, %2, #%n3
7571   add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7572   sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7573  [(set_attr "conds" "use")
7574   (set_attr "length" "4,4,8,8")
7575   (set_attr "type" "*,*,*,*")]
7576)
7577
7578(define_insn "*ifcompare_arith_arith"
7579  [(set (match_operand:SI 0 "s_register_operand" "=r")
7580	(if_then_else:SI (match_operator 9 "arm_comparison_operator"
7581			  [(match_operand:SI 5 "s_register_operand" "r")
7582			   (match_operand:SI 6 "arm_add_operand" "rIL")])
7583			 (match_operator:SI 8 "shiftable_operator"
7584			  [(match_operand:SI 1 "s_register_operand" "r")
7585			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
7586			 (match_operator:SI 7 "shiftable_operator"
7587			  [(match_operand:SI 3 "s_register_operand" "r")
7588			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7589   (clobber (reg:CC CC_REGNUM))]
7590  "TARGET_ARM"
7591  "#"
7592  [(set_attr "conds" "clob")
7593   (set_attr "length" "12")]
7594)
7595
7596(define_insn "*if_arith_arith"
7597  [(set (match_operand:SI 0 "s_register_operand" "=r")
7598	(if_then_else:SI (match_operator 5 "arm_comparison_operator"
7599			  [(match_operand 8 "cc_register" "") (const_int 0)])
7600			 (match_operator:SI 6 "shiftable_operator"
7601			  [(match_operand:SI 1 "s_register_operand" "r")
7602			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
7603			 (match_operator:SI 7 "shiftable_operator"
7604			  [(match_operand:SI 3 "s_register_operand" "r")
7605			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7606  "TARGET_ARM"
7607  "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7608  [(set_attr "conds" "use")
7609   (set_attr "length" "8")]
7610)
7611
7612(define_insn "*ifcompare_arith_move"
7613  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7614	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7615			  [(match_operand:SI 2 "s_register_operand" "r,r")
7616			   (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7617			 (match_operator:SI 7 "shiftable_operator"
7618			  [(match_operand:SI 4 "s_register_operand" "r,r")
7619			   (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7620			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7621   (clobber (reg:CC CC_REGNUM))]
7622  "TARGET_ARM"
7623  "*
7624  /* If we have an operation where (op x 0) is the identity operation and
7625     the conditional operator is LT or GE and we are comparing against zero and
7626     everything is in registers then we can do this in two instructions */
7627  if (operands[3] == const0_rtx
7628      && GET_CODE (operands[7]) != AND
7629      && GET_CODE (operands[5]) == REG
7630      && GET_CODE (operands[1]) == REG 
7631      && REGNO (operands[1]) == REGNO (operands[4])
7632      && REGNO (operands[4]) != REGNO (operands[0]))
7633    {
7634      if (GET_CODE (operands[6]) == LT)
7635	return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7636      else if (GET_CODE (operands[6]) == GE)
7637	return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7638    }
7639  if (GET_CODE (operands[3]) == CONST_INT
7640      && !const_ok_for_arm (INTVAL (operands[3])))
7641    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7642  else
7643    output_asm_insn (\"cmp\\t%2, %3\", operands);
7644  output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7645  if (which_alternative != 0)
7646    return \"mov%D6\\t%0, %1\";
7647  return \"\";
7648  "
7649  [(set_attr "conds" "clob")
7650   (set_attr "length" "8,12")]
7651)
7652
7653(define_insn "*if_arith_move"
7654  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7655	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
7656			  [(match_operand 6 "cc_register" "") (const_int 0)])
7657			 (match_operator:SI 5 "shiftable_operator"
7658			  [(match_operand:SI 2 "s_register_operand" "r,r")
7659			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7660			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7661  "TARGET_ARM"
7662  "@
7663   %I5%d4\\t%0, %2, %3
7664   %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7665  [(set_attr "conds" "use")
7666   (set_attr "length" "4,8")
7667   (set_attr "type" "*,*")]
7668)
7669
7670(define_insn "*ifcompare_move_arith"
7671  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7672	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7673			  [(match_operand:SI 4 "s_register_operand" "r,r")
7674			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7675			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7676			 (match_operator:SI 7 "shiftable_operator"
7677			  [(match_operand:SI 2 "s_register_operand" "r,r")
7678			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7679   (clobber (reg:CC CC_REGNUM))]
7680  "TARGET_ARM"
7681  "*
7682  /* If we have an operation where (op x 0) is the identity operation and
7683     the conditional operator is LT or GE and we are comparing against zero and
7684     everything is in registers then we can do this in two instructions */
7685  if (operands[5] == const0_rtx
7686      && GET_CODE (operands[7]) != AND
7687      && GET_CODE (operands[3]) == REG
7688      && GET_CODE (operands[1]) == REG 
7689      && REGNO (operands[1]) == REGNO (operands[2])
7690      && REGNO (operands[2]) != REGNO (operands[0]))
7691    {
7692      if (GET_CODE (operands[6]) == GE)
7693	return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7694      else if (GET_CODE (operands[6]) == LT)
7695	return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7696    }
7697
7698  if (GET_CODE (operands[5]) == CONST_INT
7699      && !const_ok_for_arm (INTVAL (operands[5])))
7700    output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7701  else
7702    output_asm_insn (\"cmp\\t%4, %5\", operands);
7703
7704  if (which_alternative != 0)
7705    output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7706  return \"%I7%D6\\t%0, %2, %3\";
7707  "
7708  [(set_attr "conds" "clob")
7709   (set_attr "length" "8,12")]
7710)
7711
7712(define_insn "*if_move_arith"
7713  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7714	(if_then_else:SI
7715	 (match_operator 4 "arm_comparison_operator"
7716	  [(match_operand 6 "cc_register" "") (const_int 0)])
7717	 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7718	 (match_operator:SI 5 "shiftable_operator"
7719	  [(match_operand:SI 2 "s_register_operand" "r,r")
7720	   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7721  "TARGET_ARM"
7722  "@
7723   %I5%D4\\t%0, %2, %3
7724   %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7725  [(set_attr "conds" "use")
7726   (set_attr "length" "4,8")
7727   (set_attr "type" "*,*")]
7728)
7729
7730(define_insn "*ifcompare_move_not"
7731  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7732	(if_then_else:SI
7733	 (match_operator 5 "arm_comparison_operator"
7734	  [(match_operand:SI 3 "s_register_operand" "r,r")
7735	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7736	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7737	 (not:SI
7738	  (match_operand:SI 2 "s_register_operand" "r,r"))))
7739   (clobber (reg:CC CC_REGNUM))]
7740  "TARGET_ARM"
7741  "#"
7742  [(set_attr "conds" "clob")
7743   (set_attr "length" "8,12")]
7744)
7745
7746(define_insn "*if_move_not"
7747  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7748	(if_then_else:SI
7749	 (match_operator 4 "arm_comparison_operator"
7750	  [(match_operand 3 "cc_register" "") (const_int 0)])
7751	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7752	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7753  "TARGET_ARM"
7754  "@
7755   mvn%D4\\t%0, %2
7756   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7757   mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7758  [(set_attr "conds" "use")
7759   (set_attr "length" "4,8,8")]
7760)
7761
7762(define_insn "*ifcompare_not_move"
7763  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7764	(if_then_else:SI 
7765	 (match_operator 5 "arm_comparison_operator"
7766	  [(match_operand:SI 3 "s_register_operand" "r,r")
7767	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7768	 (not:SI
7769	  (match_operand:SI 2 "s_register_operand" "r,r"))
7770	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7771   (clobber (reg:CC CC_REGNUM))]
7772  "TARGET_ARM"
7773  "#"
7774  [(set_attr "conds" "clob")
7775   (set_attr "length" "8,12")]
7776)
7777
7778(define_insn "*if_not_move"
7779  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7780	(if_then_else:SI
7781	 (match_operator 4 "arm_comparison_operator"
7782	  [(match_operand 3 "cc_register" "") (const_int 0)])
7783	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7784	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7785  "TARGET_ARM"
7786  "@
7787   mvn%d4\\t%0, %2
7788   mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7789   mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7790  [(set_attr "conds" "use")
7791   (set_attr "length" "4,8,8")]
7792)
7793
7794(define_insn "*ifcompare_shift_move"
7795  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7796	(if_then_else:SI
7797	 (match_operator 6 "arm_comparison_operator"
7798	  [(match_operand:SI 4 "s_register_operand" "r,r")
7799	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7800	 (match_operator:SI 7 "shift_operator"
7801	  [(match_operand:SI 2 "s_register_operand" "r,r")
7802	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7803	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7804   (clobber (reg:CC CC_REGNUM))]
7805  "TARGET_ARM"
7806  "#"
7807  [(set_attr "conds" "clob")
7808   (set_attr "length" "8,12")]
7809)
7810
7811(define_insn "*if_shift_move"
7812  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7813	(if_then_else:SI
7814	 (match_operator 5 "arm_comparison_operator"
7815	  [(match_operand 6 "cc_register" "") (const_int 0)])
7816	 (match_operator:SI 4 "shift_operator"
7817	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
7818	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7819	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7820  "TARGET_ARM"
7821  "@
7822   mov%d5\\t%0, %2%S4
7823   mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7824   mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7825  [(set_attr "conds" "use")
7826   (set_attr "shift" "2")
7827   (set_attr "length" "4,8,8")]
7828)
7829
7830(define_insn "*ifcompare_move_shift"
7831  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7832	(if_then_else:SI
7833	 (match_operator 6 "arm_comparison_operator"
7834	  [(match_operand:SI 4 "s_register_operand" "r,r")
7835	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7836	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7837	 (match_operator:SI 7 "shift_operator"
7838	  [(match_operand:SI 2 "s_register_operand" "r,r")
7839	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7840   (clobber (reg:CC CC_REGNUM))]
7841  "TARGET_ARM"
7842  "#"
7843  [(set_attr "conds" "clob")
7844   (set_attr "length" "8,12")]
7845)
7846
7847(define_insn "*if_move_shift"
7848  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7849	(if_then_else:SI
7850	 (match_operator 5 "arm_comparison_operator"
7851	  [(match_operand 6 "cc_register" "") (const_int 0)])
7852	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7853	 (match_operator:SI 4 "shift_operator"
7854	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
7855	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7856  "TARGET_ARM"
7857  "@
7858   mov%D5\\t%0, %2%S4
7859   mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7860   mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7861  [(set_attr "conds" "use")
7862   (set_attr "shift" "2")
7863   (set_attr "length" "4,8,8")]
7864)
7865
7866(define_insn "*ifcompare_shift_shift"
7867  [(set (match_operand:SI 0 "s_register_operand" "=r")
7868	(if_then_else:SI
7869	 (match_operator 7 "arm_comparison_operator"
7870	  [(match_operand:SI 5 "s_register_operand" "r")
7871	   (match_operand:SI 6 "arm_add_operand" "rIL")])
7872	 (match_operator:SI 8 "shift_operator"
7873	  [(match_operand:SI 1 "s_register_operand" "r")
7874	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
7875	 (match_operator:SI 9 "shift_operator"
7876	  [(match_operand:SI 3 "s_register_operand" "r")
7877	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7878   (clobber (reg:CC CC_REGNUM))]
7879  "TARGET_ARM"
7880  "#"
7881  [(set_attr "conds" "clob")
7882   (set_attr "length" "12")]
7883)
7884
7885(define_insn "*if_shift_shift"
7886  [(set (match_operand:SI 0 "s_register_operand" "=r")
7887	(if_then_else:SI
7888	 (match_operator 5 "arm_comparison_operator"
7889	  [(match_operand 8 "cc_register" "") (const_int 0)])
7890	 (match_operator:SI 6 "shift_operator"
7891	  [(match_operand:SI 1 "s_register_operand" "r")
7892	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
7893	 (match_operator:SI 7 "shift_operator"
7894	  [(match_operand:SI 3 "s_register_operand" "r")
7895	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7896  "TARGET_ARM"
7897  "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7898  [(set_attr "conds" "use")
7899   (set_attr "shift" "1")
7900   (set_attr "length" "8")]
7901)
7902
7903(define_insn "*ifcompare_not_arith"
7904  [(set (match_operand:SI 0 "s_register_operand" "=r")
7905	(if_then_else:SI
7906	 (match_operator 6 "arm_comparison_operator"
7907	  [(match_operand:SI 4 "s_register_operand" "r")
7908	   (match_operand:SI 5 "arm_add_operand" "rIL")])
7909	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7910	 (match_operator:SI 7 "shiftable_operator"
7911	  [(match_operand:SI 2 "s_register_operand" "r")
7912	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7913   (clobber (reg:CC CC_REGNUM))]
7914  "TARGET_ARM"
7915  "#"
7916  [(set_attr "conds" "clob")
7917   (set_attr "length" "12")]
7918)
7919
7920(define_insn "*if_not_arith"
7921  [(set (match_operand:SI 0 "s_register_operand" "=r")
7922	(if_then_else:SI
7923	 (match_operator 5 "arm_comparison_operator"
7924	  [(match_operand 4 "cc_register" "") (const_int 0)])
7925	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7926	 (match_operator:SI 6 "shiftable_operator"
7927	  [(match_operand:SI 2 "s_register_operand" "r")
7928	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7929  "TARGET_ARM"
7930  "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7931  [(set_attr "conds" "use")
7932   (set_attr "length" "8")]
7933)
7934
7935(define_insn "*ifcompare_arith_not"
7936  [(set (match_operand:SI 0 "s_register_operand" "=r")
7937	(if_then_else:SI
7938	 (match_operator 6 "arm_comparison_operator"
7939	  [(match_operand:SI 4 "s_register_operand" "r")
7940	   (match_operand:SI 5 "arm_add_operand" "rIL")])
7941	 (match_operator:SI 7 "shiftable_operator"
7942	  [(match_operand:SI 2 "s_register_operand" "r")
7943	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
7944	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7945   (clobber (reg:CC CC_REGNUM))]
7946  "TARGET_ARM"
7947  "#"
7948  [(set_attr "conds" "clob")
7949   (set_attr "length" "12")]
7950)
7951
7952(define_insn "*if_arith_not"
7953  [(set (match_operand:SI 0 "s_register_operand" "=r")
7954	(if_then_else:SI
7955	 (match_operator 5 "arm_comparison_operator"
7956	  [(match_operand 4 "cc_register" "") (const_int 0)])
7957	 (match_operator:SI 6 "shiftable_operator"
7958	  [(match_operand:SI 2 "s_register_operand" "r")
7959	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
7960	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7961  "TARGET_ARM"
7962  "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7963  [(set_attr "conds" "use")
7964   (set_attr "length" "8")]
7965)
7966
7967(define_insn "*ifcompare_neg_move"
7968  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7969	(if_then_else:SI
7970	 (match_operator 5 "arm_comparison_operator"
7971	  [(match_operand:SI 3 "s_register_operand" "r,r")
7972	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7973	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7974	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7975   (clobber (reg:CC CC_REGNUM))]
7976  "TARGET_ARM"
7977  "#"
7978  [(set_attr "conds" "clob")
7979   (set_attr "length" "8,12")]
7980)
7981
7982(define_insn "*if_neg_move"
7983  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7984	(if_then_else:SI
7985	 (match_operator 4 "arm_comparison_operator"
7986	  [(match_operand 3 "cc_register" "") (const_int 0)])
7987	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7988	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7989  "TARGET_ARM"
7990  "@
7991   rsb%d4\\t%0, %2, #0
7992   mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7993   mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7994  [(set_attr "conds" "use")
7995   (set_attr "length" "4,8,8")]
7996)
7997
7998(define_insn "*ifcompare_move_neg"
7999  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8000	(if_then_else:SI
8001	 (match_operator 5 "arm_comparison_operator"
8002	  [(match_operand:SI 3 "s_register_operand" "r,r")
8003	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8004	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8005	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8006   (clobber (reg:CC CC_REGNUM))]
8007  "TARGET_ARM"
8008  "#"
8009  [(set_attr "conds" "clob")
8010   (set_attr "length" "8,12")]
8011)
8012
8013(define_insn "*if_move_neg"
8014  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8015	(if_then_else:SI
8016	 (match_operator 4 "arm_comparison_operator"
8017	  [(match_operand 3 "cc_register" "") (const_int 0)])
8018	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8019	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8020  "TARGET_ARM"
8021  "@
8022   rsb%D4\\t%0, %2, #0
8023   mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8024   mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8025  [(set_attr "conds" "use")
8026   (set_attr "length" "4,8,8")]
8027)
8028
8029(define_insn "*arith_adjacentmem"
8030  [(set (match_operand:SI 0 "s_register_operand" "=r")
8031	(match_operator:SI 1 "shiftable_operator"
8032	 [(match_operand:SI 2 "memory_operand" "m")
8033	  (match_operand:SI 3 "memory_operand" "m")]))
8034   (clobber (match_scratch:SI 4 "=r"))]
8035  "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8036  "*
8037  {
8038    rtx ldm[3];
8039    rtx arith[4];
8040    int val1 = 0, val2 = 0;
8041
8042    if (REGNO (operands[0]) > REGNO (operands[4]))
8043      {
8044	ldm[1] = operands[4];
8045	ldm[2] = operands[0];
8046      }
8047    else
8048      {
8049	ldm[1] = operands[0];
8050	ldm[2] = operands[4];
8051      }
8052    if (GET_CODE (XEXP (operands[2], 0)) != REG)
8053      val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8054    if (GET_CODE (XEXP (operands[3], 0)) != REG)
8055      val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8056    arith[0] = operands[0];
8057    arith[3] = operands[1];
8058    if (val1 < val2)
8059      {
8060	arith[1] = ldm[1];
8061	arith[2] = ldm[2];
8062      }
8063    else
8064      {
8065	arith[1] = ldm[2];
8066	arith[2] = ldm[1];
8067      }
8068   if (val1 && val2)
8069      {
8070	rtx ops[3];
8071	ldm[0] = ops[0] = operands[4];
8072	ops[1] = XEXP (XEXP (operands[2], 0), 0);
8073	ops[2] = XEXP (XEXP (operands[2], 0), 1);
8074	output_add_immediate (ops);
8075	if (val1 < val2)
8076	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8077	else
8078	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8079      }
8080    else if (val1)
8081      {
8082	ldm[0] = XEXP (operands[3], 0);
8083	if (val1 < val2)
8084	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8085	else
8086	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8087      }
8088    else
8089      {
8090	ldm[0] = XEXP (operands[2], 0);
8091	if (val1 < val2)
8092	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8093	else
8094	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8095      }
8096    output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8097    return \"\";
8098  }"
8099  [(set_attr "length" "12")
8100   (set_attr "predicable" "yes")
8101   (set_attr "type" "load")]
8102)
8103
8104;; the arm can support extended pre-inc instructions
8105
8106;; In all these cases, we use operands 0 and 1 for the register being
8107;; incremented because those are the operands that local-alloc will
8108;; tie and these are the pair most likely to be tieable (and the ones
8109;; that will benefit the most).
8110
8111;; We reject the frame pointer if it occurs anywhere in these patterns since
8112;; elimination will cause too many headaches.
8113
8114(define_insn "*strqi_preinc"
8115  [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8116			 (match_operand:SI 2 "index_operand" "rJ")))
8117	(match_operand:QI 3 "s_register_operand" "r"))
8118   (set (match_operand:SI 0 "s_register_operand" "=r")
8119	(plus:SI (match_dup 1) (match_dup 2)))]
8120  "TARGET_ARM
8121   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8122   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8123   && (GET_CODE (operands[2]) != REG
8124       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8125  "str%?b\\t%3, [%0, %2]!"
8126  [(set_attr "type" "store1")
8127   (set_attr "predicable" "yes")]
8128)
8129
8130(define_insn "*strqi_predec"
8131  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8132			  (match_operand:SI 2 "s_register_operand" "r")))
8133	(match_operand:QI 3 "s_register_operand" "r"))
8134   (set (match_operand:SI 0 "s_register_operand" "=r")
8135	(minus:SI (match_dup 1) (match_dup 2)))]
8136  "TARGET_ARM
8137   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8138   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8139   && (GET_CODE (operands[2]) != REG
8140       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8141  "str%?b\\t%3, [%0, -%2]!"
8142  [(set_attr "type" "store1")
8143   (set_attr "predicable" "yes")]
8144)
8145
8146(define_insn "*loadqi_preinc"
8147  [(set (match_operand:QI 3 "s_register_operand" "=r")
8148	(mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8149			 (match_operand:SI 2 "index_operand" "rJ"))))
8150   (set (match_operand:SI 0 "s_register_operand" "=r")
8151	(plus:SI (match_dup 1) (match_dup 2)))]
8152  "TARGET_ARM
8153   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8154   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8155   && (GET_CODE (operands[2]) != REG
8156       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8157  "ldr%?b\\t%3, [%0, %2]!"
8158  [(set_attr "type" "load")
8159   (set_attr "predicable" "yes")]
8160)
8161
8162(define_insn "*loadqi_predec"
8163  [(set (match_operand:QI 3 "s_register_operand" "=r")
8164	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8165			  (match_operand:SI 2 "s_register_operand" "r"))))
8166   (set (match_operand:SI 0 "s_register_operand" "=r")
8167	(minus:SI (match_dup 1) (match_dup 2)))]
8168  "TARGET_ARM
8169   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8170   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8171   && (GET_CODE (operands[2]) != REG
8172       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8173  "ldr%?b\\t%3, [%0, -%2]!"
8174  [(set_attr "type" "load")
8175   (set_attr "predicable" "yes")]
8176)
8177
8178(define_insn "*loadqisi_preinc"
8179  [(set (match_operand:SI 3 "s_register_operand" "=r")
8180	(zero_extend:SI
8181	 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8182			  (match_operand:SI 2 "index_operand" "rJ")))))
8183   (set (match_operand:SI 0 "s_register_operand" "=r")
8184	(plus:SI (match_dup 1) (match_dup 2)))]
8185  "TARGET_ARM
8186   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8187   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8188   && (GET_CODE (operands[2]) != REG
8189       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8190  "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8191  [(set_attr "type" "load")
8192   (set_attr "predicable" "yes")]
8193)
8194
8195(define_insn "*loadqisi_predec"
8196  [(set (match_operand:SI 3 "s_register_operand" "=r")
8197	(zero_extend:SI
8198	 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8199			   (match_operand:SI 2 "s_register_operand" "r")))))
8200   (set (match_operand:SI 0 "s_register_operand" "=r")
8201	(minus:SI (match_dup 1) (match_dup 2)))]
8202  "TARGET_ARM
8203   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8204   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8205   && (GET_CODE (operands[2]) != REG
8206       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8207  "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8208  [(set_attr "type" "load")
8209   (set_attr "predicable" "yes")]
8210)
8211
8212(define_insn "*strsi_preinc"
8213  [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8214			 (match_operand:SI 2 "index_operand" "rJ")))
8215	(match_operand:SI 3 "s_register_operand" "r"))
8216   (set (match_operand:SI 0 "s_register_operand" "=r")
8217	(plus:SI (match_dup 1) (match_dup 2)))]
8218  "TARGET_ARM
8219   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8220   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8221   && (GET_CODE (operands[2]) != REG
8222       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8223  "str%?\\t%3, [%0, %2]!"
8224  [(set_attr "type" "store1")
8225   (set_attr "predicable" "yes")]
8226)
8227
8228(define_insn "*strsi_predec"
8229  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8230			  (match_operand:SI 2 "s_register_operand" "r")))
8231	(match_operand:SI 3 "s_register_operand" "r"))
8232   (set (match_operand:SI 0 "s_register_operand" "=r")
8233	(minus:SI (match_dup 1) (match_dup 2)))]
8234  "TARGET_ARM
8235   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8236   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8237   && (GET_CODE (operands[2]) != REG
8238       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8239  "str%?\\t%3, [%0, -%2]!"
8240  [(set_attr "type" "store1")
8241   (set_attr "predicable" "yes")]
8242)
8243
8244(define_insn "*loadsi_preinc"
8245  [(set (match_operand:SI 3 "s_register_operand" "=r")
8246	(mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8247			 (match_operand:SI 2 "index_operand" "rJ"))))
8248   (set (match_operand:SI 0 "s_register_operand" "=r")
8249	(plus:SI (match_dup 1) (match_dup 2)))]
8250  "TARGET_ARM
8251   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8252   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8253   && (GET_CODE (operands[2]) != REG
8254       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8255  "ldr%?\\t%3, [%0, %2]!"
8256  [(set_attr "type" "load")
8257   (set_attr "predicable" "yes")]
8258)
8259
8260(define_insn "*loadsi_predec"
8261  [(set (match_operand:SI 3 "s_register_operand" "=r")
8262	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8263			  (match_operand:SI 2 "s_register_operand" "r"))))
8264   (set (match_operand:SI 0 "s_register_operand" "=r")
8265	(minus:SI (match_dup 1) (match_dup 2)))]
8266  "TARGET_ARM
8267   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8268   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8269   && (GET_CODE (operands[2]) != REG
8270       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8271  "ldr%?\\t%3, [%0, -%2]!"
8272  [(set_attr "type" "load")
8273   (set_attr "predicable" "yes")]
8274)
8275
8276(define_insn "*loadhi_preinc"
8277  [(set (match_operand:HI 3 "s_register_operand" "=r")
8278	(mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8279			 (match_operand:SI 2 "index_operand" "rJ"))))
8280   (set (match_operand:SI 0 "s_register_operand" "=r")
8281	(plus:SI (match_dup 1) (match_dup 2)))]
8282  "TARGET_ARM
8283   && !BYTES_BIG_ENDIAN
8284   && !TARGET_MMU_TRAPS
8285   && !arm_arch4
8286   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8287   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8288   && (GET_CODE (operands[2]) != REG
8289       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8290  "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8291  [(set_attr "type" "load")
8292   (set_attr "predicable" "yes")]
8293)
8294
8295(define_insn "*loadhi_predec"
8296  [(set (match_operand:HI 3 "s_register_operand" "=r")
8297	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8298			  (match_operand:SI 2 "s_register_operand" "r"))))
8299   (set (match_operand:SI 0 "s_register_operand" "=r")
8300	(minus:SI (match_dup 1) (match_dup 2)))]
8301  "TARGET_ARM
8302   && !BYTES_BIG_ENDIAN
8303   && !TARGET_MMU_TRAPS
8304   && !arm_arch4
8305   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8306   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8307   && (GET_CODE (operands[2]) != REG
8308       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8309  "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8310  [(set_attr "type" "load")
8311   (set_attr "predicable" "yes")]
8312)
8313
8314(define_insn "*strqi_shiftpreinc"
8315  [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8316			  [(match_operand:SI 3 "s_register_operand" "r")
8317			   (match_operand:SI 4 "const_shift_operand" "n")])
8318			 (match_operand:SI 1 "s_register_operand" "0")))
8319	(match_operand:QI 5 "s_register_operand" "r"))
8320   (set (match_operand:SI 0 "s_register_operand" "=r")
8321	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8322		 (match_dup 1)))]
8323  "TARGET_ARM
8324   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8325   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8326   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8327  "str%?b\\t%5, [%0, %3%S2]!"
8328  [(set_attr "type" "store1")
8329   (set_attr "predicable" "yes")]
8330)
8331
8332(define_insn "*strqi_shiftpredec"
8333  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8334			  (match_operator:SI 2 "shift_operator"
8335			   [(match_operand:SI 3 "s_register_operand" "r")
8336			    (match_operand:SI 4 "const_shift_operand" "n")])))
8337	(match_operand:QI 5 "s_register_operand" "r"))
8338   (set (match_operand:SI 0 "s_register_operand" "=r")
8339	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8340						 (match_dup 4)])))]
8341  "TARGET_ARM
8342   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8343   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8344   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8345  "str%?b\\t%5, [%0, -%3%S2]!"
8346  [(set_attr "type" "store1")
8347   (set_attr "predicable" "yes")]
8348)
8349
8350(define_insn "*loadqi_shiftpreinc"
8351  [(set (match_operand:QI 5 "s_register_operand" "=r")
8352	(mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8353			  [(match_operand:SI 3 "s_register_operand" "r")
8354			   (match_operand:SI 4 "const_shift_operand" "n")])
8355			 (match_operand:SI 1 "s_register_operand" "0"))))
8356   (set (match_operand:SI 0 "s_register_operand" "=r")
8357	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8358		 (match_dup 1)))]
8359  "TARGET_ARM
8360   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8361   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8362   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8363  "ldr%?b\\t%5, [%0, %3%S2]!"
8364  [(set_attr "type" "load")
8365   (set_attr "predicable" "yes")]
8366)
8367
8368(define_insn "*loadqi_shiftpredec"
8369  [(set (match_operand:QI 5 "s_register_operand" "=r")
8370	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8371			  (match_operator:SI 2 "shift_operator"
8372			   [(match_operand:SI 3 "s_register_operand" "r")
8373			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8374   (set (match_operand:SI 0 "s_register_operand" "=r")
8375	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8376						 (match_dup 4)])))]
8377  "TARGET_ARM
8378   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8379   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8380   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8381  "ldr%?b\\t%5, [%0, -%3%S2]!"
8382  [(set_attr "type" "load")
8383   (set_attr "predicable" "yes")]
8384)
8385
8386(define_insn "*strsi_shiftpreinc"
8387  [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8388			  [(match_operand:SI 3 "s_register_operand" "r")
8389			   (match_operand:SI 4 "const_shift_operand" "n")])
8390			 (match_operand:SI 1 "s_register_operand" "0")))
8391	(match_operand:SI 5 "s_register_operand" "r"))
8392   (set (match_operand:SI 0 "s_register_operand" "=r")
8393	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8394		 (match_dup 1)))]
8395  "TARGET_ARM
8396   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8397   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8398   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8399  "str%?\\t%5, [%0, %3%S2]!"
8400  [(set_attr "type" "store1")
8401   (set_attr "predicable" "yes")]
8402)
8403
8404(define_insn "*strsi_shiftpredec"
8405  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8406			  (match_operator:SI 2 "shift_operator"
8407			   [(match_operand:SI 3 "s_register_operand" "r")
8408			    (match_operand:SI 4 "const_shift_operand" "n")])))
8409	(match_operand:SI 5 "s_register_operand" "r"))
8410   (set (match_operand:SI 0 "s_register_operand" "=r")
8411	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8412						 (match_dup 4)])))]
8413  "TARGET_ARM
8414   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8415   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8416   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8417  "str%?\\t%5, [%0, -%3%S2]!"
8418  [(set_attr "type" "store1")
8419   (set_attr "predicable" "yes")]
8420)
8421
8422(define_insn "*loadsi_shiftpreinc"
8423  [(set (match_operand:SI 5 "s_register_operand" "=r")
8424	(mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8425			  [(match_operand:SI 3 "s_register_operand" "r")
8426			   (match_operand:SI 4 "const_shift_operand" "n")])
8427			 (match_operand:SI 1 "s_register_operand" "0"))))
8428   (set (match_operand:SI 0 "s_register_operand" "=r")
8429	(plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8430		 (match_dup 1)))]
8431  "TARGET_ARM
8432   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8433   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8434   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8435  "ldr%?\\t%5, [%0, %3%S2]!"
8436  [(set_attr "type" "load")
8437   (set_attr "predicable" "yes")]
8438)
8439
8440(define_insn "*loadsi_shiftpredec"
8441  [(set (match_operand:SI 5 "s_register_operand" "=r")
8442	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8443			  (match_operator:SI 2 "shift_operator"
8444			   [(match_operand:SI 3 "s_register_operand" "r")
8445			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8446   (set (match_operand:SI 0 "s_register_operand" "=r")
8447	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8448						 (match_dup 4)])))]
8449  "TARGET_ARM
8450   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8451   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8452   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8453  "ldr%?\\t%5, [%0, -%3%S2]!"
8454  [(set_attr "type" "load")
8455   (set_attr "predicable" "yes")])
8456
8457(define_insn "*loadhi_shiftpreinc"
8458  [(set (match_operand:HI 5 "s_register_operand" "=r")
8459	(mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8460			  [(match_operand:SI 3 "s_register_operand" "r")
8461			   (match_operand:SI 4 "const_shift_operand" "n")])
8462			 (match_operand:SI 1 "s_register_operand" "0"))))
8463   (set (match_operand:SI 0 "s_register_operand" "=r")
8464	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8465		 (match_dup 1)))]
8466  "TARGET_ARM
8467   && !BYTES_BIG_ENDIAN
8468   && !TARGET_MMU_TRAPS
8469   && !arm_arch4
8470   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8471   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8472   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8473  "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8474  [(set_attr "type" "load")
8475   (set_attr "predicable" "yes")]
8476)
8477
8478(define_insn "*loadhi_shiftpredec"
8479  [(set (match_operand:HI 5 "s_register_operand" "=r")
8480	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8481			  (match_operator:SI 2 "shift_operator"
8482			   [(match_operand:SI 3 "s_register_operand" "r")
8483			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8484   (set (match_operand:SI 0 "s_register_operand" "=r")
8485	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8486						 (match_dup 4)])))]
8487  "TARGET_ARM
8488   && !BYTES_BIG_ENDIAN
8489   && !TARGET_MMU_TRAPS
8490   && !arm_arch4
8491   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8492   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8493   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8494  "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8495  [(set_attr "type" "load")
8496   (set_attr "predicable" "yes")]
8497)
8498
8499; It can also support extended post-inc expressions, but combine doesn't
8500; try these....
8501; It doesn't seem worth adding peepholes for anything but the most common
8502; cases since, unlike combine, the increment must immediately follow the load
8503; for this pattern to match.
8504; We must watch to see that the source/destination register isn't also the
8505; same as the base address register, and that if the index is a register,
8506; that it is not the same as the base address register.  In such cases the
8507; instruction that we would generate would have UNPREDICTABLE behaviour so 
8508; we cannot use it.
8509
8510(define_peephole
8511  [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8512	(match_operand:QI 2 "s_register_operand" "r"))
8513   (set (match_dup 0)
8514	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8515  "TARGET_ARM
8516   && (REGNO (operands[2]) != REGNO (operands[0]))
8517   && (GET_CODE (operands[1]) != REG
8518       || (REGNO (operands[1]) != REGNO (operands[0])))"
8519  "str%?b\\t%2, [%0], %1"
8520)
8521
8522(define_peephole
8523  [(set (match_operand:QI 0 "s_register_operand" "=r")
8524	(mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8525   (set (match_dup 1)
8526	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8527  "TARGET_ARM
8528   && REGNO (operands[0]) != REGNO(operands[1])
8529   && (GET_CODE (operands[2]) != REG
8530       || REGNO(operands[0]) != REGNO (operands[2]))"
8531  "ldr%?b\\t%0, [%1], %2"
8532)
8533
8534(define_peephole
8535  [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8536	(match_operand:SI 2 "s_register_operand" "r"))
8537   (set (match_dup 0)
8538	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8539  "TARGET_ARM
8540   && (REGNO (operands[2]) != REGNO (operands[0]))
8541   && (GET_CODE (operands[1]) != REG
8542       || (REGNO (operands[1]) != REGNO (operands[0])))"
8543  "str%?\\t%2, [%0], %1"
8544)
8545
8546(define_peephole
8547  [(set (match_operand:HI 0 "s_register_operand" "=r")
8548	(mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8549   (set (match_dup 1)
8550	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8551  "TARGET_ARM
8552   && !BYTES_BIG_ENDIAN
8553   && !TARGET_MMU_TRAPS
8554   && !arm_arch4
8555   && REGNO (operands[0]) != REGNO(operands[1])
8556   && (GET_CODE (operands[2]) != REG
8557       || REGNO(operands[0]) != REGNO (operands[2]))"
8558  "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8559)
8560
8561(define_peephole
8562  [(set (match_operand:SI 0 "s_register_operand" "=r")
8563	(mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8564   (set (match_dup 1)
8565	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8566  "TARGET_ARM
8567   && REGNO (operands[0]) != REGNO(operands[1])
8568   && (GET_CODE (operands[2]) != REG
8569       || REGNO(operands[0]) != REGNO (operands[2]))"
8570  "ldr%?\\t%0, [%1], %2"
8571)
8572
8573(define_peephole
8574  [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8575			 (match_operand:SI 1 "index_operand" "rJ")))
8576	(match_operand:QI 2 "s_register_operand" "r"))
8577   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8578  "TARGET_ARM
8579   && (REGNO (operands[2]) != REGNO (operands[0]))
8580   && (GET_CODE (operands[1]) != REG
8581       || (REGNO (operands[1]) != REGNO (operands[0])))"
8582  "str%?b\\t%2, [%0, %1]!"
8583)
8584
8585(define_peephole
8586  [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8587			  [(match_operand:SI 0 "s_register_operand" "r")
8588			   (match_operand:SI 1 "const_int_operand" "n")])
8589			 (match_operand:SI 2 "s_register_operand" "+r")))
8590	(match_operand:QI 3 "s_register_operand" "r"))
8591   (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8592			       (match_dup 2)))]
8593  "TARGET_ARM
8594   && (REGNO (operands[3]) != REGNO (operands[2]))
8595   && (REGNO (operands[0]) != REGNO (operands[2]))"
8596  "str%?b\\t%3, [%2, %0%S4]!"
8597)
8598
8599; This pattern is never tried by combine, so do it as a peephole
8600
8601(define_peephole2
8602  [(set (match_operand:SI 0 "s_register_operand" "")
8603	(match_operand:SI 1 "s_register_operand" ""))
8604   (set (reg:CC CC_REGNUM)
8605	(compare:CC (match_dup 1) (const_int 0)))]
8606  "TARGET_ARM
8607  "
8608  [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8609	      (set (match_dup 0) (match_dup 1))])]
8610  ""
8611)
8612
8613; Peepholes to spot possible load- and store-multiples, if the ordering is
8614; reversed, check that the memory references aren't volatile.
8615
8616(define_peephole
8617  [(set (match_operand:SI 0 "s_register_operand" "=r")
8618        (match_operand:SI 4 "memory_operand" "m"))
8619   (set (match_operand:SI 1 "s_register_operand" "=r")
8620        (match_operand:SI 5 "memory_operand" "m"))
8621   (set (match_operand:SI 2 "s_register_operand" "=r")
8622        (match_operand:SI 6 "memory_operand" "m"))
8623   (set (match_operand:SI 3 "s_register_operand" "=r")
8624        (match_operand:SI 7 "memory_operand" "m"))]
8625  "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8626  "*
8627  return emit_ldm_seq (operands, 4);
8628  "
8629)
8630
8631(define_peephole
8632  [(set (match_operand:SI 0 "s_register_operand" "=r")
8633        (match_operand:SI 3 "memory_operand" "m"))
8634   (set (match_operand:SI 1 "s_register_operand" "=r")
8635        (match_operand:SI 4 "memory_operand" "m"))
8636   (set (match_operand:SI 2 "s_register_operand" "=r")
8637        (match_operand:SI 5 "memory_operand" "m"))]
8638  "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8639  "*
8640  return emit_ldm_seq (operands, 3);
8641  "
8642)
8643
8644(define_peephole
8645  [(set (match_operand:SI 0 "s_register_operand" "=r")
8646        (match_operand:SI 2 "memory_operand" "m"))
8647   (set (match_operand:SI 1 "s_register_operand" "=r")
8648        (match_operand:SI 3 "memory_operand" "m"))]
8649  "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8650  "*
8651  return emit_ldm_seq (operands, 2);
8652  "
8653)
8654
8655(define_peephole
8656  [(set (match_operand:SI 4 "memory_operand" "=m")
8657        (match_operand:SI 0 "s_register_operand" "r"))
8658   (set (match_operand:SI 5 "memory_operand" "=m")
8659        (match_operand:SI 1 "s_register_operand" "r"))
8660   (set (match_operand:SI 6 "memory_operand" "=m")
8661        (match_operand:SI 2 "s_register_operand" "r"))
8662   (set (match_operand:SI 7 "memory_operand" "=m")
8663        (match_operand:SI 3 "s_register_operand" "r"))]
8664  "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8665  "*
8666  return emit_stm_seq (operands, 4);
8667  "
8668)
8669
8670(define_peephole
8671  [(set (match_operand:SI 3 "memory_operand" "=m")
8672        (match_operand:SI 0 "s_register_operand" "r"))
8673   (set (match_operand:SI 4 "memory_operand" "=m")
8674        (match_operand:SI 1 "s_register_operand" "r"))
8675   (set (match_operand:SI 5 "memory_operand" "=m")
8676        (match_operand:SI 2 "s_register_operand" "r"))]
8677  "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8678  "*
8679  return emit_stm_seq (operands, 3);
8680  "
8681)
8682
8683(define_peephole
8684  [(set (match_operand:SI 2 "memory_operand" "=m")
8685        (match_operand:SI 0 "s_register_operand" "r"))
8686   (set (match_operand:SI 3 "memory_operand" "=m")
8687        (match_operand:SI 1 "s_register_operand" "r"))]
8688  "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8689  "*
8690  return emit_stm_seq (operands, 2);
8691  "
8692)
8693
8694(define_split
8695  [(set (match_operand:SI 0 "s_register_operand" "")
8696	(and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8697		       (const_int 0))
8698		(neg:SI (match_operator:SI 2 "arm_comparison_operator"
8699			 [(match_operand:SI 3 "s_register_operand" "")
8700			  (match_operand:SI 4 "arm_rhs_operand" "")]))))
8701   (clobber (match_operand:SI 5 "s_register_operand" ""))]
8702  "TARGET_ARM"
8703  [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8704   (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8705			      (match_dup 5)))]
8706  ""
8707)
8708
8709;; This split can be used because CC_Z mode implies that the following
8710;; branch will be an equality, or an unsigned inequality, so the sign
8711;; extension is not needed.
8712
8713(define_split
8714  [(set (reg:CC_Z CC_REGNUM)
8715	(compare:CC_Z
8716	 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8717		    (const_int 24))
8718	 (match_operand 1 "const_int_operand" "")))
8719   (clobber (match_scratch:SI 2 ""))]
8720  "TARGET_ARM
8721   && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8722       == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8723  [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8724   (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8725  "
8726  operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8727  "
8728)
8729
8730(define_expand "prologue"
8731  [(clobber (const_int 0))]
8732  "TARGET_EITHER"
8733  "if (TARGET_ARM)
8734     arm_expand_prologue ();
8735   else
8736     thumb_expand_prologue ();
8737  DONE;
8738  "
8739)
8740
8741(define_expand "epilogue"
8742  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8743  "TARGET_EITHER"
8744  "
8745  if (TARGET_THUMB)
8746    thumb_expand_epilogue ();
8747  else if (USE_RETURN_INSN (FALSE))
8748    {
8749      emit_jump_insn (gen_return ());
8750      DONE;
8751    }
8752  emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8753	gen_rtvec (1,
8754		gen_rtx_RETURN (VOIDmode)),
8755	VUNSPEC_EPILOGUE));
8756  DONE;
8757  "
8758)
8759
8760(define_insn "sibcall_epilogue"
8761  [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8762  "TARGET_ARM"
8763  "*
8764  output_asm_insn (\"%@ Sibcall epilogue\", operands);
8765  if (USE_RETURN_INSN (FALSE))
8766    return output_return_instruction (NULL, FALSE, FALSE);
8767  return arm_output_epilogue (FALSE);
8768  "
8769;; Length is absolute worst case
8770  [(set_attr "length" "44")
8771   (set_attr "type" "block")]
8772)
8773
8774(define_insn "*epilogue_insns"
8775  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8776  "TARGET_EITHER"
8777  "*
8778  if (TARGET_ARM)
8779    return arm_output_epilogue (TRUE);
8780  else /* TARGET_THUMB */
8781    return thumb_unexpanded_epilogue ();
8782  "
8783  ; Length is absolute worst case
8784  [(set_attr "length" "44")
8785   (set_attr "type" "block")]
8786)
8787
8788(define_expand "eh_epilogue"
8789  [(use (match_operand:SI 0 "register_operand" "r"))
8790   (use (match_operand:SI 1 "register_operand" "r"))
8791   (use (match_operand:SI 2 "register_operand" "r"))]
8792  "TARGET_EITHER"
8793  "
8794  {
8795    cfun->machine->eh_epilogue_sp_ofs = operands[1];
8796    if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8797      {
8798	rtx ra = gen_rtx_REG (Pmode, 2);
8799
8800	emit_move_insn (ra, operands[2]);
8801	operands[2] = ra;
8802      }
8803    /* This is a hack -- we may have crystalized the function type too
8804       early.  */
8805    cfun->machine->func_type = 0;
8806  }"
8807)
8808
8809;; This split is only used during output to reduce the number of patterns
8810;; that need assembler instructions adding to them.  We allowed the setting
8811;; of the conditions to be implicit during rtl generation so that
8812;; the conditional compare patterns would work.  However this conflicts to
8813;; some extent with the conditional data operations, so we have to split them
8814;; up again here.
8815
8816(define_split
8817  [(set (match_operand:SI 0 "s_register_operand" "")
8818	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8819			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8820			 (match_dup 0)
8821			 (match_operand 4 "" "")))
8822   (clobber (reg:CC CC_REGNUM))]
8823  "TARGET_ARM && reload_completed"
8824  [(set (match_dup 5) (match_dup 6))
8825   (cond_exec (match_dup 7)
8826	      (set (match_dup 0) (match_dup 4)))]
8827  "
8828  {
8829    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8830					     operands[2], operands[3]);
8831    enum rtx_code rc = GET_CODE (operands[1]);
8832
8833    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8834    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8835    if (mode == CCFPmode || mode == CCFPEmode)
8836      rc = reverse_condition_maybe_unordered (rc);
8837    else
8838      rc = reverse_condition (rc);
8839
8840    operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8841  }"
8842)
8843
8844(define_split
8845  [(set (match_operand:SI 0 "s_register_operand" "")
8846	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8847			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8848			 (match_operand 4 "" "")
8849			 (match_dup 0)))
8850   (clobber (reg:CC CC_REGNUM))]
8851  "TARGET_ARM && reload_completed"
8852  [(set (match_dup 5) (match_dup 6))
8853   (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8854	      (set (match_dup 0) (match_dup 4)))]
8855  "
8856  {
8857    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8858					     operands[2], operands[3]);
8859
8860    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8861    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8862  }"
8863)
8864
8865(define_split
8866  [(set (match_operand:SI 0 "s_register_operand" "")
8867	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8868			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8869			 (match_operand 4 "" "")
8870			 (match_operand 5 "" "")))
8871   (clobber (reg:CC CC_REGNUM))]
8872  "TARGET_ARM && reload_completed"
8873  [(set (match_dup 6) (match_dup 7))
8874   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8875	      (set (match_dup 0) (match_dup 4)))
8876   (cond_exec (match_dup 8)
8877	      (set (match_dup 0) (match_dup 5)))]
8878  "
8879  {
8880    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8881					     operands[2], operands[3]);
8882    enum rtx_code rc = GET_CODE (operands[1]);
8883
8884    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8885    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8886    if (mode == CCFPmode || mode == CCFPEmode)
8887      rc = reverse_condition_maybe_unordered (rc);
8888    else
8889      rc = reverse_condition (rc);
8890
8891    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8892  }"
8893)
8894
8895(define_split
8896  [(set (match_operand:SI 0 "s_register_operand" "")
8897	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8898			  [(match_operand:SI 2 "s_register_operand" "")
8899			   (match_operand:SI 3 "arm_add_operand" "")])
8900			 (match_operand:SI 4 "arm_rhs_operand" "")
8901			 (not:SI
8902			  (match_operand:SI 5 "s_register_operand" ""))))
8903   (clobber (reg:CC CC_REGNUM))]
8904  "TARGET_ARM && reload_completed"
8905  [(set (match_dup 6) (match_dup 7))
8906   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8907	      (set (match_dup 0) (match_dup 4)))
8908   (cond_exec (match_dup 8)
8909	      (set (match_dup 0) (not:SI (match_dup 5))))]
8910  "
8911  {
8912    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8913					     operands[2], operands[3]);
8914    enum rtx_code rc = GET_CODE (operands[1]);
8915
8916    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8917    operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8918    if (mode == CCFPmode || mode == CCFPEmode)
8919      rc = reverse_condition_maybe_unordered (rc);
8920    else
8921      rc = reverse_condition (rc);
8922
8923    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8924  }"
8925)
8926
8927(define_insn "*cond_move_not"
8928  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8929	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
8930			  [(match_operand 3 "cc_register" "") (const_int 0)])
8931			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8932			 (not:SI
8933			  (match_operand:SI 2 "s_register_operand" "r,r"))))]
8934  "TARGET_ARM"
8935  "@
8936   mvn%D4\\t%0, %2
8937   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8938  [(set_attr "conds" "use")
8939   (set_attr "length" "4,8")]
8940)
8941
8942;; The next two patterns occur when an AND operation is followed by a
8943;; scc insn sequence 
8944
8945(define_insn "*sign_extract_onebit"
8946  [(set (match_operand:SI 0 "s_register_operand" "=r")
8947	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8948			 (const_int 1)
8949			 (match_operand:SI 2 "const_int_operand" "n")))]
8950  "TARGET_ARM"
8951  "*
8952    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8953    output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8954    return \"mvnne\\t%0, #0\";
8955  "
8956  [(set_attr "conds" "clob")
8957   (set_attr "length" "8")]
8958)
8959
8960(define_insn "*not_signextract_onebit"
8961  [(set (match_operand:SI 0 "s_register_operand" "=r")
8962	(not:SI
8963	 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8964			  (const_int 1)
8965			  (match_operand:SI 2 "const_int_operand" "n"))))]
8966  "TARGET_ARM"
8967  "*
8968    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8969    output_asm_insn (\"tst\\t%1, %2\", operands);
8970    output_asm_insn (\"mvneq\\t%0, #0\", operands);
8971    return \"movne\\t%0, #0\";
8972  "
8973  [(set_attr "conds" "clob")
8974   (set_attr "length" "12")]
8975)
8976
8977;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8978;; expressions.  For simplicity, the first register is also in the unspec
8979;; part.
8980(define_insn "*push_multi"
8981  [(match_parallel 2 "multi_register_push"
8982    [(set (match_operand:BLK 0 "memory_operand" "=m")
8983	  (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8984		      UNSPEC_PUSH_MULT))])]
8985  "TARGET_ARM"
8986  "*
8987  {
8988    int num_saves = XVECLEN (operands[2], 0);
8989     
8990    /* For the StrongARM at least it is faster to
8991       use STR to store only a single register.  */
8992    if (num_saves == 1)
8993      output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8994    else
8995      {
8996	int i;
8997	char pattern[100];
8998
8999	strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9000
9001	for (i = 1; i < num_saves; i++)
9002	  {
9003	    strcat (pattern, \", %|\");
9004	    strcat (pattern,
9005		    reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9006	  }
9007
9008	strcat (pattern, \"}\");
9009	output_asm_insn (pattern, operands);
9010      }
9011
9012    return \"\";
9013  }"
9014  [(set_attr "type" "store4")]
9015)
9016
9017;; Similarly for the floating point registers
9018(define_insn "*push_fp_multi"
9019  [(match_parallel 2 "multi_register_push"
9020    [(set (match_operand:BLK 0 "memory_operand" "=m")
9021	  (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9022		      UNSPEC_PUSH_MULT))])]
9023  "TARGET_ARM"
9024  "*
9025  {
9026    char pattern[100];
9027
9028    sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9029    output_asm_insn (pattern, operands);
9030    return \"\";
9031  }"
9032  [(set_attr "type" "f_store")]
9033)
9034
9035;; Special patterns for dealing with the constant pool
9036
9037(define_insn "align_4"
9038  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9039  "TARGET_EITHER"
9040  "*
9041  assemble_align (32);
9042  return \"\";
9043  "
9044)
9045
9046(define_insn "consttable_end"
9047  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9048  "TARGET_EITHER"
9049  "*
9050  making_const_table = FALSE;
9051  return \"\";
9052  "
9053)
9054
9055(define_insn "consttable_1"
9056  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9057  "TARGET_THUMB"
9058  "*
9059  making_const_table = TRUE;
9060  assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9061  assemble_zeros (3);
9062  return \"\";
9063  "
9064  [(set_attr "length" "4")]
9065)
9066
9067(define_insn "consttable_2"
9068  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9069  "TARGET_THUMB"
9070  "*
9071  making_const_table = TRUE;
9072  assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9073  assemble_zeros (2);
9074  return \"\";
9075  "
9076  [(set_attr "length" "4")]
9077)
9078
9079(define_insn "consttable_4"
9080  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9081  "TARGET_EITHER"
9082  "*
9083  {
9084    making_const_table = TRUE;
9085    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9086      {
9087      case MODE_FLOAT:
9088      {
9089        union real_extract u;
9090        memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9091        assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9092        break;
9093      }
9094      default:
9095        assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9096        break;
9097      }
9098    return \"\";
9099  }"
9100  [(set_attr "length" "4")]
9101)
9102
9103(define_insn "consttable_8"
9104  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9105  "TARGET_EITHER"
9106  "*
9107  {
9108    making_const_table = TRUE;
9109    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9110      {
9111       case MODE_FLOAT:
9112        {
9113          union real_extract u;
9114          memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9115          assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9116          break;
9117        }
9118      default:
9119        assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9120        break;
9121      }
9122    return \"\";
9123  }"
9124  [(set_attr "length" "8")]
9125)
9126
9127;; Miscellaneous Thumb patterns
9128
9129(define_expand "tablejump"
9130  [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9131	      (use (label_ref (match_operand 1 "" "")))])]
9132  "TARGET_THUMB"
9133  "
9134  if (flag_pic)
9135    {
9136      /* Hopefully, CSE will eliminate this copy.  */
9137      rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9138      rtx reg2 = gen_reg_rtx (SImode);
9139
9140      emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9141      operands[0] = reg2;
9142    }
9143  "
9144)
9145
9146(define_insn "*thumb_tablejump"
9147  [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9148   (use (label_ref (match_operand 1 "" "")))]
9149  "TARGET_THUMB"
9150  "mov\\t%|pc, %0"
9151  [(set_attr "length" "2")]
9152)
9153
9154;; V5 Instructions,
9155
9156(define_insn "clz"
9157  [(set (match_operand:SI             0 "s_register_operand" "=r")
9158	(unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9159		   UNSPEC_CLZ))]
9160  "TARGET_ARM && arm_arch5"
9161  "clz\\t%0, %1")
9162
9163(define_expand "ffssi2"
9164  [(set (match_operand:SI 0 "s_register_operand" "")
9165	(ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9166  "TARGET_ARM && arm_arch5"
9167  "
9168  {
9169    rtx t1, t2, t3;
9170
9171    t1 = gen_reg_rtx (SImode);
9172    t2 = gen_reg_rtx (SImode);
9173    t3 = gen_reg_rtx (SImode);
9174
9175    emit_insn (gen_negsi2 (t1, operands[1]));
9176    emit_insn (gen_andsi3 (t2, operands[1], t1));
9177    emit_insn (gen_clz (t3, t2));
9178    emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9179    DONE;
9180  }"
9181)
9182
9183;; V5E instructions.
9184
9185(define_insn "prefetch"
9186  [(prefetch (match_operand:SI 0 "address_operand" "p")
9187	     (match_operand:SI 1 "" "")
9188	     (match_operand:SI 2 "" ""))]
9189  "TARGET_ARM && arm_arch5e"
9190  "pld\\t%a0")
9191
9192;; General predication pattern
9193
9194(define_cond_exec
9195  [(match_operator 0 "arm_comparison_operator"
9196    [(match_operand 1 "cc_register" "")
9197     (const_int 0)])]
9198  "TARGET_ARM"
9199  ""
9200)
9201
9202(define_insn "prologue_use"
9203  [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9204  ""
9205  "%@ %0 needed for prologue"
9206)
9207