arm.md revision 104752
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   (clobber (reg:CC CC_REGNUM))]
1842  "TARGET_ARM
1843   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1844       && INTVAL (operands[2]) > 0 
1845       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1846       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1847  "*
1848  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1849			 << INTVAL (operands[3]));
1850  output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1851  return \"movne\\t%0, #1\";
1852  "
1853  [(set_attr "conds" "clob")
1854   (set_attr "length" "8")]
1855)
1856
1857;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1858;;; represented by the bitfield, then this will produce incorrect results.
1859;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1860;;; which have a real bitfield insert instruction, the truncation happens
1861;;; in the bitfield insert instruction itself.  Since arm does not have a
1862;;; bitfield insert instruction, we would have to emit code here to truncate
1863;;; the value before we insert.  This loses some of the advantage of having
1864;;; this insv pattern, so this pattern needs to be reevalutated.
1865
1866(define_expand "insv"
1867  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1868                         (match_operand:SI 1 "general_operand" "")
1869                         (match_operand:SI 2 "general_operand" ""))
1870        (match_operand:SI 3 "nonmemory_operand" ""))]
1871  "TARGET_ARM"
1872  "
1873  {
1874    int start_bit = INTVAL (operands[2]);
1875    int width = INTVAL (operands[1]);
1876    HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1877    rtx target, subtarget;
1878
1879    target = operands[0];
1880    /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1881       subreg as the final target.  */
1882    if (GET_CODE (target) == SUBREG)
1883      {
1884	subtarget = gen_reg_rtx (SImode);
1885	if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1886	    < GET_MODE_SIZE (SImode))
1887	  target = SUBREG_REG (target);
1888      }
1889    else
1890      subtarget = target;    
1891
1892    if (GET_CODE (operands[3]) == CONST_INT)
1893      {
1894	/* Since we are inserting a known constant, we may be able to
1895	   reduce the number of bits that we have to clear so that
1896	   the mask becomes simple.  */
1897	/* ??? This code does not check to see if the new mask is actually
1898	   simpler.  It may not be.  */
1899	rtx op1 = gen_reg_rtx (SImode);
1900	/* ??? Truncate operand3 to fit in the bitfield.  See comment before
1901	   start of this pattern.  */
1902	HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1903	HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1904
1905	emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1906	emit_insn (gen_iorsi3 (subtarget, op1,
1907			       GEN_INT (op3_value << start_bit)));
1908      }
1909    else if (start_bit == 0
1910	     && !(const_ok_for_arm (mask)
1911		  || const_ok_for_arm (~mask)))
1912      {
1913	/* A Trick, since we are setting the bottom bits in the word,
1914	   we can shift operand[3] up, operand[0] down, OR them together
1915	   and rotate the result back again.  This takes 3 insns, and
1916	   the third might be mergable into another op.  */
1917	/* The shift up copes with the possibility that operand[3] is
1918           wider than the bitfield.  */
1919	rtx op0 = gen_reg_rtx (SImode);
1920	rtx op1 = gen_reg_rtx (SImode);
1921
1922	emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1923	emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1924	emit_insn (gen_iorsi3  (op1, op1, op0));
1925	emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1926      }
1927    else if ((width + start_bit == 32)
1928	     && !(const_ok_for_arm (mask)
1929		  || const_ok_for_arm (~mask)))
1930      {
1931	/* Similar trick, but slightly less efficient.  */
1932
1933	rtx op0 = gen_reg_rtx (SImode);
1934	rtx op1 = gen_reg_rtx (SImode);
1935
1936	emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1937	emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1938	emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1939	emit_insn (gen_iorsi3 (subtarget, op1, op0));
1940      }
1941    else
1942      {
1943	rtx op0 = GEN_INT (mask);
1944	rtx op1 = gen_reg_rtx (SImode);
1945	rtx op2 = gen_reg_rtx (SImode);
1946
1947	if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1948	  {
1949	    rtx tmp = gen_reg_rtx (SImode);
1950
1951	    emit_insn (gen_movsi (tmp, op0));
1952	    op0 = tmp;
1953	  }
1954
1955	/* Mask out any bits in operand[3] that are not needed.  */
1956	   emit_insn (gen_andsi3 (op1, operands[3], op0));
1957
1958	if (GET_CODE (op0) == CONST_INT
1959	    && (const_ok_for_arm (mask << start_bit)
1960		|| const_ok_for_arm (~(mask << start_bit))))
1961	  {
1962	    op0 = GEN_INT (~(mask << start_bit));
1963	    emit_insn (gen_andsi3 (op2, operands[0], op0));
1964	  }
1965	else
1966	  {
1967	    if (GET_CODE (op0) == CONST_INT)
1968	      {
1969		rtx tmp = gen_reg_rtx (SImode);
1970
1971		emit_insn (gen_movsi (tmp, op0));
1972		op0 = tmp;
1973	      }
1974
1975	    if (start_bit != 0)
1976	      emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1977	    
1978	    emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1979	  }
1980
1981	if (start_bit != 0)
1982          emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1983
1984	emit_insn (gen_iorsi3 (subtarget, op1, op2));
1985      }
1986
1987    if (subtarget != target)
1988      {
1989	/* If TARGET is still a SUBREG, then it must be wider than a word,
1990	   so we must be careful only to set the subword we were asked to.  */
1991	if (GET_CODE (target) == SUBREG)
1992	  emit_move_insn (target, subtarget);
1993	else
1994	  emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1995      }
1996
1997    DONE;
1998  }"
1999)
2000
2001; constants for op 2 will never be given to these patterns.
2002(define_insn_and_split "*anddi_notdi_di"
2003  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2004	(and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2005		(match_operand:DI 2 "s_register_operand" "0,r")))]
2006  "TARGET_ARM"
2007  "#"
2008  "TARGET_ARM && reload_completed"
2009  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2010   (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2011  "
2012  {
2013    operands[3] = gen_highpart (SImode, operands[0]);
2014    operands[0] = gen_lowpart (SImode, operands[0]);
2015    operands[4] = gen_highpart (SImode, operands[1]);
2016    operands[1] = gen_lowpart (SImode, operands[1]);
2017    operands[5] = gen_highpart (SImode, operands[2]);
2018    operands[2] = gen_lowpart (SImode, operands[2]);
2019  }"
2020  [(set_attr "length" "8")
2021   (set_attr "predicable" "yes")]
2022)
2023  
2024(define_insn_and_split "*anddi_notzesidi_di"
2025  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2026	(and:DI (not:DI (zero_extend:DI
2027			 (match_operand:SI 2 "s_register_operand" "r,r")))
2028		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2029  "TARGET_ARM"
2030  "@
2031   bic%?\\t%Q0, %Q1, %2
2032   #"
2033  ; (not (zero_extend ...)) allows us to just copy the high word from
2034  ; operand1 to operand0.
2035  "TARGET_ARM
2036   && reload_completed
2037   && operands[0] != operands[1]"
2038  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2039   (set (match_dup 3) (match_dup 4))]
2040  "
2041  {
2042    operands[3] = gen_highpart (SImode, operands[0]);
2043    operands[0] = gen_lowpart (SImode, operands[0]);
2044    operands[4] = gen_highpart (SImode, operands[1]);
2045    operands[1] = gen_lowpart (SImode, operands[1]);
2046  }"
2047  [(set_attr "length" "4,8")
2048   (set_attr "predicable" "yes")]
2049)
2050  
2051(define_insn_and_split "*anddi_notsesidi_di"
2052  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2053	(and:DI (not:DI (sign_extend:DI
2054			 (match_operand:SI 2 "s_register_operand" "r,r")))
2055		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2056  "TARGET_ARM"
2057  "#"
2058  "TARGET_ARM && reload_completed"
2059  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2060   (set (match_dup 3) (and:SI (not:SI
2061				(ashiftrt:SI (match_dup 2) (const_int 31)))
2062			       (match_dup 4)))]
2063  "
2064  {
2065    operands[3] = gen_highpart (SImode, operands[0]);
2066    operands[0] = gen_lowpart (SImode, operands[0]);
2067    operands[4] = gen_highpart (SImode, operands[1]);
2068    operands[1] = gen_lowpart (SImode, operands[1]);
2069  }"
2070  [(set_attr "length" "8")
2071   (set_attr "predicable" "yes")]
2072)
2073  
2074(define_insn "andsi_notsi_si"
2075  [(set (match_operand:SI 0 "s_register_operand" "=r")
2076	(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2077		(match_operand:SI 1 "s_register_operand" "r")))]
2078  "TARGET_ARM"
2079  "bic%?\\t%0, %1, %2"
2080  [(set_attr "predicable" "yes")]
2081)
2082
2083(define_insn "bicsi3"
2084  [(set (match_operand:SI                 0 "register_operand" "=l")
2085	(and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2086		(match_operand:SI         2 "register_operand" "0")))]
2087  "TARGET_THUMB"
2088  "bic\\t%0, %0, %1"
2089  [(set_attr "length" "2")]
2090)
2091
2092(define_insn "andsi_not_shiftsi_si"
2093  [(set (match_operand:SI                   0 "s_register_operand" "=r")
2094	(and:SI (not:SI (match_operator:SI  4 "shift_operator"
2095			 [(match_operand:SI 2 "s_register_operand"  "r")
2096			  (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2097		(match_operand:SI           1 "s_register_operand"  "r")))]
2098  "TARGET_ARM"
2099  "bic%?\\t%0, %1, %2%S4"
2100  [(set_attr "predicable" "yes")
2101   (set_attr "shift" "2")
2102   ]
2103)
2104
2105(define_insn "*andsi_notsi_si_compare0"
2106  [(set (reg:CC_NOOV CC_REGNUM)
2107	(compare:CC_NOOV
2108	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2109		 (match_operand:SI 1 "s_register_operand" "r"))
2110	 (const_int 0)))
2111   (set (match_operand:SI 0 "s_register_operand" "=r")
2112	(and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2113  "TARGET_ARM"
2114  "bic%?s\\t%0, %1, %2"
2115  [(set_attr "conds" "set")]
2116)
2117
2118(define_insn "*andsi_notsi_si_compare0_scratch"
2119  [(set (reg:CC_NOOV CC_REGNUM)
2120	(compare:CC_NOOV
2121	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2122		 (match_operand:SI 1 "s_register_operand" "r"))
2123	 (const_int 0)))
2124   (clobber (match_scratch:SI 0 "=r"))]
2125  "TARGET_ARM"
2126  "bic%?s\\t%0, %1, %2"
2127  [(set_attr "conds" "set")]
2128)
2129
2130(define_insn "iordi3"
2131  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2132	(ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2133		(match_operand:DI 2 "s_register_operand"   "r,r")))]
2134  "TARGET_ARM"
2135  "#"
2136  [(set_attr "length" "8")
2137   (set_attr "predicable" "yes")]
2138)
2139
2140(define_insn "*iordi_zesidi_di"
2141  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2142	(ior:DI (zero_extend:DI
2143		 (match_operand:SI 2 "s_register_operand" "r,r"))
2144		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2145  "TARGET_ARM"
2146  "@
2147   orr%?\\t%Q0, %Q1, %2
2148   #"
2149  [(set_attr "length" "4,8")
2150   (set_attr "predicable" "yes")]
2151)
2152
2153(define_insn "*iordi_sesidi_di"
2154  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2155	(ior:DI (sign_extend:DI
2156		 (match_operand:SI 2 "s_register_operand" "r,r"))
2157		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2158  "TARGET_ARM"
2159  "#"
2160  [(set_attr "length" "8")
2161   (set_attr "predicable" "yes")]
2162)
2163
2164(define_expand "iorsi3"
2165  [(set (match_operand:SI         0 "s_register_operand" "")
2166	(ior:SI (match_operand:SI 1 "s_register_operand" "")
2167		(match_operand:SI 2 "reg_or_int_operand" "")))]
2168  "TARGET_EITHER"
2169  "
2170  if (GET_CODE (operands[2]) == CONST_INT)
2171    {
2172      if (TARGET_ARM)
2173        {
2174          arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2175		 	      operands[1],
2176			      (no_new_pseudos
2177			      ? 0 : preserve_subexpressions_p ()));
2178          DONE;
2179	}
2180      else /* TARGET_THUMB */
2181	operands [2] = force_reg (SImode, operands [2]);
2182    }
2183  "
2184)
2185
2186(define_insn_and_split "*arm_iorsi3"
2187  [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2188	(ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2189		(match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2190  "TARGET_ARM"
2191  "@
2192   orr%?\\t%0, %1, %2
2193   #"
2194  "TARGET_ARM
2195   && GET_CODE (operands[2]) == CONST_INT
2196   && !const_ok_for_arm (INTVAL (operands[2]))"
2197  [(clobber (const_int 0))]
2198  "
2199  arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2200		      operands[1], 0);
2201  DONE;
2202  "
2203  [(set_attr "length" "4,16")
2204   (set_attr "predicable" "yes")]
2205)
2206
2207(define_insn "*thumb_iorsi3"
2208  [(set (match_operand:SI         0 "register_operand" "=l")
2209	(ior:SI (match_operand:SI 1 "register_operand" "%0")
2210		(match_operand:SI 2 "register_operand" "l")))]
2211  "TARGET_THUMB"
2212  "orr\\t%0, %0, %2"
2213  [(set_attr "length" "2")]
2214)
2215
2216(define_peephole2
2217  [(match_scratch:SI 3 "r")
2218   (set (match_operand:SI         0 "s_register_operand" "")
2219	(ior:SI (match_operand:SI 1 "s_register_operand" "")
2220		(match_operand:SI 2 "const_int_operand" "")))]
2221  "TARGET_ARM
2222   && !const_ok_for_arm (INTVAL (operands[2]))
2223   && const_ok_for_arm (~INTVAL (operands[2]))"
2224  [(set (match_dup 3) (match_dup 2))
2225   (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2226  ""
2227)
2228
2229(define_insn "*iorsi3_compare0"
2230  [(set (reg:CC_NOOV CC_REGNUM)
2231	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2232				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2233			 (const_int 0)))
2234   (set (match_operand:SI 0 "s_register_operand" "=r")
2235	(ior:SI (match_dup 1) (match_dup 2)))]
2236  "TARGET_ARM"
2237  "orr%?s\\t%0, %1, %2"
2238  [(set_attr "conds" "set")]
2239)
2240
2241(define_insn "*iorsi3_compare0_scratch"
2242  [(set (reg:CC_NOOV CC_REGNUM)
2243	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2244				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2245			 (const_int 0)))
2246   (clobber (match_scratch:SI 0 "=r"))]
2247  "TARGET_ARM"
2248  "orr%?s\\t%0, %1, %2"
2249  [(set_attr "conds" "set")]
2250)
2251
2252(define_insn "xordi3"
2253  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2254	(xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2255		(match_operand:DI 2 "s_register_operand"   "r,r")))]
2256  "TARGET_ARM"
2257  "#"
2258  [(set_attr "length" "8")
2259   (set_attr "predicable" "yes")]
2260)
2261
2262(define_insn "*xordi_zesidi_di"
2263  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2264	(xor:DI (zero_extend:DI
2265		 (match_operand:SI 2 "s_register_operand" "r,r"))
2266		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2267  "TARGET_ARM"
2268  "@
2269   eor%?\\t%Q0, %Q1, %2
2270   #"
2271  [(set_attr "length" "4,8")
2272   (set_attr "predicable" "yes")]
2273)
2274
2275(define_insn "*xordi_sesidi_di"
2276  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2277	(xor:DI (sign_extend:DI
2278		 (match_operand:SI 2 "s_register_operand" "r,r"))
2279		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2280  "TARGET_ARM"
2281  "#"
2282  [(set_attr "length" "8")
2283   (set_attr "predicable" "yes")]
2284)
2285
2286(define_expand "xorsi3"
2287  [(set (match_operand:SI         0 "s_register_operand" "")
2288	(xor:SI (match_operand:SI 1 "s_register_operand" "")
2289		(match_operand:SI 2 "arm_rhs_operand"  "")))]
2290  "TARGET_EITHER"
2291  "if (TARGET_THUMB)
2292     if (GET_CODE (operands[2]) == CONST_INT)
2293       operands[2] = force_reg (SImode, operands[2]);
2294  "
2295)
2296
2297(define_insn "*arm_xorsi3"
2298  [(set (match_operand:SI         0 "s_register_operand" "=r")
2299	(xor:SI (match_operand:SI 1 "s_register_operand" "r")
2300		(match_operand:SI 2 "arm_rhs_operand" "rI")))]
2301  "TARGET_ARM"
2302  "eor%?\\t%0, %1, %2"
2303  [(set_attr "predicable" "yes")]
2304)
2305
2306(define_insn "*thumb_xorsi3"
2307  [(set (match_operand:SI         0 "register_operand" "=l")
2308	(xor:SI (match_operand:SI 1 "register_operand" "%0")
2309		(match_operand:SI 2 "register_operand" "l")))]
2310  "TARGET_THUMB"
2311  "eor\\t%0, %0, %2"
2312  [(set_attr "length" "2")]
2313)
2314
2315(define_insn "*xorsi3_compare0"
2316  [(set (reg:CC_NOOV CC_REGNUM)
2317	(compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2318				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2319			 (const_int 0)))
2320   (set (match_operand:SI 0 "s_register_operand" "=r")
2321	(xor:SI (match_dup 1) (match_dup 2)))]
2322  "TARGET_ARM"
2323  "eor%?s\\t%0, %1, %2"
2324  [(set_attr "conds" "set")]
2325)
2326
2327(define_insn "*xorsi3_compare0_scratch"
2328  [(set (reg:CC_NOOV CC_REGNUM)
2329	(compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2330				 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2331			 (const_int 0)))]
2332  "TARGET_ARM"
2333  "teq%?\\t%0, %1"
2334  [(set_attr "conds" "set")]
2335)
2336
2337; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2338; (NOT D) we can sometimes merge the final NOT into one of the following
2339; insns.
2340
2341(define_split
2342  [(set (match_operand:SI 0 "s_register_operand" "=r")
2343	(ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2344			(not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
2345		(match_operand:SI 3 "arm_rhs_operand" "rI")))
2346   (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
2347  "TARGET_ARM"
2348  [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2349			      (not:SI (match_dup 3))))
2350   (set (match_dup 0) (not:SI (match_dup 4)))]
2351  ""
2352)
2353
2354(define_insn "*andsi_iorsi3_notsi"
2355  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2356	(and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2357			(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2358		(not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2359  "TARGET_ARM"
2360  "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2361  [(set_attr "length" "8")
2362   (set_attr "predicable" "yes")]
2363)
2364
2365
2366
2367;; Minimum and maximum insns
2368
2369(define_insn "smaxsi3"
2370  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2371	(smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2372		 (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2373   (clobber (reg:CC CC_REGNUM))]
2374  "TARGET_ARM"
2375  "@
2376   cmp\\t%1, %2\;movlt\\t%0, %2
2377   cmp\\t%1, %2\;movge\\t%0, %1
2378   cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2379  [(set_attr "conds" "clob")
2380   (set_attr "length" "8,8,12")]
2381)
2382
2383(define_insn "sminsi3"
2384  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2385	(smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2386		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2387   (clobber (reg:CC CC_REGNUM))]
2388  "TARGET_ARM"
2389  "@
2390   cmp\\t%1, %2\;movge\\t%0, %2
2391   cmp\\t%1, %2\;movlt\\t%0, %1
2392   cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2393  [(set_attr "conds" "clob")
2394   (set_attr "length" "8,8,12")]
2395)
2396
2397(define_insn "umaxsi3"
2398  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2399	(umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2400		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2401   (clobber (reg:CC CC_REGNUM))]
2402  "TARGET_ARM"
2403  "@
2404   cmp\\t%1, %2\;movcc\\t%0, %2
2405   cmp\\t%1, %2\;movcs\\t%0, %1
2406   cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2407  [(set_attr "conds" "clob")
2408   (set_attr "length" "8,8,12")]
2409)
2410
2411(define_insn "uminsi3"
2412  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2413	(umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2414		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2415   (clobber (reg:CC CC_REGNUM))]
2416  "TARGET_ARM"
2417  "@
2418   cmp\\t%1, %2\;movcs\\t%0, %2
2419   cmp\\t%1, %2\;movcc\\t%0, %1
2420   cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2421  [(set_attr "conds" "clob")
2422   (set_attr "length" "8,8,12")]
2423)
2424
2425(define_insn "*store_minmaxsi"
2426  [(set (match_operand:SI 0 "memory_operand" "=m")
2427	(match_operator:SI 3 "minmax_operator"
2428	 [(match_operand:SI 1 "s_register_operand" "r")
2429	  (match_operand:SI 2 "s_register_operand" "r")]))
2430   (clobber (reg:CC CC_REGNUM))]
2431  "TARGET_ARM"
2432  "*
2433  operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2434			 operands[2]);
2435  output_asm_insn (\"cmp\\t%1, %2\", operands);
2436  output_asm_insn (\"str%d3\\t%1, %0\", operands);
2437  output_asm_insn (\"str%D3\\t%2, %0\", operands);
2438  return \"\";
2439  "
2440  [(set_attr "conds" "clob")
2441   (set_attr "length" "12")
2442   (set_attr "type" "store1")]
2443)
2444
2445; Reject the frame pointer in operand[1], since reloading this after
2446; it has been eliminated can cause carnage.
2447(define_insn "*minmax_arithsi"
2448  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2449	(match_operator:SI 4 "shiftable_operator"
2450	 [(match_operator:SI 5 "minmax_operator"
2451	   [(match_operand:SI 2 "s_register_operand" "r,r")
2452	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2453	  (match_operand:SI 1 "s_register_operand" "0,?r")]))
2454   (clobber (reg:CC CC_REGNUM))]
2455  "TARGET_ARM
2456   && (GET_CODE (operands[1]) != REG
2457       || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2458           && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2459  "*
2460  {
2461    enum rtx_code code = GET_CODE (operands[4]);
2462
2463    operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2464			   operands[3]);
2465    output_asm_insn (\"cmp\\t%2, %3\", operands);
2466    output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2467    if (which_alternative != 0 || operands[3] != const0_rtx
2468        || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2469      output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2470    return \"\";
2471  }"
2472  [(set_attr "conds" "clob")
2473   (set_attr "length" "12")]
2474)
2475
2476
2477;; Shift and rotation insns
2478
2479(define_expand "ashlsi3"
2480  [(set (match_operand:SI            0 "s_register_operand" "")
2481	(ashift:SI (match_operand:SI 1 "s_register_operand" "")
2482		   (match_operand:SI 2 "arm_rhs_operand" "")))]
2483  "TARGET_EITHER"
2484  "
2485  if (GET_CODE (operands[2]) == CONST_INT
2486      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2487    {
2488      emit_insn (gen_movsi (operands[0], const0_rtx));
2489      DONE;
2490    }
2491  "
2492)
2493
2494(define_insn "*thumb_ashlsi3"
2495  [(set (match_operand:SI            0 "register_operand" "=l,l")
2496	(ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2497		   (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2498  "TARGET_THUMB"
2499  "lsl\\t%0, %1, %2"
2500  [(set_attr "length" "2")]
2501)
2502
2503(define_expand "ashrsi3"
2504  [(set (match_operand:SI              0 "s_register_operand" "")
2505	(ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2506		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2507  "TARGET_EITHER"
2508  "
2509  if (GET_CODE (operands[2]) == CONST_INT
2510      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2511    operands[2] = GEN_INT (31);
2512  "
2513)
2514
2515(define_insn "*thumb_ashrsi3"
2516  [(set (match_operand:SI              0 "register_operand" "=l,l")
2517	(ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2518		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2519  "TARGET_THUMB"
2520  "asr\\t%0, %1, %2"
2521  [(set_attr "length" "2")]
2522)
2523
2524(define_expand "lshrsi3"
2525  [(set (match_operand:SI              0 "s_register_operand" "")
2526	(lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2527		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2528  "TARGET_EITHER"
2529  "
2530  if (GET_CODE (operands[2]) == CONST_INT
2531      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2532    {
2533      emit_insn (gen_movsi (operands[0], const0_rtx));
2534      DONE;
2535    }
2536  "
2537)
2538
2539(define_insn "*thumb_lshrsi3"
2540  [(set (match_operand:SI              0 "register_operand" "=l,l")
2541	(lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2542		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2543  "TARGET_THUMB"
2544  "lsr\\t%0, %1, %2"
2545  [(set_attr "length" "2")]
2546)
2547
2548(define_expand "rotlsi3"
2549  [(set (match_operand:SI              0 "s_register_operand" "")
2550	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2551		     (match_operand:SI 2 "reg_or_int_operand" "")))]
2552  "TARGET_ARM"
2553  "
2554  if (GET_CODE (operands[2]) == CONST_INT)
2555    operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2556  else
2557    {
2558      rtx reg = gen_reg_rtx (SImode);
2559      emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2560      operands[2] = reg;
2561    }
2562  "
2563)
2564
2565(define_expand "rotrsi3"
2566  [(set (match_operand:SI              0 "s_register_operand" "")
2567	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2568		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2569  "TARGET_EITHER"
2570  "
2571  if (TARGET_ARM)
2572    {
2573      if (GET_CODE (operands[2]) == CONST_INT
2574          && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2575        operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2576    }
2577  else /* TARGET_THUMB */
2578    {
2579      if (GET_CODE (operands [2]) == CONST_INT)
2580        operands [2] = force_reg (SImode, operands[2]);
2581    }
2582  "
2583)
2584
2585(define_insn "*thumb_rotrsi3"
2586  [(set (match_operand:SI              0 "register_operand" "=l")
2587	(rotatert:SI (match_operand:SI 1 "register_operand" "0")
2588		     (match_operand:SI 2 "register_operand" "l")))]
2589  "TARGET_THUMB"
2590  "ror\\t%0, %0, %2"
2591  [(set_attr "length" "2")]
2592)
2593
2594(define_insn "*arm_shiftsi3"
2595  [(set (match_operand:SI   0 "s_register_operand" "=r")
2596	(match_operator:SI  3 "shift_operator"
2597	 [(match_operand:SI 1 "s_register_operand"  "r")
2598	  (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2599  "TARGET_ARM"
2600  "mov%?\\t%0, %1%S3"
2601  [(set_attr "predicable" "yes")
2602   (set_attr "shift" "1")
2603   ]
2604)
2605
2606(define_insn "*shiftsi3_compare0"
2607  [(set (reg:CC_NOOV CC_REGNUM)
2608	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2609			  [(match_operand:SI 1 "s_register_operand" "r")
2610			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
2611			 (const_int 0)))
2612   (set (match_operand:SI 0 "s_register_operand" "=r")
2613	(match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2614  "TARGET_ARM"
2615  "mov%?s\\t%0, %1%S3"
2616  [(set_attr "conds" "set")
2617   (set_attr "shift" "1")
2618   ]
2619)
2620
2621(define_insn "*shiftsi3_compare0_scratch"
2622  [(set (reg:CC_NOOV CC_REGNUM)
2623	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2624			  [(match_operand:SI 1 "s_register_operand" "r")
2625			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
2626			 (const_int 0)))
2627   (clobber (match_scratch:SI 0 "=r"))]
2628  "TARGET_ARM"
2629  "mov%?s\\t%0, %1%S3"
2630  [(set_attr "conds" "set")
2631   (set_attr "shift" "1")
2632   ]
2633)
2634
2635(define_insn "*notsi_shiftsi"
2636  [(set (match_operand:SI 0 "s_register_operand" "=r")
2637	(not:SI (match_operator:SI 3 "shift_operator"
2638		 [(match_operand:SI 1 "s_register_operand" "r")
2639		  (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2640  "TARGET_ARM"
2641  "mvn%?\\t%0, %1%S3"
2642  [(set_attr "predicable" "yes")
2643   (set_attr "shift" "1")
2644   ]
2645)
2646
2647(define_insn "*notsi_shiftsi_compare0"
2648  [(set (reg:CC_NOOV CC_REGNUM)
2649	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2650			  [(match_operand:SI 1 "s_register_operand" "r")
2651			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2652			 (const_int 0)))
2653   (set (match_operand:SI 0 "s_register_operand" "=r")
2654	(not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2655  "TARGET_ARM"
2656  "mvn%?s\\t%0, %1%S3"
2657  [(set_attr "conds" "set")
2658   (set_attr "shift" "1")
2659   ]
2660)
2661
2662(define_insn "*not_shiftsi_compare0_scratch"
2663  [(set (reg:CC_NOOV CC_REGNUM)
2664	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2665			  [(match_operand:SI 1 "s_register_operand" "r")
2666			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2667			 (const_int 0)))
2668   (clobber (match_scratch:SI 0 "=r"))]
2669  "TARGET_ARM"
2670  "mvn%?s\\t%0, %1%S3"
2671  [(set_attr "conds" "set")
2672   (set_attr "shift" "1")
2673  ]
2674)
2675
2676;; We don't really have extzv, but defining this using shifts helps
2677;; to reduce register pressure later on.
2678
2679(define_expand "extzv"
2680  [(set (match_dup 4)
2681	(ashift:SI (match_operand:SI   1 "register_operand" "")
2682		   (match_operand:SI   2 "const_int_operand" "")))
2683   (set (match_operand:SI              0 "register_operand" "")
2684	(lshiftrt:SI (match_dup 4)
2685		     (match_operand:SI 3 "const_int_operand" "")))]
2686  "TARGET_THUMB"
2687  "
2688  {
2689    HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2690    HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2691    
2692    operands[3] = GEN_INT (rshift);
2693    
2694    if (lshift == 0)
2695      {
2696        emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2697        DONE;
2698      }
2699      
2700    operands[2] = GEN_INT (lshift);
2701    operands[4] = gen_reg_rtx (SImode);
2702  }"
2703)
2704
2705
2706;; Unary arithmetic insns
2707
2708(define_expand "negdi2"
2709 [(parallel
2710   [(set (match_operand:DI          0 "s_register_operand" "")
2711	  (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2712    (clobber (reg:CC CC_REGNUM))])]
2713  "TARGET_EITHER"
2714  "
2715  if (TARGET_THUMB)
2716    {
2717      if (GET_CODE (operands[1]) != REG)
2718        operands[1] = force_reg (SImode, operands[1]);
2719     }
2720  "
2721)
2722
2723;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2724;; The second alternative is to allow the common case of a *full* overlap.
2725(define_insn "*arm_negdi2"
2726  [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2727	(neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2728   (clobber (reg:CC CC_REGNUM))]
2729  "TARGET_ARM"
2730  "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2731  [(set_attr "conds" "clob")
2732   (set_attr "length" "8")]
2733)
2734
2735(define_insn "*thumb_negdi2"
2736  [(set (match_operand:DI         0 "register_operand" "=&l")
2737	(neg:DI (match_operand:DI 1 "register_operand"   "l")))
2738   (clobber (reg:CC CC_REGNUM))]
2739  "TARGET_THUMB"
2740  "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2741  [(set_attr "length" "6")]
2742)
2743
2744(define_expand "negsi2"
2745  [(set (match_operand:SI         0 "s_register_operand" "")
2746	(neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2747  "TARGET_EITHER"
2748  ""
2749)
2750
2751(define_insn "*arm_negsi2"
2752  [(set (match_operand:SI         0 "s_register_operand" "=r")
2753	(neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2754  "TARGET_ARM"
2755  "rsb%?\\t%0, %1, #0"
2756  [(set_attr "predicable" "yes")]
2757)
2758
2759(define_insn "*thumb_negsi2"
2760  [(set (match_operand:SI         0 "register_operand" "=l")
2761	(neg:SI (match_operand:SI 1 "register_operand" "l")))]
2762  "TARGET_THUMB"
2763  "neg\\t%0, %1"
2764  [(set_attr "length" "2")]
2765)
2766
2767(define_insn "negsf2"
2768  [(set (match_operand:SF         0 "s_register_operand" "=f")
2769	(neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2770  "TARGET_ARM && TARGET_HARD_FLOAT"
2771  "mnf%?s\\t%0, %1"
2772  [(set_attr "type" "ffarith")
2773   (set_attr "predicable" "yes")]
2774)
2775
2776(define_insn "negdf2"
2777  [(set (match_operand:DF         0 "s_register_operand" "=f")
2778	(neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2779  "TARGET_ARM && TARGET_HARD_FLOAT"
2780  "mnf%?d\\t%0, %1"
2781  [(set_attr "type" "ffarith")
2782   (set_attr "predicable" "yes")]
2783)
2784
2785(define_insn "*negdf_esfdf"
2786  [(set (match_operand:DF 0 "s_register_operand" "=f")
2787	(neg:DF (float_extend:DF
2788		 (match_operand:SF 1 "s_register_operand" "f"))))]
2789  "TARGET_ARM && TARGET_HARD_FLOAT"
2790  "mnf%?d\\t%0, %1"
2791  [(set_attr "type" "ffarith")
2792   (set_attr "predicable" "yes")]
2793)
2794
2795(define_insn "negxf2"
2796  [(set (match_operand:XF 0 "s_register_operand" "=f")
2797	(neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2798  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2799  "mnf%?e\\t%0, %1"
2800  [(set_attr "type" "ffarith")
2801   (set_attr "predicable" "yes")]
2802)
2803
2804;; abssi2 doesn't really clobber the condition codes if a different register
2805;; is being set.  To keep things simple, assume during rtl manipulations that
2806;; it does, but tell the final scan operator the truth.  Similarly for
2807;; (neg (abs...))
2808
2809(define_insn "abssi2"
2810  [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2811	(abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2812   (clobber (reg:CC CC_REGNUM))]
2813  "TARGET_ARM"
2814  "@
2815   cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2816   eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2817  [(set_attr "conds" "clob,*")
2818   (set_attr "shift" "1")
2819   ;; predicable can't be set based on the variant, so left as no
2820   (set_attr "length" "8")]
2821)
2822
2823(define_insn "*neg_abssi2"
2824  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2825	(neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2826   (clobber (reg:CC CC_REGNUM))]
2827  "TARGET_ARM"
2828  "@
2829   cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2830   eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2831  [(set_attr "conds" "clob,*")
2832   (set_attr "shift" "1")
2833   ;; predicable can't be set based on the variant, so left as no
2834   (set_attr "length" "8")]
2835)
2836
2837(define_insn "abssf2"
2838  [(set (match_operand:SF          0 "s_register_operand" "=f")
2839	 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2840  "TARGET_ARM && TARGET_HARD_FLOAT"
2841  "abs%?s\\t%0, %1"
2842  [(set_attr "type" "ffarith")
2843   (set_attr "predicable" "yes")]
2844)
2845
2846(define_insn "absdf2"
2847  [(set (match_operand:DF         0 "s_register_operand" "=f")
2848	(abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2849  "TARGET_ARM && TARGET_HARD_FLOAT"
2850  "abs%?d\\t%0, %1"
2851  [(set_attr "type" "ffarith")
2852   (set_attr "predicable" "yes")]
2853)
2854
2855(define_insn "*absdf_esfdf"
2856  [(set (match_operand:DF 0 "s_register_operand" "=f")
2857	(abs:DF (float_extend:DF
2858		 (match_operand:SF 1 "s_register_operand" "f"))))]
2859  "TARGET_ARM && TARGET_HARD_FLOAT"
2860  "abs%?d\\t%0, %1"
2861  [(set_attr "type" "ffarith")
2862   (set_attr "predicable" "yes")]
2863)
2864
2865(define_insn "absxf2"
2866  [(set (match_operand:XF 0 "s_register_operand" "=f")
2867	(abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2868  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2869  "abs%?e\\t%0, %1"
2870  [(set_attr "type" "ffarith")
2871   (set_attr "predicable" "yes")]
2872)
2873
2874(define_insn "sqrtsf2"
2875  [(set (match_operand:SF 0 "s_register_operand" "=f")
2876	(sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2877  "TARGET_ARM && TARGET_HARD_FLOAT"
2878  "sqt%?s\\t%0, %1"
2879  [(set_attr "type" "float_em")
2880   (set_attr "predicable" "yes")]
2881)
2882
2883(define_insn "sqrtdf2"
2884  [(set (match_operand:DF 0 "s_register_operand" "=f")
2885	(sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2886  "TARGET_ARM && TARGET_HARD_FLOAT"
2887  "sqt%?d\\t%0, %1"
2888  [(set_attr "type" "float_em")
2889   (set_attr "predicable" "yes")]
2890)
2891
2892(define_insn "*sqrtdf_esfdf"
2893  [(set (match_operand:DF 0 "s_register_operand" "=f")
2894	(sqrt:DF (float_extend:DF
2895		  (match_operand:SF 1 "s_register_operand" "f"))))]
2896  "TARGET_ARM && TARGET_HARD_FLOAT"
2897  "sqt%?d\\t%0, %1"
2898  [(set_attr "type" "float_em")
2899   (set_attr "predicable" "yes")]
2900)
2901
2902(define_insn "sqrtxf2"
2903  [(set (match_operand:XF 0 "s_register_operand" "=f")
2904	(sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2905  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2906  "sqt%?e\\t%0, %1"
2907  [(set_attr "type" "float_em")
2908   (set_attr "predicable" "yes")]
2909)
2910
2911;; SIN COS TAN and family are always emulated, so it's probably better
2912;; to always call a library function.
2913;(define_insn "sinsf2"
2914;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2915;	(unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2916;		    UNSPEC_SIN))]
2917;  "TARGET_ARM && TARGET_HARD_FLOAT"
2918;  "sin%?s\\t%0, %1"
2919;[(set_attr "type" "float_em")])
2920;
2921;(define_insn "sindf2"
2922;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2923;	(unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2924;		    UNSPEC_SIN))]
2925;  "TARGET_ARM && TARGET_HARD_FLOAT"
2926;  "sin%?d\\t%0, %1"
2927;[(set_attr "type" "float_em")])
2928;
2929;(define_insn "*sindf_esfdf"
2930;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2931;	(unspec:DF [(float_extend:DF
2932;		     (match_operand:SF 1 "s_register_operand" "f"))]
2933;		    UNSPEC_SIN))]
2934;  "TARGET_ARM && TARGET_HARD_FLOAT"
2935;  "sin%?d\\t%0, %1"
2936;[(set_attr "type" "float_em")])
2937;
2938;(define_insn "sinxf2"
2939;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2940;	(unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2941;		   UNSPEC_SIN))]
2942;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2943;  "sin%?e\\t%0, %1"
2944;[(set_attr "type" "float_em")])
2945;
2946;(define_insn "cossf2"
2947;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2948;	(unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2949;		   UNSPEC_COS))]
2950;  "TARGET_ARM && TARGET_HARD_FLOAT"
2951;  "cos%?s\\t%0, %1"
2952;[(set_attr "type" "float_em")])
2953;
2954;(define_insn "cosdf2"
2955;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2956;	(unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2957;		   UNSPEC_COS))]
2958;  "TARGET_ARM && TARGET_HARD_FLOAT"
2959;  "cos%?d\\t%0, %1"
2960;[(set_attr "type" "float_em")])
2961;
2962;(define_insn "*cosdf_esfdf"
2963;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2964;	(unspec:DF [(float_extend:DF
2965;		     (match_operand:SF 1 "s_register_operand" "f"))]
2966;		   UNSPEC_COS))]
2967;  "TARGET_ARM && TARGET_HARD_FLOAT"
2968;  "cos%?d\\t%0, %1"
2969;[(set_attr "type" "float_em")])
2970;
2971;(define_insn "cosxf2"
2972;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2973;	(unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2974;		   UNSEPC_COS))]
2975;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2976;  "cos%?e\\t%0, %1"
2977;[(set_attr "type" "float_em")])
2978
2979(define_insn_and_split "one_cmpldi2"
2980  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2981	(not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2982  "TARGET_ARM"
2983  "#"
2984  "TARGET_ARM && reload_completed"
2985  [(set (match_dup 0) (not:SI (match_dup 1)))
2986   (set (match_dup 2) (not:SI (match_dup 3)))]
2987  "
2988  {
2989    operands[2] = gen_highpart (SImode, operands[0]);
2990    operands[0] = gen_lowpart (SImode, operands[0]);
2991    operands[3] = gen_highpart (SImode, operands[1]);
2992    operands[1] = gen_lowpart (SImode, operands[1]);
2993  }"
2994  [(set_attr "length" "8")
2995   (set_attr "predicable" "yes")]
2996)
2997
2998(define_expand "one_cmplsi2"
2999  [(set (match_operand:SI         0 "s_register_operand" "")
3000	(not:SI (match_operand:SI 1 "s_register_operand" "")))]
3001  "TARGET_EITHER"
3002  ""
3003)
3004
3005(define_insn "*arm_one_cmplsi2"
3006  [(set (match_operand:SI         0 "s_register_operand" "=r")
3007	(not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3008  "TARGET_ARM"
3009  "mvn%?\\t%0, %1"
3010  [(set_attr "predicable" "yes")]
3011)
3012
3013(define_insn "*thumb_one_cmplsi2"
3014  [(set (match_operand:SI         0 "register_operand" "=l")
3015	(not:SI (match_operand:SI 1 "register_operand"  "l")))]
3016  "TARGET_THUMB"
3017  "mvn\\t%0, %1"
3018  [(set_attr "length" "2")]
3019)
3020
3021(define_insn "*notsi_compare0"
3022  [(set (reg:CC_NOOV CC_REGNUM)
3023	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3024			 (const_int 0)))
3025   (set (match_operand:SI 0 "s_register_operand" "=r")
3026	(not:SI (match_dup 1)))]
3027  "TARGET_ARM"
3028  "mvn%?s\\t%0, %1"
3029  [(set_attr "conds" "set")]
3030)
3031
3032(define_insn "*notsi_compare0_scratch"
3033  [(set (reg:CC_NOOV CC_REGNUM)
3034	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3035			 (const_int 0)))
3036   (clobber (match_scratch:SI 0 "=r"))]
3037  "TARGET_ARM"
3038  "mvn%?s\\t%0, %1"
3039  [(set_attr "conds" "set")]
3040)
3041
3042;; Fixed <--> Floating conversion insns
3043
3044(define_insn "floatsisf2"
3045  [(set (match_operand:SF           0 "s_register_operand" "=f")
3046	(float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3047  "TARGET_ARM && TARGET_HARD_FLOAT"
3048  "flt%?s\\t%0, %1"
3049  [(set_attr "type" "r_2_f")
3050   (set_attr "predicable" "yes")]
3051)
3052
3053(define_insn "floatsidf2"
3054  [(set (match_operand:DF           0 "s_register_operand" "=f")
3055	(float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3056  "TARGET_ARM && TARGET_HARD_FLOAT"
3057  "flt%?d\\t%0, %1"
3058  [(set_attr "type" "r_2_f")
3059   (set_attr "predicable" "yes")]
3060)
3061
3062(define_insn "floatsixf2"
3063  [(set (match_operand:XF 0 "s_register_operand" "=f")
3064	(float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3065  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3066  "flt%?e\\t%0, %1"
3067  [(set_attr "type" "r_2_f")
3068   (set_attr "predicable" "yes")]
3069)
3070
3071(define_insn "fix_truncsfsi2"
3072  [(set (match_operand:SI         0 "s_register_operand" "=r")
3073	(fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3074  "TARGET_ARM && TARGET_HARD_FLOAT"
3075  "fix%?z\\t%0, %1"
3076  [(set_attr "type" "f_2_r")
3077   (set_attr "predicable" "yes")]
3078)
3079
3080(define_insn "fix_truncdfsi2"
3081  [(set (match_operand:SI         0 "s_register_operand" "=r")
3082	(fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3083  "TARGET_ARM && TARGET_HARD_FLOAT"
3084  "fix%?z\\t%0, %1"
3085  [(set_attr "type" "f_2_r")
3086   (set_attr "predicable" "yes")]
3087)
3088
3089(define_insn "fix_truncxfsi2"
3090  [(set (match_operand:SI 0 "s_register_operand" "=r")
3091	(fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3092  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3093  "fix%?z\\t%0, %1"
3094  [(set_attr "type" "f_2_r")
3095   (set_attr "predicable" "yes")]
3096)
3097
3098;; Truncation insns
3099
3100(define_insn "truncdfsf2"
3101  [(set (match_operand:SF 0 "s_register_operand" "=f")
3102	(float_truncate:SF
3103	 (match_operand:DF 1 "s_register_operand" "f")))]
3104  "TARGET_ARM && TARGET_HARD_FLOAT"
3105  "mvf%?s\\t%0, %1"
3106  [(set_attr "type" "ffarith")
3107   (set_attr "predicable" "yes")]
3108)
3109
3110(define_insn "truncxfsf2"
3111  [(set (match_operand:SF 0 "s_register_operand" "=f")
3112	(float_truncate:SF
3113	 (match_operand:XF 1 "s_register_operand" "f")))]
3114  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3115  "mvf%?s\\t%0, %1"
3116  [(set_attr "type" "ffarith")
3117   (set_attr "predicable" "yes")]
3118)
3119
3120(define_insn "truncxfdf2"
3121  [(set (match_operand:DF 0 "s_register_operand" "=f")
3122	(float_truncate:DF
3123	 (match_operand:XF 1 "s_register_operand" "f")))]
3124  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3125  "mvf%?d\\t%0, %1"
3126  [(set_attr "type" "ffarith")
3127   (set_attr "predicable" "yes")]
3128)
3129
3130;; Zero and sign extension instructions.
3131
3132(define_insn "zero_extendsidi2"
3133  [(set (match_operand:DI 0 "s_register_operand" "=r")
3134        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3135  "TARGET_ARM"
3136  "*
3137    if (REGNO (operands[1])
3138        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3139      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3140    return \"mov%?\\t%R0, #0\";
3141  "
3142  [(set_attr "length" "8")
3143   (set_attr "predicable" "yes")]
3144)
3145
3146(define_insn "zero_extendqidi2"
3147  [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3148	(zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3149  "TARGET_ARM"
3150  "@
3151   and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3152   ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3153  [(set_attr "length" "8")
3154   (set_attr "predicable" "yes")
3155   (set_attr "type" "*,load")
3156   (set_attr "pool_range" "*,4092")
3157   (set_attr "neg_pool_range" "*,4084")]
3158)
3159
3160(define_insn "extendsidi2"
3161  [(set (match_operand:DI 0 "s_register_operand" "=r")
3162        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3163  "TARGET_ARM"
3164  "*
3165    if (REGNO (operands[1])
3166        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3167      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3168    return \"mov%?\\t%R0, %Q0, asr #31\";
3169  "
3170  [(set_attr "length" "8")
3171   (set_attr "shift" "1")
3172   (set_attr "predicable" "yes")]
3173)
3174
3175(define_expand "zero_extendhisi2"
3176  [(set (match_dup 2)
3177	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3178		   (const_int 16)))
3179   (set (match_operand:SI 0 "s_register_operand" "")
3180	(lshiftrt:SI (match_dup 2) (const_int 16)))]
3181  "TARGET_EITHER"
3182  "
3183  {
3184    if (TARGET_ARM)
3185      {
3186        if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3187          {
3188           /* Note: We do not have to worry about TARGET_MMU_TRAPS
3189	      here because the insn below will generate an LDRH instruction
3190	      rather than an LDR instruction, so we cannot get an unaligned
3191	      word access.  */
3192            emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3193			            gen_rtx_ZERO_EXTEND (SImode,
3194							 operands[1])));
3195            DONE;
3196          }
3197        if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3198          {
3199            emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3200            DONE;
3201          }
3202        if (!s_register_operand (operands[1], HImode))
3203          operands[1] = copy_to_mode_reg (HImode, operands[1]);
3204        operands[1] = gen_lowpart (SImode, operands[1]);
3205        operands[2] = gen_reg_rtx (SImode);
3206      }
3207    else /* TARGET_THUMB */
3208      {
3209        if (GET_CODE (operands[1]) == MEM)
3210	  {
3211	    rtx tmp;
3212
3213	    tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3214	    tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3215	    emit_insn (tmp);
3216	  }
3217	else
3218	  {
3219	    rtx ops[3];
3220	    
3221	    if (!s_register_operand (operands[1], HImode))
3222	      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3223	    operands[1] = gen_lowpart (SImode, operands[1]);
3224	    operands[2] = gen_reg_rtx (SImode);
3225	    
3226	    ops[0] = operands[2];
3227	    ops[1] = operands[1];
3228	    ops[2] = GEN_INT (16);
3229	    
3230	    emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3231				    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3232
3233	    ops[0] = operands[0];
3234	    ops[1] = operands[2];
3235	    ops[2] = GEN_INT (16);
3236
3237	    emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3238				    gen_rtx_LSHIFTRT (SImode, ops[1],
3239						      ops[2])));
3240	  }
3241	DONE; 
3242      }
3243  }"
3244)
3245
3246(define_insn "*thumb_zero_extendhisi2"
3247  [(set (match_operand:SI                 0 "register_operand" "=l")
3248	(zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3249  "TARGET_THUMB"
3250  "*
3251  rtx mem = XEXP (operands[1], 0);
3252
3253  if (GET_CODE (mem) == CONST)
3254    mem = XEXP (mem, 0);
3255    
3256  if (GET_CODE (mem) == LABEL_REF)
3257    return \"ldr\\t%0, %1\";
3258    
3259  if (GET_CODE (mem) == PLUS)
3260    {
3261      rtx a = XEXP (mem, 0);
3262      rtx b = XEXP (mem, 1);
3263
3264      /* This can happen due to bugs in reload.  */
3265      if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3266        {
3267          rtx ops[2];
3268          ops[0] = operands[0];
3269          ops[1] = a;
3270      
3271          output_asm_insn (\"mov	%0, %1\", ops);
3272
3273          XEXP (mem, 0) = operands[0];
3274       }
3275
3276      else if (   GET_CODE (a) == LABEL_REF
3277	       && GET_CODE (b) == CONST_INT)
3278        return \"ldr\\t%0, %1\";
3279    }
3280    
3281  return \"ldrh\\t%0, %1\";
3282  "
3283  [(set_attr "length" "4")
3284   (set_attr "type" "load")
3285   (set_attr "pool_range" "60")]
3286)
3287
3288(define_insn "*arm_zero_extendhisi2"
3289  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3290	(zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3291  "TARGET_ARM && arm_arch4"
3292  "ldr%?h\\t%0, %1"
3293  [(set_attr "type" "load")
3294   (set_attr "predicable" "yes")
3295   (set_attr "pool_range" "256")
3296   (set_attr "neg_pool_range" "244")]
3297)
3298
3299(define_split
3300  [(set (match_operand:SI 0 "s_register_operand" "")
3301	(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3302   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3303  "TARGET_ARM && (!arm_arch4)"
3304  [(set (match_dup 2) (match_dup 1))
3305   (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3306  "
3307  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3308    FAIL;
3309  "
3310)
3311
3312(define_split
3313  [(set (match_operand:SI 0 "s_register_operand" "")
3314	(match_operator:SI 3 "shiftable_operator"
3315	 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3316	  (match_operand:SI 4 "s_register_operand" "")]))
3317   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3318  "TARGET_ARM && (!arm_arch4)"
3319  [(set (match_dup 2) (match_dup 1))
3320   (set (match_dup 0)
3321	(match_op_dup 3
3322	 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3323  "
3324  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3325    FAIL;
3326  "
3327)
3328
3329(define_expand "zero_extendqisi2"
3330  [(set (match_operand:SI 0 "s_register_operand" "")
3331	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3332  "TARGET_EITHER"
3333  "
3334  if (GET_CODE (operands[1]) != MEM)
3335    {
3336      if (TARGET_ARM)
3337        {
3338          emit_insn (gen_andsi3 (operands[0],
3339				 gen_lowpart (SImode, operands[1]),
3340			         GEN_INT (255)));
3341        }
3342      else /* TARGET_THUMB */
3343        {
3344          rtx temp = gen_reg_rtx (SImode);
3345	  rtx ops[3];
3346	  
3347          operands[1] = copy_to_mode_reg (QImode, operands[1]);
3348          operands[1] = gen_lowpart (SImode, operands[1]);
3349
3350	  ops[0] = temp;
3351	  ops[1] = operands[1];
3352	  ops[2] = GEN_INT (24);
3353
3354	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3355				  gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3356	  
3357          ops[0] = operands[0];
3358	  ops[1] = temp;
3359	  ops[2] = GEN_INT (24);
3360
3361	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3362				  gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3363	}
3364      DONE;
3365    }
3366  "
3367)
3368
3369(define_insn "*thumb_zero_extendqisi2"
3370  [(set (match_operand:SI                 0 "register_operand" "=l")
3371	(zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3372  "TARGET_THUMB"
3373  "ldrb\\t%0, %1"
3374  [(set_attr "length" "2")
3375   (set_attr "type" "load")
3376   (set_attr "pool_range" "32")]
3377)
3378
3379(define_insn "*arm_zero_extendqisi2"
3380  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3381	(zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3382  "TARGET_ARM"
3383  "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3384  [(set_attr "type" "load")
3385   (set_attr "predicable" "yes")
3386   (set_attr "pool_range" "4096")
3387   (set_attr "neg_pool_range" "4084")]
3388)
3389
3390(define_split
3391  [(set (match_operand:SI 0 "s_register_operand" "")
3392	(zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3393   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3394  "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3395  [(set (match_dup 2) (match_dup 1))
3396   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3397  ""
3398)
3399
3400(define_insn "*compareqi_eq0"
3401  [(set (reg:CC_Z CC_REGNUM)
3402	(compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3403			 (const_int 0)))]
3404  "TARGET_ARM"
3405  "tst\\t%0, #255"
3406  [(set_attr "conds" "set")]
3407)
3408
3409(define_expand "extendhisi2"
3410  [(set (match_dup 2)
3411	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3412		   (const_int 16)))
3413   (set (match_operand:SI 0 "s_register_operand" "")
3414	(ashiftrt:SI (match_dup 2)
3415		     (const_int 16)))]
3416  "TARGET_EITHER"
3417  "
3418  {
3419    if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3420      {
3421       /* Note: We do not have to worry about TARGET_MMU_TRAPS
3422	  here because the insn below will generate an LDRH instruction
3423	  rather than an LDR instruction, so we cannot get an unaligned
3424	  word access.  */
3425        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3426		   gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3427        DONE;
3428      }
3429
3430    if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3431      {
3432        emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3433        DONE;
3434      }
3435    if (!s_register_operand (operands[1], HImode))
3436      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3437    operands[1] = gen_lowpart (SImode, operands[1]);
3438    operands[2] = gen_reg_rtx (SImode);
3439
3440    if (TARGET_THUMB)
3441      {
3442	rtx ops[3];
3443	
3444	ops[0] = operands[2];
3445	ops[1] = operands[1];
3446	ops[2] = GEN_INT (16);
3447	
3448        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3449				gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3450	    
3451	ops[0] = operands[0];
3452	ops[1] = operands[2];
3453	ops[2] = GEN_INT (16);
3454	
3455        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3456				gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3457	
3458	DONE;
3459      }
3460  }"
3461)
3462
3463(define_insn "*thumb_extendhisi2_insn"
3464  [(set (match_operand:SI                 0 "register_operand" "=l")
3465	(sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3466   (clobber (match_scratch:SI             2                   "=&l"))]
3467  "TARGET_THUMB"
3468  "*
3469  {
3470    rtx ops[4];
3471    rtx mem = XEXP (operands[1], 0);
3472
3473    /* This code used to try to use 'V', and fix the address only if it was
3474       offsettable, but this fails for e.g. REG+48 because 48 is outside the
3475       range of QImode offsets, and offsettable_address_p does a QImode
3476       address check.  */
3477       
3478    if (GET_CODE (mem) == CONST)
3479      mem = XEXP (mem, 0);
3480    
3481    if (GET_CODE (mem) == LABEL_REF)
3482      return \"ldr\\t%0, %1\";
3483    
3484    if (GET_CODE (mem) == PLUS)
3485      {
3486        rtx a = XEXP (mem, 0);
3487        rtx b = XEXP (mem, 1);
3488
3489        if (GET_CODE (a) == LABEL_REF
3490	    && GET_CODE (b) == CONST_INT)
3491          return \"ldr\\t%0, %1\";
3492
3493        if (GET_CODE (b) == REG)
3494          return \"ldrsh\\t%0, %1\";
3495	  
3496        ops[1] = a;
3497        ops[2] = b;
3498      }
3499    else
3500      {
3501        ops[1] = mem;
3502        ops[2] = const0_rtx;
3503      }
3504      
3505    if (GET_CODE (ops[1]) != REG)
3506      {
3507        debug_rtx (ops[1]);
3508        abort ();
3509      }
3510
3511    ops[0] = operands[0];
3512    ops[3] = operands[2];
3513    output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3514    return \"\";
3515  }"
3516  [(set_attr "length" "4")
3517   (set_attr "type" "load")
3518   (set_attr "pool_range" "1020")]
3519)
3520
3521(define_expand "extendhisi2_mem"
3522  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3523   (set (match_dup 3)
3524	(zero_extend:SI (match_dup 7)))
3525   (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3526   (set (match_operand:SI 0 "" "")
3527	(ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3528  "TARGET_ARM"
3529  "
3530  {
3531    rtx mem1, mem2;
3532    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3533
3534    mem1 = gen_rtx_MEM (QImode, addr);
3535    MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3536    mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3537    MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3538    operands[0] = gen_lowpart (SImode, operands[0]);
3539    operands[1] = mem1;
3540    operands[2] = gen_reg_rtx (SImode);
3541    operands[3] = gen_reg_rtx (SImode);
3542    operands[6] = gen_reg_rtx (SImode);
3543    operands[7] = mem2;
3544
3545    if (BYTES_BIG_ENDIAN)
3546      {
3547	operands[4] = operands[2];
3548	operands[5] = operands[3];
3549      }
3550    else
3551      {
3552	operands[4] = operands[3];
3553	operands[5] = operands[2];
3554      }
3555  }"
3556)
3557
3558(define_insn "*arm_extendhisi_insn"
3559  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3560	(sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3561  "TARGET_ARM && arm_arch4"
3562  "ldr%?sh\\t%0, %1"
3563  [(set_attr "type" "load")
3564   (set_attr "predicable" "yes")
3565   (set_attr "pool_range" "256")
3566   (set_attr "neg_pool_range" "244")]
3567)
3568
3569(define_split
3570  [(set (match_operand:SI                 0 "s_register_operand" "")
3571	(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3572   (clobber (match_operand:SI             2 "s_register_operand" ""))]
3573  "TARGET_ARM && (!arm_arch4)"
3574  [(set (match_dup 2) (match_dup 1))
3575   (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3576  "
3577  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3578    FAIL;
3579  "
3580)
3581
3582(define_split
3583  [(set (match_operand:SI                   0 "s_register_operand" "")
3584	(match_operator:SI                  3 "shiftable_operator"
3585	 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3586	  (match_operand:SI                 4 "s_register_operand" "")]))
3587   (clobber (match_operand:SI               2 "s_register_operand" ""))]
3588  "TARGET_ARM && (!arm_arch4)"
3589  [(set (match_dup 2) (match_dup 1))
3590   (set (match_dup 0)
3591	(match_op_dup 3
3592	 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3593  "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3594     FAIL;
3595  "
3596)
3597
3598(define_expand "extendqihi2"
3599  [(set (match_dup 2)
3600	(ashift:SI (match_operand:QI 1 "general_operand" "")
3601		   (const_int 24)))
3602   (set (match_operand:HI 0 "s_register_operand" "")
3603	(ashiftrt:SI (match_dup 2)
3604		     (const_int 24)))]
3605  "TARGET_ARM"
3606  "
3607  {
3608    if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3609      {
3610	emit_insn (gen_rtx_SET (VOIDmode,
3611				operands[0],
3612				gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3613	DONE;
3614      }
3615    if (!s_register_operand (operands[1], QImode))
3616      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3617    operands[0] = gen_lowpart (SImode, operands[0]);
3618    operands[1] = gen_lowpart (SImode, operands[1]);
3619    operands[2] = gen_reg_rtx (SImode);
3620  }"
3621)
3622
3623; Rather than restricting all byte accesses to memory addresses that ldrsb
3624; can handle, we fix up the ones that ldrsb can't grok with a split.
3625(define_insn "*extendqihi_insn"
3626  [(set (match_operand:HI                 0 "s_register_operand" "=r")
3627	(sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3628  "TARGET_ARM && arm_arch4"
3629  "*
3630  /* If the address is invalid, this will split the instruction into two. */
3631  if (bad_signed_byte_operand (operands[1], VOIDmode))
3632    return \"#\";
3633  return \"ldr%?sb\\t%0, %1\";
3634  "
3635  [(set_attr "type" "load")
3636   (set_attr "predicable" "yes")
3637   (set_attr "length" "8")
3638   (set_attr "pool_range" "256")
3639   (set_attr "neg_pool_range" "244")]
3640)
3641
3642(define_split
3643  [(set (match_operand:HI 0 "s_register_operand" "")
3644	(sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3645  "TARGET_ARM && arm_arch4 && reload_completed"
3646  [(set (match_dup 3) (match_dup 1))
3647   (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3648  "
3649  {
3650    HOST_WIDE_INT offset;
3651
3652    operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3653    operands[2] = gen_rtx_MEM (QImode, operands[3]);
3654    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3655    operands[1] = XEXP (operands[1], 0);
3656    if (GET_CODE (operands[1]) == PLUS
3657	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3658	&& !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3659	     || const_ok_for_arm (-offset)))
3660      {
3661	HOST_WIDE_INT low = (offset > 0
3662			     ? (offset & 0xff) : -((-offset) & 0xff));
3663	XEXP (operands[2], 0) = plus_constant (operands[3], low);
3664	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3665      }
3666    /* Ensure the sum is in correct canonical form */
3667    else if (GET_CODE (operands[1]) == PLUS
3668	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3669	     && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3670      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3671					   XEXP (operands[1], 1),
3672					   XEXP (operands[1], 0));
3673  }"
3674)
3675
3676(define_expand "extendqisi2"
3677  [(set (match_dup 2)
3678	(ashift:SI (match_operand:QI 1 "general_operand" "")
3679		   (const_int 24)))
3680   (set (match_operand:SI 0 "s_register_operand" "")
3681	(ashiftrt:SI (match_dup 2)
3682		     (const_int 24)))]
3683  "TARGET_EITHER"
3684  "
3685  {
3686    if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3687      {
3688        emit_insn (gen_rtx_SET (VOIDmode,
3689			        operands[0],
3690			        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3691        DONE;
3692      }
3693    if (!s_register_operand (operands[1], QImode))
3694      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3695    operands[1] = gen_lowpart (SImode, operands[1]);
3696    operands[2] = gen_reg_rtx (SImode);
3697    
3698    if (TARGET_THUMB)
3699      {
3700	rtx ops[3];
3701	
3702	ops[0] = operands[2];
3703	ops[1] = operands[1];
3704	ops[2] = GEN_INT (24);
3705	
3706        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3707		   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3708
3709	ops[0] = operands[0];
3710	ops[1] = operands[2];
3711	ops[2] = GEN_INT (24);
3712	
3713        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3714		   gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3715	
3716	DONE;
3717      }
3718  }"
3719)
3720
3721; Rather than restricting all byte accesses to memory addresses that ldrsb
3722; can handle, we fix up the ones that ldrsb can't grok with a split.
3723(define_insn "*arm_extendqisi_insn"
3724  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3725	(sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3726  "TARGET_ARM && arm_arch4"
3727  "*
3728  /* If the address is invalid, this will split the instruction into two. */
3729  if (bad_signed_byte_operand (operands[1], VOIDmode))
3730    return \"#\";
3731  return \"ldr%?sb\\t%0, %1\";
3732  "
3733  [(set_attr "type" "load")
3734   (set_attr "predicable" "yes")
3735   (set_attr "length" "8")
3736   (set_attr "pool_range" "256")
3737   (set_attr "neg_pool_range" "244")]
3738)
3739
3740(define_split
3741  [(set (match_operand:SI 0 "s_register_operand" "")
3742	(sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3743  "TARGET_ARM && arm_arch4 && reload_completed"
3744  [(set (match_dup 0) (match_dup 1))
3745   (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3746  "
3747  {
3748    HOST_WIDE_INT offset;
3749
3750    operands[2] = gen_rtx_MEM (QImode, operands[0]);
3751    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3752    operands[1] = XEXP (operands[1], 0);
3753    if (GET_CODE (operands[1]) == PLUS
3754	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3755	&& !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3756	     || const_ok_for_arm (-offset)))
3757      {
3758	HOST_WIDE_INT low = (offset > 0
3759			     ? (offset & 0xff) : -((-offset) & 0xff));
3760	XEXP (operands[2], 0) = plus_constant (operands[0], low);
3761	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3762      }
3763    /* Ensure the sum is in correct canonical form */
3764    else if (GET_CODE (operands[1]) == PLUS
3765	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3766	     && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3767      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3768					   XEXP (operands[1], 1),
3769					   XEXP (operands[1], 0));
3770  }"
3771)
3772
3773(define_insn "*thumb_extendqisi2_insn"
3774  [(set (match_operand:SI                 0 "register_operand" "=l,l")
3775	(sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3776  "TARGET_THUMB"
3777  "*
3778  {
3779    rtx ops[3];
3780    rtx mem = XEXP (operands[1], 0);
3781    
3782    if (GET_CODE (mem) == CONST)
3783      mem = XEXP (mem, 0);
3784    
3785    if (GET_CODE (mem) == LABEL_REF)
3786      return \"ldr\\t%0, %1\";
3787
3788    if (GET_CODE (mem) == PLUS
3789        && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3790      return \"ldr\\t%0, %1\";
3791      
3792    if (which_alternative == 0)
3793      return \"ldrsb\\t%0, %1\";
3794      
3795    ops[0] = operands[0];
3796    
3797    if (GET_CODE (mem) == PLUS)
3798      {
3799        rtx a = XEXP (mem, 0);
3800	rtx b = XEXP (mem, 1);
3801	
3802        ops[1] = a;
3803        ops[2] = b;
3804
3805        if (GET_CODE (a) == REG)
3806	  {
3807	    if (GET_CODE (b) == REG)
3808              output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3809            else if (REGNO (a) == REGNO (ops[0]))
3810	      {
3811                output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3812		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3813		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3814	      }
3815	    else
3816              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3817	  }
3818        else if (GET_CODE (b) != REG)
3819	  abort ();
3820	else
3821          {
3822            if (REGNO (b) == REGNO (ops[0]))
3823	      {
3824                output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3825		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3826		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3827	      }
3828	    else
3829              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3830          }
3831      }
3832    else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3833      {
3834        output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3835	output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3836	output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3837      }
3838    else
3839      {
3840        ops[1] = mem;
3841        ops[2] = const0_rtx;
3842	
3843        output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3844      }
3845    return \"\";
3846  }"
3847  [(set_attr "length" "2,6")
3848   (set_attr "type" "load,load")
3849   (set_attr "pool_range" "32,32")]
3850)
3851
3852(define_insn "extendsfdf2"
3853  [(set (match_operand:DF                  0 "s_register_operand" "=f")
3854	(float_extend:DF (match_operand:SF 1 "s_register_operand"  "f")))]
3855  "TARGET_ARM && TARGET_HARD_FLOAT"
3856  "mvf%?d\\t%0, %1"
3857  [(set_attr "type" "ffarith")
3858   (set_attr "predicable" "yes")]
3859)
3860
3861(define_insn "extendsfxf2"
3862  [(set (match_operand:XF 0 "s_register_operand" "=f")
3863	(float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3864  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3865  "mvf%?e\\t%0, %1"
3866  [(set_attr "type" "ffarith")
3867   (set_attr "predicable" "yes")]
3868)
3869
3870(define_insn "extenddfxf2"
3871  [(set (match_operand:XF 0 "s_register_operand" "=f")
3872	(float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3873  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3874  "mvf%?e\\t%0, %1"
3875  [(set_attr "type" "ffarith")
3876   (set_attr "predicable" "yes")]
3877)
3878
3879
3880;; Move insns (including loads and stores)
3881
3882;; XXX Just some ideas about movti.
3883;; I don't think these are a good idea on the arm, there just aren't enough
3884;; registers
3885;;(define_expand "loadti"
3886;;  [(set (match_operand:TI 0 "s_register_operand" "")
3887;;	(mem:TI (match_operand:SI 1 "address_operand" "")))]
3888;;  "" "")
3889
3890;;(define_expand "storeti"
3891;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3892;;	(match_operand:TI 1 "s_register_operand" ""))]
3893;;  "" "")
3894
3895;;(define_expand "movti"
3896;;  [(set (match_operand:TI 0 "general_operand" "")
3897;;	(match_operand:TI 1 "general_operand" ""))]
3898;;  ""
3899;;  "
3900;;{
3901;;  rtx insn;
3902;;
3903;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3904;;    operands[1] = copy_to_reg (operands[1]);
3905;;  if (GET_CODE (operands[0]) == MEM)
3906;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3907;;  else if (GET_CODE (operands[1]) == MEM)
3908;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3909;;  else
3910;;    FAIL;
3911;;
3912;;  emit_insn (insn);
3913;;  DONE;
3914;;}")
3915
3916;; Recognise garbage generated above.
3917
3918;;(define_insn ""
3919;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3920;;	(match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3921;;  ""
3922;;  "*
3923;;  {
3924;;    register mem = (which_alternative < 3);
3925;;    register const char *template;
3926;;
3927;;    operands[mem] = XEXP (operands[mem], 0);
3928;;    switch (which_alternative)
3929;;      {
3930;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3931;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3932;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3933;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3934;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3935;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3936;;      }
3937;;    output_asm_insn (template, operands);
3938;;    return \"\";
3939;;  }")
3940
3941(define_expand "movdi"
3942  [(set (match_operand:DI 0 "general_operand" "")
3943	(match_operand:DI 1 "general_operand" ""))]
3944  "TARGET_EITHER"
3945  "
3946  if (TARGET_THUMB)
3947    {
3948      if (!no_new_pseudos)
3949        {
3950          if (GET_CODE (operands[0]) != REG)
3951	    operands[1] = force_reg (DImode, operands[1]);
3952        }
3953    }
3954  "
3955)
3956
3957(define_insn "*arm_movdi"
3958  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3959	(match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3960  "TARGET_ARM"
3961  "*
3962  return (output_move_double (operands));
3963  "
3964  [(set_attr "length" "8")
3965   (set_attr "type" "*,load,store2")
3966   (set_attr "pool_range" "*,1020,*")
3967   (set_attr "neg_pool_range" "*,1008,*")]
3968)
3969
3970;;; ??? This should have alternatives for constants.
3971;;; ??? This was originally identical to the movdf_insn pattern.
3972;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3973;;; thumb_reorg with a memory reference.
3974(define_insn "*thumb_movdi_insn"
3975  [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3976	(match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3977  "TARGET_THUMB
3978   && (   register_operand (operands[0], DImode)
3979       || register_operand (operands[1], DImode))"
3980  "*
3981  {
3982  switch (which_alternative)
3983    {
3984    default:
3985    case 0:
3986      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3987	return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3988      return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3989    case 1:
3990      return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3991    case 2:
3992      operands[1] = GEN_INT (- INTVAL (operands[1]));
3993      return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3994    case 3:
3995      return \"ldmia\\t%1, {%0, %H0}\";
3996    case 4:
3997      return \"stmia\\t%0, {%1, %H1}\";
3998    case 5:
3999      return thumb_load_double_from_address (operands);
4000    case 6:
4001      operands[2] = gen_rtx (MEM, SImode,
4002			     plus_constant (XEXP (operands[0], 0), 4));
4003      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4004      return \"\";
4005    case 7:
4006      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4007	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4008      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4009    }
4010  }"
4011  [(set_attr "length" "4,4,6,2,2,6,4,4")
4012   (set_attr "type" "*,*,*,load,store2,load,store2,*")
4013   (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4014)
4015
4016(define_expand "movsi"
4017  [(set (match_operand:SI 0 "general_operand" "")
4018        (match_operand:SI 1 "general_operand" ""))]
4019  "TARGET_EITHER"
4020  "
4021  if (TARGET_ARM)
4022    {
4023      /* Everything except mem = const or mem = mem can be done easily */
4024      if (GET_CODE (operands[0]) == MEM)
4025        operands[1] = force_reg (SImode, operands[1]);
4026      if (GET_CODE (operands[1]) == CONST_INT
4027          && !(const_ok_for_arm (INTVAL (operands[1]))
4028               || const_ok_for_arm (~INTVAL (operands[1]))))
4029        {
4030           arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4031		    	      NULL_RTX,
4032			      (no_new_pseudos ? 0
4033			       : preserve_subexpressions_p ()));
4034          DONE;
4035        }
4036    }
4037  else /* TARGET_THUMB.... */
4038    {
4039      if (!no_new_pseudos)
4040        {
4041          if (GET_CODE (operands[0]) != REG)
4042	    operands[1] = force_reg (SImode, operands[1]);
4043        }
4044    }
4045    
4046  if (flag_pic
4047      && (CONSTANT_P (operands[1])
4048	 || symbol_mentioned_p (operands[1])
4049	 || label_mentioned_p (operands[1])))
4050    operands[1] = legitimize_pic_address (operands[1], SImode,
4051					  (no_new_pseudos ? operands[0] : 0));
4052  "
4053)
4054
4055(define_insn "*arm_movsi_insn"
4056  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4057	(match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4058  "TARGET_ARM
4059   && (   register_operand (operands[0], SImode)
4060       || register_operand (operands[1], SImode))"
4061  "@
4062   mov%?\\t%0, %1
4063   mvn%?\\t%0, #%B1
4064   ldr%?\\t%0, %1
4065   str%?\\t%1, %0"
4066  [(set_attr "type" "*,*,load,store1")
4067   (set_attr "predicable" "yes")
4068   (set_attr "pool_range" "*,*,4096,*")
4069   (set_attr "neg_pool_range" "*,*,4084,*")]
4070)
4071
4072(define_split
4073  [(set (match_operand:SI 0 "s_register_operand" "")
4074	(match_operand:SI 1 "const_int_operand" ""))]
4075  "TARGET_ARM
4076  && (!(const_ok_for_arm (INTVAL (operands[1]))
4077        || const_ok_for_arm (~INTVAL (operands[1]))))"
4078  [(clobber (const_int 0))]
4079  "
4080  arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4081		      NULL_RTX, 0);
4082  DONE;
4083  "
4084)
4085
4086(define_insn "*thumb_movsi_insn"
4087  [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4088	(match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4089  "TARGET_THUMB
4090   && (   register_operand (operands[0], SImode) 
4091       || register_operand (operands[1], SImode))"
4092  "@
4093   mov	%0, %1
4094   mov	%0, %1
4095   #
4096   #
4097   ldmia\\t%1, {%0}
4098   stmia\\t%0, {%1}
4099   ldr\\t%0, %1
4100   str\\t%1, %0
4101   mov\\t%0, %1"
4102  [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4103   (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4104   (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4105)
4106
4107(define_split 
4108  [(set (match_operand:SI 0 "register_operand" "")
4109	(match_operand:SI 1 "const_int_operand" ""))]
4110  "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4111  [(set (match_dup 0) (match_dup 1))
4112   (set (match_dup 0) (neg:SI (match_dup 0)))]
4113  "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4114)
4115
4116(define_split 
4117  [(set (match_operand:SI 0 "register_operand" "")
4118	(match_operand:SI 1 "const_int_operand" ""))]
4119  "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4120  [(set (match_dup 0) (match_dup 1))
4121   (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4122  "
4123  {
4124    unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4125    unsigned HOST_WIDE_INT mask = 0xff;
4126    int i;
4127    
4128    for (i = 0; i < 25; i++)
4129      if ((val & (mask << i)) == val)
4130        break;
4131
4132    if (i == 0)
4133      FAIL;
4134
4135    operands[1] = GEN_INT (val >> i);
4136    operands[2] = GEN_INT (i);
4137  }"
4138)
4139
4140;; When generating pic, we need to load the symbol offset into a register.
4141;; So that the optimizer does not confuse this with a normal symbol load
4142;; we use an unspec.  The offset will be loaded from a constant pool entry,
4143;; since that is the only type of relocation we can use.
4144
4145;; The rather odd constraints on the following are to force reload to leave
4146;; the insn alone, and to force the minipool generation pass to then move
4147;; the GOT symbol to memory.
4148
4149(define_insn "pic_load_addr_arm"
4150  [(set (match_operand:SI 0 "s_register_operand" "=r")
4151	(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4152  "TARGET_ARM && flag_pic"
4153  "ldr%?\\t%0, %1"
4154  [(set_attr "type" "load")
4155   (set (attr "pool_range")     (const_int 4096))
4156   (set (attr "neg_pool_range") (const_int 4084))]
4157)
4158
4159(define_insn "pic_load_addr_thumb"
4160  [(set (match_operand:SI 0 "s_register_operand" "=l")
4161	(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4162  "TARGET_THUMB && flag_pic"
4163  "ldr\\t%0, %1"
4164  [(set_attr "type" "load")
4165   (set (attr "pool_range") (const_int 1024))]
4166)
4167
4168;; This variant is used for AOF assembly, since it needs to mention the
4169;; pic register in the rtl.
4170(define_expand "pic_load_addr_based"
4171  [(set (match_operand:SI 0 "s_register_operand" "=r")
4172	(unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4173  "TARGET_ARM && flag_pic"
4174  "operands[2] = pic_offset_table_rtx;"
4175)
4176
4177(define_insn "*pic_load_addr_based_insn"
4178  [(set (match_operand:SI 0 "s_register_operand" "=r")
4179	(unspec:SI [(match_operand 1 "" "")
4180		    (match_operand 2 "s_register_operand" "r")]
4181		   UNSPEC_PIC_SYM))]
4182  "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4183  "*
4184#ifdef AOF_ASSEMBLER
4185  operands[1] = aof_pic_entry (operands[1]);
4186#endif
4187  output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4188  return \"\";
4189  "
4190  [(set_attr "type" "load")
4191   (set (attr "pool_range")
4192	(if_then_else (eq_attr "is_thumb" "yes")
4193		      (const_int 1024)
4194		      (const_int 4096)))
4195   (set (attr "neg_pool_range")
4196	(if_then_else (eq_attr "is_thumb" "yes")
4197		      (const_int 0)
4198		      (const_int 4084)))]
4199)
4200
4201(define_insn "pic_add_dot_plus_four"
4202  [(set (match_operand:SI 0 "register_operand" "+r")
4203	(plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4204   (use (label_ref (match_operand 1 "" "")))]
4205  "TARGET_THUMB && flag_pic"
4206  "*
4207  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4208			     CODE_LABEL_NUMBER (operands[1]));
4209  return \"add\\t%0, %|pc\";
4210  "
4211  [(set_attr "length" "2")]
4212)
4213
4214(define_insn "pic_add_dot_plus_eight"
4215  [(set (match_operand:SI 0 "register_operand" "+r")
4216	(plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4217   (use (label_ref (match_operand 1 "" "")))]
4218  "TARGET_ARM && flag_pic"
4219  "*
4220    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4221			       CODE_LABEL_NUMBER (operands[1]));
4222    return \"add%?\\t%0, %|pc, %0\";
4223  "
4224  [(set_attr "predicable" "yes")]
4225)
4226
4227(define_expand "builtin_setjmp_receiver"
4228  [(label_ref (match_operand 0 "" ""))]
4229  "flag_pic"
4230  "
4231{
4232  arm_finalize_pic (0);
4233  DONE;
4234}")
4235
4236;; If copying one reg to another we can set the condition codes according to
4237;; its value.  Such a move is common after a return from subroutine and the
4238;; result is being tested against zero.
4239
4240(define_insn "*movsi_compare0"
4241  [(set (reg:CC CC_REGNUM)
4242	(compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4243		    (const_int 0)))
4244   (set (match_operand:SI 0 "s_register_operand" "=r,r")
4245	(match_dup 1))]
4246  "TARGET_ARM"
4247  "@
4248   cmp%?\\t%0, #0
4249   sub%?s\\t%0, %1, #0"
4250  [(set_attr "conds" "set")]
4251)
4252
4253;; Subroutine to store a half word from a register into memory.
4254;; Operand 0 is the source register (HImode)
4255;; Operand 1 is the destination address in a register (SImode)
4256
4257;; In both this routine and the next, we must be careful not to spill
4258;; a memory address of reg+large_const into a separate PLUS insn, since this
4259;; can generate unrecognizable rtl.
4260
4261(define_expand "storehi"
4262  [;; store the low byte
4263   (set (match_operand 1 "" "") (match_dup 3))
4264   ;; extract the high byte
4265   (set (match_dup 2)
4266	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4267   ;; store the high byte
4268   (set (match_dup 4) (subreg:QI (match_dup 2) 0))]	;explicit subreg safe
4269  "TARGET_ARM"
4270  "
4271  {
4272    rtx op1 = operands[1];
4273    rtx addr = XEXP (op1, 0);
4274    enum rtx_code code = GET_CODE (addr);
4275
4276    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4277	|| code == MINUS)
4278      op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4279
4280    operands[4] = adjust_address (op1, QImode, 1);
4281    operands[1] = adjust_address (operands[1], QImode, 0);
4282    operands[3] = gen_lowpart (QImode, operands[0]);
4283    operands[0] = gen_lowpart (SImode, operands[0]);
4284    operands[2] = gen_reg_rtx (SImode); 
4285  }"
4286)
4287
4288(define_expand "storehi_bigend"
4289  [(set (match_dup 4) (match_dup 3))
4290   (set (match_dup 2)
4291	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4292   (set (match_operand 1 "" "")	(subreg:QI (match_dup 2) 3))]
4293  "TARGET_ARM"
4294  "
4295  {
4296    rtx op1 = operands[1];
4297    rtx addr = XEXP (op1, 0);
4298    enum rtx_code code = GET_CODE (addr);
4299
4300    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4301	|| code == MINUS)
4302      op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4303
4304    operands[4] = adjust_address (op1, QImode, 1);
4305    operands[1] = adjust_address (operands[1], QImode, 0);
4306    operands[3] = gen_lowpart (QImode, operands[0]);
4307    operands[0] = gen_lowpart (SImode, operands[0]);
4308    operands[2] = gen_reg_rtx (SImode);
4309  }"
4310)
4311
4312;; Subroutine to store a half word integer constant into memory.
4313(define_expand "storeinthi"
4314  [(set (match_operand 0 "" "")
4315	(subreg:QI (match_operand 1 "" "") 0))
4316   (set (match_dup 3) (match_dup 2))]
4317  "TARGET_ARM"
4318  "
4319  {
4320    HOST_WIDE_INT value = INTVAL (operands[1]);
4321    rtx addr = XEXP (operands[0], 0);
4322    rtx op0 = operands[0];
4323    enum rtx_code code = GET_CODE (addr);
4324
4325    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4326	|| code == MINUS)
4327      op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4328
4329    operands[1] = gen_reg_rtx (SImode);
4330    if (BYTES_BIG_ENDIAN)
4331      {
4332	emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4333	if ((value & 255) == ((value >> 8) & 255))
4334	  operands[2] = operands[1];
4335	else
4336	  {
4337	    operands[2] = gen_reg_rtx (SImode);
4338	    emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4339	  }
4340      }
4341    else
4342      {
4343	emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4344	if ((value & 255) == ((value >> 8) & 255))
4345	  operands[2] = operands[1];
4346	else
4347	  {
4348	    operands[2] = gen_reg_rtx (SImode);
4349	    emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4350	  }
4351      }
4352
4353    operands[3] = adjust_address (op0, QImode, 1);
4354    operands[0] = adjust_address (operands[0], QImode, 0);
4355    operands[2] = gen_lowpart (QImode, operands[2]);
4356  }"
4357)
4358
4359(define_expand "storehi_single_op"
4360  [(set (match_operand:HI 0 "memory_operand" "")
4361	(match_operand:HI 1 "general_operand" ""))]
4362  "TARGET_ARM && arm_arch4"
4363  "
4364  if (!s_register_operand (operands[1], HImode))
4365    operands[1] = copy_to_mode_reg (HImode, operands[1]);
4366  "
4367)
4368
4369(define_expand "movhi"
4370  [(set (match_operand:HI 0 "general_operand" "")
4371	(match_operand:HI 1 "general_operand" ""))]
4372  "TARGET_EITHER"
4373  "
4374  if (TARGET_ARM)
4375    {
4376      if (!no_new_pseudos)
4377        {
4378          if (GET_CODE (operands[0]) == MEM)
4379	    {
4380	      if (arm_arch4)
4381	        {
4382	          emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4383	          DONE;
4384	        }
4385	      if (GET_CODE (operands[1]) == CONST_INT)
4386	        emit_insn (gen_storeinthi (operands[0], operands[1]));
4387	      else
4388	        {
4389	          if (GET_CODE (operands[1]) == MEM)
4390		    operands[1] = force_reg (HImode, operands[1]);
4391	          if (BYTES_BIG_ENDIAN)
4392		    emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4393	          else
4394		   emit_insn (gen_storehi (operands[1], operands[0]));
4395	        }
4396	      DONE;
4397	    }
4398          /* Sign extend a constant, and keep it in an SImode reg.  */
4399          else if (GET_CODE (operands[1]) == CONST_INT)
4400	    {
4401	      rtx reg = gen_reg_rtx (SImode);
4402	      HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4403
4404	      /* If the constant is already valid, leave it alone.  */
4405	      if (!const_ok_for_arm (val))
4406	        {
4407	          /* If setting all the top bits will make the constant 
4408		     loadable in a single instruction, then set them.  
4409		     Otherwise, sign extend the number.  */
4410
4411	          if (const_ok_for_arm (~(val | ~0xffff)))
4412		    val |= ~0xffff;
4413	          else if (val & 0x8000)
4414		    val |= ~0xffff;
4415	        }
4416
4417	      emit_insn (gen_movsi (reg, GEN_INT (val)));
4418	      operands[1] = gen_lowpart (HImode, reg);
4419	    }
4420          else if (!arm_arch4)
4421	    {
4422	     /* Note: We do not have to worry about TARGET_MMU_TRAPS
4423	        for v4 and up architectures because LDRH instructions will
4424	        be used to access the HI values, and these cannot generate
4425	        unaligned word access faults in the MMU.  */
4426	      if (GET_CODE (operands[1]) == MEM)
4427	        {
4428	          if (TARGET_MMU_TRAPS)
4429		    {
4430		      rtx base;
4431		      rtx offset = const0_rtx;
4432		      rtx reg = gen_reg_rtx (SImode);
4433
4434		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4435		           || (GET_CODE (base) == PLUS
4436			       && (GET_CODE (offset = XEXP (base, 1))
4437				   == CONST_INT)
4438                               && ((INTVAL(offset) & 1) != 1)
4439			       && GET_CODE (base = XEXP (base, 0)) == REG))
4440		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4441		        {
4442		          HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4443		          rtx new;
4444
4445		          new = gen_rtx_MEM (SImode,
4446				   	     plus_constant (base, new_offset));
4447	                  MEM_COPY_ATTRIBUTES (new, operands[1]);
4448		          emit_insn (gen_movsi (reg, new));
4449		          if (((INTVAL (offset) & 2) != 0)
4450			      ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4451			    {
4452			      rtx reg2 = gen_reg_rtx (SImode);
4453
4454			      emit_insn (gen_lshrsi3 (reg2, reg,
4455					 GEN_INT (16)));
4456			      reg = reg2;
4457			    }
4458		        }
4459		      else
4460		        emit_insn (gen_movhi_bytes (reg, operands[1]));
4461
4462		      operands[1] = gen_lowpart (HImode, reg);
4463		    }
4464	          else if (BYTES_BIG_ENDIAN)
4465		    {
4466		      rtx base;
4467		      rtx offset = const0_rtx;
4468
4469		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4470		           || (GET_CODE (base) == PLUS
4471			      && (GET_CODE (offset = XEXP (base, 1))
4472				  == CONST_INT)
4473			      && GET_CODE (base = XEXP (base, 0)) == REG))
4474		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4475		        {
4476		          rtx reg = gen_reg_rtx (SImode);
4477		          rtx new;
4478
4479		          if ((INTVAL (offset) & 2) == 2)
4480			    {
4481			      HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4482			      new = gen_rtx_MEM (SImode,
4483				  	         plus_constant (base,
4484								new_offset));
4485                              MEM_COPY_ATTRIBUTES (new, operands[1]);
4486			      emit_insn (gen_movsi (reg, new));
4487			    }
4488		          else
4489			    {
4490			      new = gen_rtx_MEM (SImode,
4491						 XEXP (operands[1], 0));
4492	                      MEM_COPY_ATTRIBUTES (new, operands[1]);
4493			      emit_insn (gen_rotated_loadsi (reg, new));
4494			    }
4495
4496		          operands[1] = gen_lowpart (HImode, reg);
4497		        }
4498		      else
4499		        {
4500		          emit_insn (gen_movhi_bigend (operands[0],
4501						       operands[1]));
4502		          DONE;
4503		        }
4504		    }
4505	       }
4506	   }
4507        }
4508      /* Handle loading a large integer during reload */
4509      else if (GET_CODE (operands[1]) == CONST_INT
4510	       && !const_ok_for_arm (INTVAL (operands[1]))
4511	       && !const_ok_for_arm (~INTVAL (operands[1])))
4512        {
4513          /* Writing a constant to memory needs a scratch, which should
4514	     be handled with SECONDARY_RELOADs.  */
4515          if (GET_CODE (operands[0]) != REG)
4516	    abort ();
4517
4518          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4519          emit_insn (gen_movsi (operands[0], operands[1]));
4520          DONE;
4521       }
4522    }
4523  else /* TARGET_THUMB */
4524    {
4525      if (!no_new_pseudos)
4526        {
4527          if (GET_CODE (operands[0]) != REG)
4528	    operands[1] = force_reg (HImode, operands[1]);
4529
4530          /* ??? We shouldn't really get invalid addresses here, but this can
4531	     happen if we are passed a SP (never OK for HImode/QImode) or 
4532	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4533	     HImode/QImode) relative address.  */
4534          /* ??? This should perhaps be fixed elsewhere, for instance, in
4535	     fixup_stack_1, by checking for other kinds of invalid addresses,
4536	     e.g. a bare reference to a virtual register.  This may confuse the
4537	     alpha though, which must handle this case differently.  */
4538          if (GET_CODE (operands[0]) == MEM
4539	      && !memory_address_p (GET_MODE (operands[0]),
4540				    XEXP (operands[0], 0)))
4541	    operands[0]
4542	      = replace_equiv_address (operands[0],
4543				       copy_to_reg (XEXP (operands[0], 0)));
4544   
4545          if (GET_CODE (operands[1]) == MEM
4546	      && !memory_address_p (GET_MODE (operands[1]),
4547				    XEXP (operands[1], 0)))
4548	    operands[1]
4549	      = replace_equiv_address (operands[1],
4550				       copy_to_reg (XEXP (operands[1], 0)));
4551        }
4552      /* Handle loading a large integer during reload */
4553      else if (GET_CODE (operands[1]) == CONST_INT
4554	        && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4555        {
4556          /* Writing a constant to memory needs a scratch, which should
4557	     be handled with SECONDARY_RELOADs.  */
4558          if (GET_CODE (operands[0]) != REG)
4559	    abort ();
4560
4561          operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4562          emit_insn (gen_movsi (operands[0], operands[1]));
4563          DONE;
4564        }
4565    }
4566  "
4567)
4568
4569(define_insn "*thumb_movhi_insn"
4570  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4571	(match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4572  "TARGET_THUMB
4573   && (   register_operand (operands[0], HImode)
4574       || register_operand (operands[1], HImode))"
4575  "*
4576  switch (which_alternative)
4577    {
4578    case 0: return \"add	%0, %1, #0\";
4579    case 2: return \"strh	%1, %0\";
4580    case 3: return \"mov	%0, %1\";
4581    case 4: return \"mov	%0, %1\";
4582    case 5: return \"mov	%0, %1\";
4583    default: abort ();
4584    case 1:
4585      /* The stack pointer can end up being taken as an index register.
4586          Catch this case here and deal with it.  */
4587      if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4588	  && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4589	  && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4590        {
4591	  rtx ops[2];
4592          ops[0] = operands[0];
4593          ops[1] = XEXP (XEXP (operands[1], 0), 0);
4594      
4595          output_asm_insn (\"mov	%0, %1\", ops);
4596
4597          XEXP (XEXP (operands[1], 0), 0) = operands[0];
4598    
4599	}
4600      return \"ldrh	%0, %1\";
4601    }"
4602  [(set_attr "length" "2,4,2,2,2,2")
4603   (set_attr "type" "*,load,store1,*,*,*")
4604   (set_attr "pool_range" "*,64,*,*,*,*")]
4605)
4606
4607
4608(define_insn "rotated_loadsi"
4609  [(set (match_operand:SI            0 "s_register_operand"        "=r")
4610	(rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4611		   (const_int 16)))]
4612  "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4613  "*
4614  {
4615    rtx ops[2];
4616
4617    ops[0] = operands[0];
4618    ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4619    output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4620    return \"\";
4621  }"
4622  [(set_attr "type" "load")
4623   (set_attr "predicable" "yes")]
4624)
4625
4626(define_expand "movhi_bytes"
4627  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4628   (set (match_dup 3)
4629	(zero_extend:SI (match_dup 6)))
4630   (set (match_operand:SI 0 "" "")
4631	 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4632  "TARGET_ARM"
4633  "
4634  {
4635    rtx mem1, mem2;
4636    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4637
4638    mem1 = gen_rtx_MEM (QImode, addr);
4639    MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4640    mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4641    MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4642    operands[0] = gen_lowpart (SImode, operands[0]);
4643    operands[1] = mem1;
4644    operands[2] = gen_reg_rtx (SImode);
4645    operands[3] = gen_reg_rtx (SImode);
4646    operands[6] = mem2;
4647
4648    if (BYTES_BIG_ENDIAN)
4649      {
4650	operands[4] = operands[2];
4651	operands[5] = operands[3];
4652      }
4653    else
4654      {
4655	operands[4] = operands[3];
4656	operands[5] = operands[2];
4657      }
4658  }"
4659)
4660
4661(define_expand "movhi_bigend"
4662  [(set (match_dup 2)
4663	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4664		   (const_int 16)))
4665   (set (match_dup 3)
4666	(ashiftrt:SI (match_dup 2) (const_int 16)))
4667   (set (match_operand:HI 0 "s_register_operand" "")
4668	(subreg:HI (match_dup 3) 0))]
4669  "TARGET_ARM"
4670  "
4671  operands[2] = gen_reg_rtx (SImode);
4672  operands[3] = gen_reg_rtx (SImode);
4673  "
4674)
4675
4676;; Pattern to recognise insn generated default case above
4677(define_insn "*movhi_insn_arch4"
4678  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4679	(match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4680  "TARGET_ARM
4681   && arm_arch4
4682   && (GET_CODE (operands[1]) != CONST_INT
4683       || const_ok_for_arm (INTVAL (operands[1]))
4684       || const_ok_for_arm (~INTVAL (operands[1])))"
4685  "@
4686   mov%?\\t%0, %1\\t%@ movhi
4687   mvn%?\\t%0, #%B1\\t%@ movhi
4688   str%?h\\t%1, %0\\t%@ movhi 
4689   ldr%?h\\t%0, %1\\t%@ movhi"
4690  [(set_attr "type" "*,*,store1,load")
4691   (set_attr "predicable" "yes")
4692   (set_attr "pool_range" "*,*,*,256")
4693   (set_attr "neg_pool_range" "*,*,*,244")]
4694)
4695
4696(define_insn "*movhi_insn_littleend"
4697  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4698	(match_operand:HI 1 "general_operand"  "rI,K,m"))]
4699  "TARGET_ARM
4700   && !arm_arch4
4701   && !BYTES_BIG_ENDIAN
4702   && !TARGET_MMU_TRAPS
4703   && (GET_CODE (operands[1]) != CONST_INT
4704       || const_ok_for_arm (INTVAL (operands[1]))
4705       || const_ok_for_arm (~INTVAL (operands[1])))"
4706  "@
4707   mov%?\\t%0, %1\\t%@ movhi
4708   mvn%?\\t%0, #%B1\\t%@ movhi
4709   ldr%?\\t%0, %1\\t%@ movhi"
4710  [(set_attr "type" "*,*,load")
4711   (set_attr "predicable" "yes")
4712   (set_attr "pool_range" "4096")
4713   (set_attr "neg_pool_range" "4084")]
4714)
4715
4716(define_insn "*movhi_insn_bigend"
4717  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4718	(match_operand:HI 1 "general_operand"    "rI,K,m"))]
4719  "TARGET_ARM
4720   && !arm_arch4
4721   && BYTES_BIG_ENDIAN
4722   && !TARGET_MMU_TRAPS
4723   && (GET_CODE (operands[1]) != CONST_INT
4724       || const_ok_for_arm (INTVAL (operands[1]))
4725       || const_ok_for_arm (~INTVAL (operands[1])))"
4726  "@
4727   mov%?\\t%0, %1\\t%@ movhi
4728   mvn%?\\t%0, #%B1\\t%@ movhi
4729   ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4730  [(set_attr "type" "*,*,load")
4731   (set_attr "predicable" "yes")
4732   (set_attr "length" "4,4,8")
4733   (set_attr "pool_range" "*,*,4092")
4734   (set_attr "neg_pool_range" "*,*,4084")]
4735)
4736
4737(define_insn "*loadhi_si_bigend"
4738  [(set (match_operand:SI                       0 "s_register_operand" "=r")
4739	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4740		   (const_int 16)))]
4741  "TARGET_ARM
4742   && BYTES_BIG_ENDIAN
4743   && !TARGET_MMU_TRAPS"
4744  "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4745  [(set_attr "type" "load")
4746   (set_attr "predicable" "yes")
4747   (set_attr "pool_range" "4096")
4748   (set_attr "neg_pool_range" "4084")]
4749)
4750
4751(define_insn "*movhi_bytes"
4752  [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4753	(match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4754  "TARGET_ARM && TARGET_MMU_TRAPS"
4755  "@
4756   mov%?\\t%0, %1\\t%@ movhi
4757   mvn%?\\t%0, #%B1\\t%@ movhi"
4758  [(set_attr "predicable" "yes")]
4759)
4760
4761(define_insn "thumb_movhi_clobber"
4762  [(set (match_operand:HI     0 "memory_operand"   "=m")
4763	(match_operand:HI     1 "register_operand" "l"))
4764   (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4765  "TARGET_THUMB"
4766  "*
4767  abort ();"
4768)
4769	
4770;; We use a DImode scratch because we may occasionally need an additional
4771;; temporary if the address isn't offsettable -- push_reload doesn't seem
4772;; to take any notice of the "o" constraints on reload_memory_operand operand.
4773(define_expand "reload_outhi"
4774  [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4775	      (match_operand:HI 1 "s_register_operand"        "r")
4776	      (match_operand:DI 2 "s_register_operand"        "=&l")])]
4777  "TARGET_EITHER"
4778  "if (TARGET_ARM)
4779     arm_reload_out_hi (operands);
4780   else
4781     thumb_reload_out_hi (operands);
4782  DONE;
4783  "
4784)
4785
4786(define_expand "reload_inhi"
4787  [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4788	      (match_operand:HI 1 "arm_reload_memory_operand" "o")
4789	      (match_operand:DI 2 "s_register_operand" "=&r")])]
4790  "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4791  "
4792  if (TARGET_ARM)
4793    arm_reload_in_hi (operands);
4794  else
4795    thumb_reload_out_hi (operands);
4796  DONE;
4797")
4798
4799(define_expand "movqi"
4800  [(set (match_operand:QI 0 "general_operand" "")
4801        (match_operand:QI 1 "general_operand" ""))]
4802  "TARGET_EITHER"
4803  "
4804  if (TARGET_ARM)
4805    {
4806      /* Everything except mem = const or mem = mem can be done easily */
4807
4808      if (!no_new_pseudos)
4809        {
4810          if (GET_CODE (operands[1]) == CONST_INT)
4811	    {
4812	      rtx reg = gen_reg_rtx (SImode);
4813
4814	      emit_insn (gen_movsi (reg, operands[1]));
4815	      operands[1] = gen_lowpart (QImode, reg);
4816	    }
4817         if (GET_CODE (operands[0]) == MEM)
4818	   operands[1] = force_reg (QImode, operands[1]);
4819       }
4820    }
4821  else /* TARGET_THUMB */
4822    {
4823      if (!no_new_pseudos)
4824        {
4825          if (GET_CODE (operands[0]) != REG)
4826	    operands[1] = force_reg (QImode, operands[1]);
4827
4828          /* ??? We shouldn't really get invalid addresses here, but this can
4829	     happen if we are passed a SP (never OK for HImode/QImode) or
4830	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4831	     HImode/QImode) relative address.  */
4832          /* ??? This should perhaps be fixed elsewhere, for instance, in
4833	     fixup_stack_1, by checking for other kinds of invalid addresses,
4834	     e.g. a bare reference to a virtual register.  This may confuse the
4835	     alpha though, which must handle this case differently.  */
4836          if (GET_CODE (operands[0]) == MEM
4837	      && !memory_address_p (GET_MODE (operands[0]),
4838		  		     XEXP (operands[0], 0)))
4839	    operands[0]
4840	      = replace_equiv_address (operands[0],
4841				       copy_to_reg (XEXP (operands[0], 0)));
4842          if (GET_CODE (operands[1]) == MEM
4843	      && !memory_address_p (GET_MODE (operands[1]),
4844				    XEXP (operands[1], 0)))
4845	     operands[1]
4846	       = replace_equiv_address (operands[1],
4847					copy_to_reg (XEXP (operands[1], 0)));
4848        }
4849      /* Handle loading a large integer during reload */
4850      else if (GET_CODE (operands[1]) == CONST_INT
4851	       && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4852        {
4853          /* Writing a constant to memory needs a scratch, which should
4854	     be handled with SECONDARY_RELOADs.  */
4855          if (GET_CODE (operands[0]) != REG)
4856	    abort ();
4857
4858          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4859          emit_insn (gen_movsi (operands[0], operands[1]));
4860          DONE;
4861       }
4862    }
4863  "
4864)
4865
4866
4867(define_insn "*arm_movqi_insn"
4868  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4869	(match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4870  "TARGET_ARM
4871   && (   register_operand (operands[0], QImode)
4872       || register_operand (operands[1], QImode))"
4873  "@
4874   mov%?\\t%0, %1
4875   mvn%?\\t%0, #%B1
4876   ldr%?b\\t%0, %1
4877   str%?b\\t%1, %0"
4878  [(set_attr "type" "*,*,load,store1")
4879   (set_attr "predicable" "yes")]
4880)
4881
4882(define_insn "*thumb_movqi_insn"
4883  [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4884	(match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4885  "TARGET_THUMB
4886   && (   register_operand (operands[0], QImode)
4887       || register_operand (operands[1], QImode))"
4888  "@
4889   add\\t%0, %1, #0
4890   ldrb\\t%0, %1
4891   strb\\t%1, %0
4892   mov\\t%0, %1
4893   mov\\t%0, %1
4894   mov\\t%0, %1"
4895  [(set_attr "length" "2")
4896   (set_attr "type" "*,load,store1,*,*,*")
4897   (set_attr "pool_range" "*,32,*,*,*,*")]
4898)
4899
4900(define_expand "movsf"
4901  [(set (match_operand:SF 0 "general_operand" "")
4902	(match_operand:SF 1 "general_operand" ""))]
4903  "TARGET_EITHER"
4904  "
4905  if (TARGET_ARM)
4906    {
4907      if (GET_CODE (operands[0]) == MEM)
4908        operands[1] = force_reg (SFmode, operands[1]);
4909    }
4910  else /* TARGET_THUMB */
4911    {
4912      if (!no_new_pseudos)
4913        {
4914           if (GET_CODE (operands[0]) != REG)
4915	     operands[1] = force_reg (SFmode, operands[1]);
4916        }
4917    }
4918  "
4919)
4920
4921(define_split
4922  [(set (match_operand:SF 0 "nonimmediate_operand" "")
4923	(match_operand:SF 1 "immediate_operand" ""))]
4924  "TARGET_ARM
4925   && !TARGET_HARD_FLOAT
4926   && reload_completed
4927   && GET_CODE (operands[1]) == CONST_DOUBLE"
4928  [(set (match_dup 2) (match_dup 3))]
4929  "
4930  operands[2] = gen_lowpart (SImode, operands[0]);
4931  operands[3] = gen_lowpart (SImode, operands[1]);
4932  if (operands[2] == 0 || operands[3] == 0)
4933    FAIL;
4934  "
4935)
4936
4937(define_insn "*arm_movsf_hard_insn"
4938  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4939	(match_operand:SF 1 "general_operand"      "fG,H,mE,f,r,f,r,mE,r"))]
4940  "TARGET_ARM
4941   && TARGET_HARD_FLOAT
4942   && (GET_CODE (operands[0]) != MEM
4943       || register_operand (operands[1], SFmode))"
4944  "@
4945   mvf%?s\\t%0, %1
4946   mnf%?s\\t%0, #%N1
4947   ldf%?s\\t%0, %1
4948   stf%?s\\t%1, %0
4949   str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4950   stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4951   mov%?\\t%0, %1
4952   ldr%?\\t%0, %1\\t%@ float
4953   str%?\\t%1, %0\\t%@ float"
4954  [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4955   (set_attr "predicable" "yes")
4956   (set_attr "type"
4957	 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4958   (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4959   (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4960)
4961
4962;; Exactly the same as above, except that all `f' cases are deleted.
4963;; This is necessary to prevent reload from ever trying to use a `f' reg
4964;; when -msoft-float.
4965
4966(define_insn "*arm_movsf_soft_insn"
4967  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4968	(match_operand:SF 1 "general_operand"  "r,mE,r"))]
4969  "TARGET_ARM
4970   && TARGET_SOFT_FLOAT
4971   && (GET_CODE (operands[0]) != MEM
4972       || register_operand (operands[1], SFmode))"
4973  "@
4974   mov%?\\t%0, %1
4975   ldr%?\\t%0, %1\\t%@ float
4976   str%?\\t%1, %0\\t%@ float"
4977  [(set_attr "length" "4,4,4")
4978   (set_attr "predicable" "yes")
4979   (set_attr "type" "*,load,store1")
4980   (set_attr "pool_range" "*,4096,*")
4981   (set_attr "neg_pool_range" "*,4084,*")]
4982)
4983
4984;;; ??? This should have alternatives for constants.
4985(define_insn "*thumb_movsf_insn"
4986  [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4987	(match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4988  "TARGET_THUMB
4989   && (   register_operand (operands[0], SFmode) 
4990       || register_operand (operands[1], SFmode))"
4991  "@
4992   add\\t%0, %1, #0
4993   ldmia\\t%1, {%0}
4994   stmia\\t%0, {%1}
4995   ldr\\t%0, %1
4996   str\\t%1, %0
4997   mov\\t%0, %1
4998   mov\\t%0, %1"
4999  [(set_attr "length" "2")
5000   (set_attr "type" "*,load,store1,load,store1,*,*")
5001   (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5002)
5003
5004(define_expand "movdf"
5005  [(set (match_operand:DF 0 "general_operand" "")
5006	(match_operand:DF 1 "general_operand" ""))]
5007  "TARGET_EITHER"
5008  "
5009  if (TARGET_ARM)
5010    {
5011      if (GET_CODE (operands[0]) == MEM)
5012        operands[1] = force_reg (DFmode, operands[1]);
5013    }
5014  else /* TARGET_THUMB */
5015    {
5016      if (!no_new_pseudos)
5017        {
5018          if (GET_CODE (operands[0]) != REG)
5019	    operands[1] = force_reg (DFmode, operands[1]);
5020        }
5021    }
5022  "
5023)
5024
5025;; Reloading a df mode value stored in integer regs to memory can require a
5026;; scratch reg.
5027(define_expand "reload_outdf"
5028  [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5029   (match_operand:DF 1 "s_register_operand" "r")
5030   (match_operand:SI 2 "s_register_operand" "=&r")]
5031  "TARGET_ARM"
5032  "
5033  {
5034    enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5035
5036    if (code == REG)
5037      operands[2] = XEXP (operands[0], 0);
5038    else if (code == POST_INC || code == PRE_DEC)
5039      {
5040	operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5041	operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5042	emit_insn (gen_movdi (operands[0], operands[1]));
5043	DONE;
5044      }
5045    else if (code == PRE_INC)
5046      {
5047	rtx reg = XEXP (XEXP (operands[0], 0), 0);
5048
5049	emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5050	operands[2] = reg;
5051      }
5052    else if (code == POST_DEC)
5053      operands[2] = XEXP (XEXP (operands[0], 0), 0);
5054    else
5055      emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5056			     XEXP (XEXP (operands[0], 0), 1)));
5057
5058    emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5059			    operands[1]));
5060
5061    if (code == POST_DEC)
5062      emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5063
5064    DONE;
5065  }"
5066)
5067
5068(define_insn "*movdf_hard_insn"
5069  [(set (match_operand:DF 0 "nonimmediate_operand"
5070						"=r,Q,r,m,r, f, f,f, m,!f,!r")
5071	(match_operand:DF 1 "general_operand"
5072						"Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5073  "TARGET_ARM
5074   && TARGET_HARD_FLOAT
5075   && (GET_CODE (operands[0]) != MEM
5076       || register_operand (operands[1], DFmode))"
5077  "*
5078  {
5079  switch (which_alternative)
5080    {
5081    default:
5082    case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5083    case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5084    case 2: case 3: case 4: return output_move_double (operands);
5085    case 5: return \"mvf%?d\\t%0, %1\";
5086    case 6: return \"mnf%?d\\t%0, #%N1\";
5087    case 7: return \"ldf%?d\\t%0, %1\";
5088    case 8: return \"stf%?d\\t%1, %0\";
5089    case 9: return output_mov_double_fpu_from_arm (operands);
5090    case 10: return output_mov_double_arm_from_fpu (operands);
5091    }
5092  }
5093  "
5094  [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5095   (set_attr "predicable" "yes")
5096   (set_attr "type"
5097    "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5098   (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
5099   (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
5100)
5101
5102;; Software floating point version.  This is essentially the same as movdi.
5103;; Do not use `f' as a constraint to prevent reload from ever trying to use
5104;; an `f' reg.
5105
5106(define_insn "*movdf_soft_insn"
5107  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5108	(match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5109  "TARGET_ARM && TARGET_SOFT_FLOAT
5110  "
5111  "* return output_move_double (operands);"
5112  [(set_attr "length" "8,8,8")
5113   (set_attr "type" "*,load,store2")
5114   (set_attr "pool_range" "1020")
5115   (set_attr "neg_pool_range" "1008")]
5116)
5117
5118;;; ??? This should have alternatives for constants.
5119;;; ??? This was originally identical to the movdi_insn pattern.
5120;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5121;;; thumb_reorg with a memory reference.
5122(define_insn "*thumb_movdf_insn"
5123  [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5124	(match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5125  "TARGET_THUMB
5126   && (   register_operand (operands[0], DFmode)
5127       || register_operand (operands[1], DFmode))"
5128  "*
5129  switch (which_alternative)
5130    {
5131    default:
5132    case 0:
5133      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5134	return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5135      return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5136    case 1:
5137      return \"ldmia\\t%1, {%0, %H0}\";
5138    case 2:
5139      return \"stmia\\t%0, {%1, %H1}\";
5140    case 3:
5141      return thumb_load_double_from_address (operands);
5142    case 4:
5143      operands[2] = gen_rtx (MEM, SImode,
5144			     plus_constant (XEXP (operands[0], 0), 4));
5145      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5146      return \"\";
5147    case 5:
5148      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5149	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5150      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5151    }
5152  "
5153  [(set_attr "length" "4,2,2,6,4,4")
5154   (set_attr "type" "*,load,store2,load,store2,*")
5155   (set_attr "pool_range" "*,*,*,1020,*,*")]
5156)
5157
5158
5159(define_expand "movxf"
5160  [(set (match_operand:XF 0 "general_operand" "")
5161	(match_operand:XF 1 "general_operand" ""))]
5162  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5163  "")
5164
5165;; Even when the XFmode patterns aren't enabled, we enable this after
5166;; reloading so that we can push floating point registers in the prologue.
5167
5168(define_insn "*movxf_hard_insn"
5169  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5170	(match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5171  "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5172  "*
5173  switch (which_alternative)
5174    {
5175    default:
5176    case 0: return \"mvf%?e\\t%0, %1\";
5177    case 1: return \"mnf%?e\\t%0, #%N1\";
5178    case 2: return \"ldf%?e\\t%0, %1\";
5179    case 3: return \"stf%?e\\t%1, %0\";
5180    case 4: return output_mov_long_double_fpu_from_arm (operands);
5181    case 5: return output_mov_long_double_arm_from_fpu (operands);
5182    case 6: return output_mov_long_double_arm_from_arm (operands);
5183    }
5184  "
5185  [(set_attr "length" "4,4,4,4,8,8,12")
5186   (set_attr "predicable" "yes")
5187   (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5188   (set_attr "pool_range" "*,*,1024,*,*,*,*")
5189   (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5190)
5191
5192
5193;; load- and store-multiple insns
5194;; The arm can load/store any set of registers, provided that they are in
5195;; ascending order; but that is beyond GCC so stick with what it knows.
5196
5197(define_expand "load_multiple"
5198  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5199                          (match_operand:SI 1 "" ""))
5200                     (use (match_operand:SI 2 "" ""))])]
5201  "TARGET_ARM"
5202  "
5203  /* Support only fixed point registers.  */
5204  if (GET_CODE (operands[2]) != CONST_INT
5205      || INTVAL (operands[2]) > 14
5206      || INTVAL (operands[2]) < 2
5207      || GET_CODE (operands[1]) != MEM
5208      || GET_CODE (operands[0]) != REG
5209      || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5210      || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5211    FAIL;
5212
5213  operands[3]
5214    = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5215			     force_reg (SImode, XEXP (operands[1], 0)),
5216			     TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5217			     MEM_IN_STRUCT_P(operands[1]),
5218	                     MEM_SCALAR_P (operands[1]));
5219  "
5220)
5221
5222;; Load multiple with write-back
5223
5224(define_insn "*ldmsi_postinc4"
5225  [(match_parallel 0 "load_multiple_operation"
5226    [(set (match_operand:SI 1 "s_register_operand" "=r")
5227	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5228		   (const_int 16)))
5229     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5230	  (mem:SI (match_dup 2)))
5231     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5232	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5233     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5234	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5235     (set (match_operand:SI 6 "arm_hard_register_operand" "")
5236	  (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5237  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5238  "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5239  [(set_attr "type" "load")
5240   (set_attr "predicable" "yes")]
5241)
5242
5243(define_insn "*ldmsi_postinc3"
5244  [(match_parallel 0 "load_multiple_operation"
5245    [(set (match_operand:SI 1 "s_register_operand" "=r")
5246	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5247		   (const_int 12)))
5248     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5249	  (mem:SI (match_dup 2)))
5250     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5251	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5252     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5253	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5254  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5255  "ldm%?ia\\t%1!, {%3, %4, %5}"
5256  [(set_attr "type" "load")
5257   (set_attr "predicable" "yes")]
5258)
5259
5260(define_insn "*ldmsi_postinc2"
5261  [(match_parallel 0 "load_multiple_operation"
5262    [(set (match_operand:SI 1 "s_register_operand" "=r")
5263	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5264		   (const_int 8)))
5265     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5266	  (mem:SI (match_dup 2)))
5267     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5268	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5269  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5270  "ldm%?ia\\t%1!, {%3, %4}"
5271  [(set_attr "type" "load")
5272   (set_attr "predicable" "yes")]
5273)
5274
5275;; Ordinary load multiple
5276
5277(define_insn "*ldmsi4"
5278  [(match_parallel 0 "load_multiple_operation"
5279    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5280	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5281     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5282	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5283     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5284	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5285     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5286	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5287  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5288  "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5289  [(set_attr "type" "load")
5290   (set_attr "predicable" "yes")]
5291)
5292
5293(define_insn "*ldmsi3"
5294  [(match_parallel 0 "load_multiple_operation"
5295    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5296	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5297     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5298	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5299     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5300	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5301  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5302  "ldm%?ia\\t%1, {%2, %3, %4}"
5303  [(set_attr "type" "load")
5304   (set_attr "predicable" "yes")]
5305)
5306
5307(define_insn "*ldmsi2"
5308  [(match_parallel 0 "load_multiple_operation"
5309    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5310	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5311     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5312	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5313  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5314  "ldm%?ia\\t%1, {%2, %3}"
5315  [(set_attr "type" "load")
5316   (set_attr "predicable" "yes")]
5317)
5318
5319(define_expand "store_multiple"
5320  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5321                          (match_operand:SI 1 "" ""))
5322                     (use (match_operand:SI 2 "" ""))])]
5323  "TARGET_ARM"
5324  "
5325  /* Support only fixed point registers */
5326  if (GET_CODE (operands[2]) != CONST_INT
5327      || INTVAL (operands[2]) > 14
5328      || INTVAL (operands[2]) < 2
5329      || GET_CODE (operands[1]) != REG
5330      || GET_CODE (operands[0]) != MEM
5331      || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5332      || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5333    FAIL;
5334
5335  operands[3]
5336    = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5337			      force_reg (SImode, XEXP (operands[0], 0)),
5338			      TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5339			      MEM_IN_STRUCT_P(operands[0]), 
5340	                      MEM_SCALAR_P (operands[0]));
5341  "
5342)
5343
5344;; Store multiple with write-back
5345
5346(define_insn "*stmsi_postinc4"
5347  [(match_parallel 0 "store_multiple_operation"
5348    [(set (match_operand:SI 1 "s_register_operand" "=r")
5349	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5350		   (const_int 16)))
5351     (set (mem:SI (match_dup 2))
5352	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5353     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5354	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5355     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5356	  (match_operand:SI 5 "arm_hard_register_operand" ""))
5357     (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5358	  (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5359  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5360  "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5361  [(set_attr "predicable" "yes")
5362   (set_attr "type" "store4")]
5363)
5364
5365(define_insn "*stmsi_postinc3"
5366  [(match_parallel 0 "store_multiple_operation"
5367    [(set (match_operand:SI 1 "s_register_operand" "=r")
5368	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5369		   (const_int 12)))
5370     (set (mem:SI (match_dup 2))
5371	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5372     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5373	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5374     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5375	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5376  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5377  "stm%?ia\\t%1!, {%3, %4, %5}"
5378  [(set_attr "predicable" "yes")
5379   (set_attr "type" "store3")]
5380)
5381
5382(define_insn "*stmsi_postinc2"
5383  [(match_parallel 0 "store_multiple_operation"
5384    [(set (match_operand:SI 1 "s_register_operand" "=r")
5385	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5386		   (const_int 8)))
5387     (set (mem:SI (match_dup 2))
5388	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5389     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5390	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5391  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5392  "stm%?ia\\t%1!, {%3, %4}"
5393  [(set_attr "predicable" "yes")
5394   (set_attr "type" "store2")]
5395)
5396
5397;; Ordinary store multiple
5398
5399(define_insn "*stmsi4"
5400  [(match_parallel 0 "store_multiple_operation"
5401    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5402	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5403     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5404	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5405     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5406	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5407     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5408	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5409  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5410  "stm%?ia\\t%1, {%2, %3, %4, %5}"
5411  [(set_attr "predicable" "yes")
5412   (set_attr "type" "store4")]
5413)
5414
5415(define_insn "*stmsi3"
5416  [(match_parallel 0 "store_multiple_operation"
5417    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5418	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5419     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5420	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5421     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5422	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5423  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5424  "stm%?ia\\t%1, {%2, %3, %4}"
5425  [(set_attr "predicable" "yes")
5426   (set_attr "type" "store3")]
5427)
5428
5429(define_insn "*stmsi2"
5430  [(match_parallel 0 "store_multiple_operation"
5431    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5432	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5433     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5434	  (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5435  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5436  "stm%?ia\\t%1, {%2, %3}"
5437  [(set_attr "predicable" "yes")
5438   (set_attr "type" "store2")]
5439)
5440
5441;; Move a block of memory if it is word aligned and MORE than 2 words long.
5442;; We could let this apply for blocks of less than this, but it clobbers so
5443;; many registers that there is then probably a better way.
5444
5445(define_expand "movstrqi"
5446  [(match_operand:BLK 0 "general_operand" "")
5447   (match_operand:BLK 1 "general_operand" "")
5448   (match_operand:SI 2 "const_int_operand" "")
5449   (match_operand:SI 3 "const_int_operand" "")]
5450  "TARGET_EITHER"
5451  "
5452  if (TARGET_ARM)
5453    {
5454      if (arm_gen_movstrqi (operands))
5455        DONE;
5456      FAIL;
5457    }
5458  else /* TARGET_THUMB */
5459    {
5460      if (   INTVAL (operands[3]) != 4
5461          || INTVAL (operands[2]) > 48)
5462        FAIL;
5463
5464      thumb_expand_movstrqi (operands);
5465      DONE;
5466    }
5467  "
5468)
5469
5470;; Thumb block-move insns
5471
5472(define_insn "movmem12b"
5473  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5474	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5475   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5476	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5477   (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5478	(mem:SI (plus:SI (match_dup 3) (const_int 8))))
5479   (set (match_operand:SI 0 "register_operand" "=l")
5480	(plus:SI (match_dup 2) (const_int 12)))
5481   (set (match_operand:SI 1 "register_operand" "=l")
5482	(plus:SI (match_dup 3) (const_int 12)))
5483   (clobber (match_scratch:SI 4 "=&l"))
5484   (clobber (match_scratch:SI 5 "=&l"))
5485   (clobber (match_scratch:SI 6 "=&l"))]
5486  "TARGET_THUMB"
5487  "* return thumb_output_move_mem_multiple (3, operands);"
5488  [(set_attr "length" "4")
5489   ; This isn't entirely accurate...  It loads as well, but in terms of
5490   ; scheduling the following insn it is better to consider it as a store
5491   (set_attr "type" "store3")]
5492)
5493
5494(define_insn "movmem8b"
5495  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5496	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5497   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5498	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5499   (set (match_operand:SI 0 "register_operand" "=l")
5500	(plus:SI (match_dup 2) (const_int 8)))
5501   (set (match_operand:SI 1 "register_operand" "=l")
5502	(plus:SI (match_dup 3) (const_int 8)))
5503   (clobber (match_scratch:SI 4 "=&l"))
5504   (clobber (match_scratch:SI 5 "=&l"))]
5505  "TARGET_THUMB"
5506  "* return thumb_output_move_mem_multiple (2, operands);"
5507  [(set_attr "length" "4")
5508   ; This isn't entirely accurate...  It loads as well, but in terms of
5509   ; scheduling the following insn it is better to consider it as a store
5510   (set_attr "type" "store2")]
5511)
5512
5513
5514
5515;; Compare & branch insns
5516;; The range calcualations are based as follows:
5517;; For forward branches, the address calculation returns the address of
5518;; the next instruction.  This is 2 beyond the branch instruction.
5519;; For backward branches, the address calculation returns the address of
5520;; the first instruction in this pattern (cmp).  This is 2 before the branch
5521;; instruction for the shortest sequence, and 4 before the branch instruction
5522;; if we have to jump around an unconditional branch.
5523;; To the basic branch range the PC offset must be added (this is +4).
5524;; So for forward branches we have 
5525;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5526;; And for backward branches we have 
5527;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5528;;
5529;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5530;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5531
5532(define_insn "cbranchsi4"
5533  [(set (pc)
5534	(if_then_else
5535	    (match_operator                    0 "arm_comparison_operator"
5536	                    [(match_operand:SI 1 "register_operand"   "l,r")
5537			     (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5538	    (label_ref       (match_operand    3 "" ""))
5539	    (pc)))]
5540  "TARGET_THUMB"
5541  "*
5542  output_asm_insn (\"cmp\\t%1, %2\", operands);
5543  switch (get_attr_length (insn))
5544    {
5545    case 4:  return \"b%d0\\t%l3\";
5546    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5547    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5548    }
5549  "
5550  [(set (attr "far_jump")
5551        (if_then_else
5552	    (eq_attr "length" "8")
5553	    (const_string "yes")
5554            (const_string "no")))
5555   (set (attr "length") 
5556        (if_then_else
5557	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5558	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5559	    (const_int 4)
5560	    (if_then_else
5561	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5562		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5563		(const_int 6)
5564		(const_int 8))))]
5565)
5566
5567(define_insn "*negated_cbranchsi4"
5568  [(set (pc)
5569	(if_then_else
5570	 (match_operator             0 "arm_comparison_operator"
5571	  [(match_operand:SI         1 "register_operand"  "l")
5572	   (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5573	 (label_ref (match_operand   3 "" ""))
5574	 (pc)))]
5575  "TARGET_THUMB"
5576  "*
5577  output_asm_insn (\"cmn\\t%1, %2\", operands);
5578  switch (get_attr_length (insn))
5579    {
5580    case 4:  return \"b%d0\\t%l3\";
5581    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5582    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5583    }
5584  "
5585  [(set (attr "far_jump")
5586        (if_then_else
5587	    (eq_attr "length" "8")
5588	    (const_string "yes")
5589            (const_string "no")))
5590   (set (attr "length") 
5591        (if_then_else
5592	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5593	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5594	    (const_int 4)
5595	    (if_then_else
5596	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5597		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5598		(const_int 6)
5599		(const_int 8))))]
5600)
5601
5602
5603;; Comparison and test insns
5604
5605(define_expand "cmpsi"
5606  [(match_operand:SI 0 "s_register_operand" "")
5607   (match_operand:SI 1 "arm_add_operand" "")]
5608  "TARGET_ARM"
5609  "{
5610    arm_compare_op0 = operands[0];
5611    arm_compare_op1 = operands[1];
5612    DONE;
5613  }"
5614)
5615
5616(define_expand "cmpsf"
5617  [(match_operand:SF 0 "s_register_operand" "")
5618   (match_operand:SF 1 "fpu_rhs_operand" "")]
5619  "TARGET_ARM && TARGET_HARD_FLOAT"
5620  "
5621  arm_compare_op0 = operands[0];
5622  arm_compare_op1 = operands[1];
5623  DONE;
5624  "
5625)
5626
5627(define_expand "cmpdf"
5628  [(match_operand:DF 0 "s_register_operand" "")
5629   (match_operand:DF 1 "fpu_rhs_operand" "")]
5630  "TARGET_ARM && TARGET_HARD_FLOAT"
5631  "
5632  arm_compare_op0 = operands[0];
5633  arm_compare_op1 = operands[1];
5634  DONE;
5635  "
5636)
5637
5638(define_expand "cmpxf"
5639  [(match_operand:XF 0 "s_register_operand" "")
5640   (match_operand:XF 1 "fpu_rhs_operand" "")]
5641  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5642  "
5643  arm_compare_op0 = operands[0];
5644  arm_compare_op1 = operands[1];
5645  DONE;
5646  "
5647)
5648
5649(define_insn "*arm_cmpsi_insn"
5650  [(set (reg:CC CC_REGNUM)
5651	(compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5652		    (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5653  "TARGET_ARM"
5654  "@
5655   cmp%?\\t%0, %1
5656   cmn%?\\t%0, #%n1"
5657  [(set_attr "conds" "set")]
5658)
5659
5660(define_insn "*cmpsi_shiftsi"
5661  [(set (reg:CC CC_REGNUM)
5662	(compare:CC (match_operand:SI   0 "s_register_operand" "r")
5663		    (match_operator:SI  3 "shift_operator"
5664		     [(match_operand:SI 1 "s_register_operand" "r")
5665		      (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5666  "TARGET_ARM"
5667  "cmp%?\\t%0, %1%S3"
5668  [(set_attr "conds" "set")
5669   (set_attr "shift" "1")
5670   ]
5671)
5672
5673(define_insn "*cmpsi_shiftsi_swp"
5674  [(set (reg:CC_SWP CC_REGNUM)
5675	(compare:CC_SWP (match_operator:SI 3 "shift_operator"
5676			 [(match_operand:SI 1 "s_register_operand" "r")
5677			  (match_operand:SI 2 "reg_or_int_operand" "rM")])
5678			(match_operand:SI 0 "s_register_operand" "r")))]
5679  "TARGET_ARM"
5680  "cmp%?\\t%0, %1%S3"
5681  [(set_attr "conds" "set")
5682   (set_attr "shift" "1")
5683   ]
5684)
5685
5686(define_insn "*cmpsi_neg_shiftsi"
5687  [(set (reg:CC CC_REGNUM)
5688	(compare:CC (match_operand:SI 0 "s_register_operand" "r")
5689		    (neg:SI (match_operator:SI 3 "shift_operator"
5690			     [(match_operand:SI 1 "s_register_operand" "r")
5691			      (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5692  "TARGET_ARM"
5693  "cmn%?\\t%0, %1%S3"
5694  [(set_attr "conds" "set")
5695   (set_attr "shift" "1")
5696   ]
5697)
5698
5699(define_insn "*cmpsf_insn"
5700  [(set (reg:CCFP CC_REGNUM)
5701	(compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5702		      (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5703  "TARGET_ARM && TARGET_HARD_FLOAT"
5704  "@
5705   cmf%?\\t%0, %1
5706   cnf%?\\t%0, #%N1"
5707  [(set_attr "conds" "set")
5708   (set_attr "type" "f_2_r")]
5709)
5710
5711(define_insn "*cmpdf_insn"
5712  [(set (reg:CCFP CC_REGNUM)
5713	(compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5714		      (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5715  "TARGET_ARM && TARGET_HARD_FLOAT"
5716  "@
5717   cmf%?\\t%0, %1
5718   cnf%?\\t%0, #%N1"
5719  [(set_attr "conds" "set")
5720   (set_attr "type" "f_2_r")]
5721)
5722
5723(define_insn "*cmpesfdf_df"
5724  [(set (reg:CCFP CC_REGNUM)
5725	(compare:CCFP (float_extend:DF
5726		       (match_operand:SF 0 "s_register_operand" "f,f"))
5727		      (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5728  "TARGET_ARM && TARGET_HARD_FLOAT"
5729  "@
5730   cmf%?\\t%0, %1
5731   cnf%?\\t%0, #%N1"
5732  [(set_attr "conds" "set")
5733   (set_attr "type" "f_2_r")]
5734)
5735
5736(define_insn "*cmpdf_esfdf"
5737  [(set (reg:CCFP CC_REGNUM)
5738	(compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5739		      (float_extend:DF
5740		       (match_operand:SF 1 "s_register_operand" "f"))))]
5741  "TARGET_ARM && TARGET_HARD_FLOAT"
5742  "cmf%?\\t%0, %1"
5743  [(set_attr "conds" "set")
5744   (set_attr "type" "f_2_r")]
5745)
5746
5747(define_insn "*cmpxf_insn"
5748  [(set (reg:CCFP CC_REGNUM)
5749	(compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5750		      (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5751  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5752  "@
5753   cmf%?\\t%0, %1
5754   cnf%?\\t%0, #%N1"
5755  [(set_attr "conds" "set")
5756   (set_attr "type" "f_2_r")]
5757)
5758
5759(define_insn "*cmpsf_trap"
5760  [(set (reg:CCFPE CC_REGNUM)
5761	(compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5762		       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5763  "TARGET_ARM && TARGET_HARD_FLOAT"
5764  "@
5765   cmf%?e\\t%0, %1
5766   cnf%?e\\t%0, #%N1"
5767  [(set_attr "conds" "set")
5768   (set_attr "type" "f_2_r")]
5769)
5770
5771(define_insn "*cmpdf_trap"
5772  [(set (reg:CCFPE CC_REGNUM)
5773	(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5774		       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5775  "TARGET_ARM && TARGET_HARD_FLOAT"
5776  "@
5777   cmf%?e\\t%0, %1
5778   cnf%?e\\t%0, #%N1"
5779  [(set_attr "conds" "set")
5780   (set_attr "type" "f_2_r")]
5781)
5782
5783(define_insn "*cmp_esfdf_df_trap"
5784  [(set (reg:CCFPE CC_REGNUM)
5785	(compare:CCFPE (float_extend:DF
5786			(match_operand:SF 0 "s_register_operand" "f,f"))
5787		       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5788  "TARGET_ARM && TARGET_HARD_FLOAT"
5789  "@
5790   cmf%?e\\t%0, %1
5791   cnf%?e\\t%0, #%N1"
5792  [(set_attr "conds" "set")
5793   (set_attr "type" "f_2_r")]
5794)
5795
5796(define_insn "*cmp_df_esfdf_trap"
5797  [(set (reg:CCFPE CC_REGNUM)
5798	(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5799		       (float_extend:DF
5800			(match_operand:SF 1 "s_register_operand" "f"))))]
5801  "TARGET_ARM && TARGET_HARD_FLOAT"
5802  "cmf%?e\\t%0, %1"
5803  [(set_attr "conds" "set")
5804   (set_attr "type" "f_2_r")]
5805)
5806
5807(define_insn "*cmpxf_trap"
5808  [(set (reg:CCFPE CC_REGNUM)
5809	(compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5810		       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5811  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5812  "@
5813   cmf%?e\\t%0, %1
5814   cnf%?e\\t%0, #%N1"
5815  [(set_attr "conds" "set")
5816   (set_attr "type" "f_2_r")]
5817)
5818
5819; This insn allows redundant compares to be removed by cse, nothing should
5820; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5821; is deleted later on. The match_dup will match the mode here, so that
5822; mode changes of the condition codes aren't lost by this even though we don't
5823; specify what they are.
5824
5825(define_insn "*deleted_compare"
5826  [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5827  "TARGET_ARM"
5828  "\\t%@ deleted compare"
5829  [(set_attr "conds" "set")
5830   (set_attr "length" "0")]
5831)
5832
5833
5834;; Conditional branch insns
5835
5836(define_expand "beq"
5837  [(set (pc)
5838	(if_then_else (eq (match_dup 1) (const_int 0))
5839		      (label_ref (match_operand 0 "" ""))
5840		      (pc)))]
5841  "TARGET_ARM"
5842  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5843)
5844
5845(define_expand "bne"
5846  [(set (pc)
5847	(if_then_else (ne (match_dup 1) (const_int 0))
5848		      (label_ref (match_operand 0 "" ""))
5849		      (pc)))]
5850  "TARGET_ARM"
5851  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5852)
5853
5854(define_expand "bgt"
5855  [(set (pc)
5856	(if_then_else (gt (match_dup 1) (const_int 0))
5857		      (label_ref (match_operand 0 "" ""))
5858		      (pc)))]
5859  "TARGET_ARM"
5860  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5861)
5862
5863(define_expand "ble"
5864  [(set (pc)
5865	(if_then_else (le (match_dup 1) (const_int 0))
5866		      (label_ref (match_operand 0 "" ""))
5867		      (pc)))]
5868  "TARGET_ARM"
5869  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5870)
5871
5872(define_expand "bge"
5873  [(set (pc)
5874	(if_then_else (ge (match_dup 1) (const_int 0))
5875		      (label_ref (match_operand 0 "" ""))
5876		      (pc)))]
5877  "TARGET_ARM"
5878  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5879)
5880
5881(define_expand "blt"
5882  [(set (pc)
5883	(if_then_else (lt (match_dup 1) (const_int 0))
5884		      (label_ref (match_operand 0 "" ""))
5885		      (pc)))]
5886  "TARGET_ARM"
5887  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5888)
5889
5890(define_expand "bgtu"
5891  [(set (pc)
5892	(if_then_else (gtu (match_dup 1) (const_int 0))
5893		      (label_ref (match_operand 0 "" ""))
5894		      (pc)))]
5895  "TARGET_ARM"
5896  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5897)
5898
5899(define_expand "bleu"
5900  [(set (pc)
5901	(if_then_else (leu (match_dup 1) (const_int 0))
5902		      (label_ref (match_operand 0 "" ""))
5903		      (pc)))]
5904  "TARGET_ARM"
5905  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5906)
5907
5908(define_expand "bgeu"
5909  [(set (pc)
5910	(if_then_else (geu (match_dup 1) (const_int 0))
5911		      (label_ref (match_operand 0 "" ""))
5912		      (pc)))]
5913  "TARGET_ARM"
5914  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5915)
5916
5917(define_expand "bltu"
5918  [(set (pc)
5919	(if_then_else (ltu (match_dup 1) (const_int 0))
5920		      (label_ref (match_operand 0 "" ""))
5921		      (pc)))]
5922  "TARGET_ARM"
5923  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5924)
5925
5926(define_expand "bunordered"
5927  [(set (pc)
5928	(if_then_else (unordered (match_dup 1) (const_int 0))
5929		      (label_ref (match_operand 0 "" ""))
5930		      (pc)))]
5931  "TARGET_ARM && TARGET_HARD_FLOAT"
5932  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5933				      arm_compare_op1);"
5934)
5935
5936(define_expand "bordered"
5937  [(set (pc)
5938	(if_then_else (ordered (match_dup 1) (const_int 0))
5939		      (label_ref (match_operand 0 "" ""))
5940		      (pc)))]
5941  "TARGET_ARM && TARGET_HARD_FLOAT"
5942  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5943				      arm_compare_op1);"
5944)
5945
5946(define_expand "bungt"
5947  [(set (pc)
5948	(if_then_else (ungt (match_dup 1) (const_int 0))
5949		      (label_ref (match_operand 0 "" ""))
5950		      (pc)))]
5951  "TARGET_ARM && TARGET_HARD_FLOAT"
5952  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5953)
5954
5955(define_expand "bunlt"
5956  [(set (pc)
5957	(if_then_else (unlt (match_dup 1) (const_int 0))
5958		      (label_ref (match_operand 0 "" ""))
5959		      (pc)))]
5960  "TARGET_ARM && TARGET_HARD_FLOAT"
5961  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5962)
5963
5964(define_expand "bunge"
5965  [(set (pc)
5966	(if_then_else (unge (match_dup 1) (const_int 0))
5967		      (label_ref (match_operand 0 "" ""))
5968		      (pc)))]
5969  "TARGET_ARM && TARGET_HARD_FLOAT"
5970  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5971)
5972
5973(define_expand "bunle"
5974  [(set (pc)
5975	(if_then_else (unle (match_dup 1) (const_int 0))
5976		      (label_ref (match_operand 0 "" ""))
5977		      (pc)))]
5978  "TARGET_ARM && TARGET_HARD_FLOAT"
5979  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5980)
5981
5982;; The following two patterns need two branch instructions, since there is
5983;; no single instruction that will handle all cases.
5984(define_expand "buneq"
5985  [(set (pc)
5986	(if_then_else (uneq (match_dup 1) (const_int 0))
5987		      (label_ref (match_operand 0 "" ""))
5988		      (pc)))]
5989  "TARGET_ARM && TARGET_HARD_FLOAT"
5990  "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5991)
5992
5993(define_expand "bltgt"
5994  [(set (pc)
5995	(if_then_else (ltgt (match_dup 1) (const_int 0))
5996		      (label_ref (match_operand 0 "" ""))
5997		      (pc)))]
5998  "TARGET_ARM && TARGET_HARD_FLOAT"
5999  "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6000)
6001
6002;;
6003;; Patterns to match conditional branch insns.
6004;;
6005
6006; Special pattern to match UNEQ.
6007(define_insn "*arm_buneq"
6008  [(set (pc)
6009	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6010		      (label_ref (match_operand 0 "" ""))
6011		      (pc)))]
6012  "TARGET_ARM && TARGET_HARD_FLOAT"
6013  "*
6014  if (arm_ccfsm_state != 0)
6015    abort ();
6016
6017  return \"bvs\\t%l0;beq\\t%l0\";
6018  "
6019  [(set_attr "conds" "jump_clob")
6020   (set_attr "length" "8")]
6021)
6022
6023; Special pattern to match LTGT.
6024(define_insn "*arm_bltgt"
6025  [(set (pc)
6026	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6027		      (label_ref (match_operand 0 "" ""))
6028		      (pc)))]
6029  "TARGET_ARM && TARGET_HARD_FLOAT"
6030  "*
6031  if (arm_ccfsm_state != 0)
6032    abort ();
6033
6034  return \"bmi\\t%l0;bgt\\t%l0\";
6035  "
6036  [(set_attr "conds" "jump_clob")
6037   (set_attr "length" "8")]
6038)
6039
6040(define_insn "*arm_cond_branch"
6041  [(set (pc)
6042	(if_then_else (match_operator 1 "arm_comparison_operator"
6043		       [(match_operand 2 "cc_register" "") (const_int 0)])
6044		      (label_ref (match_operand 0 "" ""))
6045		      (pc)))]
6046  "TARGET_ARM"
6047  "*
6048  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6049    {
6050      arm_ccfsm_state += 2;
6051      return \"\";
6052    }
6053  return \"b%d1\\t%l0\";
6054  "
6055  [(set_attr "conds" "use")]
6056)
6057
6058; Special pattern to match reversed UNEQ.
6059(define_insn "*arm_buneq_reversed"
6060  [(set (pc)
6061	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6062		      (pc)
6063		      (label_ref (match_operand 0 "" ""))))]
6064  "TARGET_ARM && TARGET_HARD_FLOAT"
6065  "*
6066  if (arm_ccfsm_state != 0)
6067    abort ();
6068
6069  return \"bmi\\t%l0;bgt\\t%l0\";
6070  "
6071  [(set_attr "conds" "jump_clob")
6072   (set_attr "length" "8")]
6073)
6074
6075; Special pattern to match reversed LTGT.
6076(define_insn "*arm_bltgt_reversed"
6077  [(set (pc)
6078	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6079		      (pc)
6080		      (label_ref (match_operand 0 "" ""))))]
6081  "TARGET_ARM && TARGET_HARD_FLOAT"
6082  "*
6083  if (arm_ccfsm_state != 0)
6084    abort ();
6085
6086  return \"bvs\\t%l0;beq\\t%l0\";
6087  "
6088  [(set_attr "conds" "jump_clob")
6089   (set_attr "length" "8")]
6090)
6091
6092(define_insn "*arm_cond_branch_reversed"
6093  [(set (pc)
6094	(if_then_else (match_operator 1 "arm_comparison_operator"
6095		       [(match_operand 2 "cc_register" "") (const_int 0)])
6096		      (pc)
6097		      (label_ref (match_operand 0 "" ""))))]
6098  "TARGET_ARM"
6099  "*
6100  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6101    {
6102      arm_ccfsm_state += 2;
6103      return \"\";
6104    }
6105  return \"b%D1\\t%l0\";
6106  "
6107  [(set_attr "conds" "use")]
6108)
6109
6110
6111
6112; scc insns
6113
6114(define_expand "seq"
6115  [(set (match_operand:SI 0 "s_register_operand" "=r")
6116	(eq:SI (match_dup 1) (const_int 0)))]
6117  "TARGET_ARM"
6118  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6119)
6120
6121(define_expand "sne"
6122  [(set (match_operand:SI 0 "s_register_operand" "=r")
6123	(ne:SI (match_dup 1) (const_int 0)))]
6124  "TARGET_ARM"
6125  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6126)
6127
6128(define_expand "sgt"
6129  [(set (match_operand:SI 0 "s_register_operand" "=r")
6130	(gt:SI (match_dup 1) (const_int 0)))]
6131  "TARGET_ARM"
6132  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6133)
6134
6135(define_expand "sle"
6136  [(set (match_operand:SI 0 "s_register_operand" "=r")
6137	(le:SI (match_dup 1) (const_int 0)))]
6138  "TARGET_ARM"
6139  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6140)
6141
6142(define_expand "sge"
6143  [(set (match_operand:SI 0 "s_register_operand" "=r")
6144	(ge:SI (match_dup 1) (const_int 0)))]
6145  "TARGET_ARM"
6146  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6147)
6148
6149(define_expand "slt"
6150  [(set (match_operand:SI 0 "s_register_operand" "=r")
6151	(lt:SI (match_dup 1) (const_int 0)))]
6152  "TARGET_ARM"
6153  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6154)
6155
6156(define_expand "sgtu"
6157  [(set (match_operand:SI 0 "s_register_operand" "=r")
6158	(gtu:SI (match_dup 1) (const_int 0)))]
6159  "TARGET_ARM"
6160  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6161)
6162
6163(define_expand "sleu"
6164  [(set (match_operand:SI 0 "s_register_operand" "=r")
6165	(leu:SI (match_dup 1) (const_int 0)))]
6166  "TARGET_ARM"
6167  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6168)
6169
6170(define_expand "sgeu"
6171  [(set (match_operand:SI 0 "s_register_operand" "=r")
6172	(geu:SI (match_dup 1) (const_int 0)))]
6173  "TARGET_ARM"
6174  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6175)
6176
6177(define_expand "sltu"
6178  [(set (match_operand:SI 0 "s_register_operand" "=r")
6179	(ltu:SI (match_dup 1) (const_int 0)))]
6180  "TARGET_ARM"
6181  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6182)
6183
6184(define_expand "sunordered"
6185  [(set (match_operand:SI 0 "s_register_operand" "=r")
6186	(unordered:SI (match_dup 1) (const_int 0)))]
6187  "TARGET_ARM && TARGET_HARD_FLOAT"
6188  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6189				      arm_compare_op1);"
6190)
6191
6192(define_expand "sordered"
6193  [(set (match_operand:SI 0 "s_register_operand" "=r")
6194	(ordered:SI (match_dup 1) (const_int 0)))]
6195  "TARGET_ARM && TARGET_HARD_FLOAT"
6196  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6197				      arm_compare_op1);"
6198)
6199
6200(define_expand "sungt"
6201  [(set (match_operand:SI 0 "s_register_operand" "=r")
6202	(ungt:SI (match_dup 1) (const_int 0)))]
6203  "TARGET_ARM && TARGET_HARD_FLOAT"
6204  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6205				      arm_compare_op1);"
6206)
6207
6208(define_expand "sunge"
6209  [(set (match_operand:SI 0 "s_register_operand" "=r")
6210	(unge:SI (match_dup 1) (const_int 0)))]
6211  "TARGET_ARM && TARGET_HARD_FLOAT"
6212  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6213				      arm_compare_op1);"
6214)
6215
6216(define_expand "sunlt"
6217  [(set (match_operand:SI 0 "s_register_operand" "=r")
6218	(unlt:SI (match_dup 1) (const_int 0)))]
6219  "TARGET_ARM && TARGET_HARD_FLOAT"
6220  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6221				      arm_compare_op1);"
6222)
6223
6224(define_expand "sunle"
6225  [(set (match_operand:SI 0 "s_register_operand" "=r")
6226	(unle:SI (match_dup 1) (const_int 0)))]
6227  "TARGET_ARM && TARGET_HARD_FLOAT"
6228  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6229				      arm_compare_op1);"
6230)
6231
6232;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6233;;; simple ARM instructions. 
6234;
6235; (define_expand "suneq"
6236;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6237; 	(uneq:SI (match_dup 1) (const_int 0)))]
6238;   "TARGET_ARM && TARGET_HARD_FLOAT"
6239;   "abort ();"
6240; )
6241;
6242; (define_expand "sltgt"
6243;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6244; 	(ltgt:SI (match_dup 1) (const_int 0)))]
6245;   "TARGET_ARM && TARGET_HARD_FLOAT"
6246;   "abort ();"
6247; )
6248
6249(define_insn "*mov_scc"
6250  [(set (match_operand:SI 0 "s_register_operand" "=r")
6251	(match_operator:SI 1 "arm_comparison_operator"
6252	 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6253  "TARGET_ARM"
6254  "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6255  [(set_attr "conds" "use")
6256   (set_attr "length" "8")]
6257)
6258
6259(define_insn "*mov_negscc"
6260  [(set (match_operand:SI 0 "s_register_operand" "=r")
6261	(neg:SI (match_operator:SI 1 "arm_comparison_operator"
6262		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6263  "TARGET_ARM"
6264  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6265  [(set_attr "conds" "use")
6266   (set_attr "length" "8")]
6267)
6268
6269(define_insn "*mov_notscc"
6270  [(set (match_operand:SI 0 "s_register_operand" "=r")
6271	(not:SI (match_operator:SI 1 "arm_comparison_operator"
6272		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6273  "TARGET_ARM"
6274  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6275  [(set_attr "conds" "use")
6276   (set_attr "length" "8")]
6277)
6278
6279
6280;; Conditional move insns
6281
6282(define_expand "movsicc"
6283  [(set (match_operand:SI 0 "s_register_operand" "")
6284	(if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6285			 (match_operand:SI 2 "arm_not_operand" "")
6286			 (match_operand:SI 3 "arm_not_operand" "")))]
6287  "TARGET_ARM"
6288  "
6289  {
6290    enum rtx_code code = GET_CODE (operands[1]);
6291    rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6292
6293    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6294  }"
6295)
6296
6297(define_expand "movsfcc"
6298  [(set (match_operand:SF 0 "s_register_operand" "")
6299	(if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6300			 (match_operand:SF 2 "s_register_operand" "")
6301			 (match_operand:SF 3 "nonmemory_operand" "")))]
6302  "TARGET_ARM"
6303  "
6304  {
6305    enum rtx_code code = GET_CODE (operands[1]);
6306    rtx ccreg;
6307
6308    /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6309       Otherwise, ensure it is a valid FP add operand */
6310    if ((!TARGET_HARD_FLOAT)
6311        || (!fpu_add_operand (operands[3], SFmode)))
6312      operands[3] = force_reg (SFmode, operands[3]);
6313
6314    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6315    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6316  }"
6317)
6318
6319(define_expand "movdfcc"
6320  [(set (match_operand:DF 0 "s_register_operand" "")
6321	(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6322			 (match_operand:DF 2 "s_register_operand" "")
6323			 (match_operand:DF 3 "fpu_add_operand" "")))]
6324  "TARGET_ARM && TARGET_HARD_FLOAT"
6325  "
6326  {
6327    enum rtx_code code = GET_CODE (operands[1]);
6328    rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6329
6330    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6331  }"
6332)
6333
6334(define_insn "*movsicc_insn"
6335  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6336	(if_then_else:SI
6337	 (match_operator 3 "arm_comparison_operator"
6338	  [(match_operand 4 "cc_register" "") (const_int 0)])
6339	 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6340	 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6341  "TARGET_ARM"
6342  "@
6343   mov%D3\\t%0, %2
6344   mvn%D3\\t%0, #%B2
6345   mov%d3\\t%0, %1
6346   mvn%d3\\t%0, #%B1
6347   mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6348   mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6349   mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6350   mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6351  [(set_attr "length" "4,4,4,4,8,8,8,8")
6352   (set_attr "conds" "use")]
6353)
6354
6355(define_insn "*movsfcc_hard_insn"
6356  [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6357	(if_then_else:SF
6358	 (match_operator 3 "arm_comparison_operator" 
6359	  [(match_operand 4 "cc_register" "") (const_int 0)])
6360	 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6361	 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6362  "TARGET_ARM && TARGET_HARD_FLOAT"
6363  "@
6364   mvf%D3s\\t%0, %2
6365   mnf%D3s\\t%0, #%N2
6366   mvf%d3s\\t%0, %1
6367   mnf%d3s\\t%0, #%N1
6368   mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6369   mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6370   mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6371   mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6372  [(set_attr "length" "4,4,4,4,8,8,8,8")
6373   (set_attr "type" "ffarith")
6374   (set_attr "conds" "use")]
6375)
6376
6377(define_insn "*movsfcc_soft_insn"
6378  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6379	(if_then_else:SF (match_operator 3 "arm_comparison_operator"
6380			  [(match_operand 4 "cc_register" "") (const_int 0)])
6381			 (match_operand:SF 1 "s_register_operand" "0,r")
6382			 (match_operand:SF 2 "s_register_operand" "r,0")))]
6383  "TARGET_ARM && TARGET_SOFT_FLOAT"
6384  "@
6385   mov%D3\\t%0, %2
6386   mov%d3\\t%0, %1"
6387  [(set_attr "conds" "use")]
6388)
6389
6390(define_insn "*movdfcc_insn"
6391  [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6392	(if_then_else:DF
6393	 (match_operator 3 "arm_comparison_operator"
6394	  [(match_operand 4 "cc_register" "") (const_int 0)])
6395	 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6396	 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6397  "TARGET_ARM && TARGET_HARD_FLOAT"
6398  "@
6399   mvf%D3d\\t%0, %2
6400   mnf%D3d\\t%0, #%N2
6401   mvf%d3d\\t%0, %1
6402   mnf%d3d\\t%0, #%N1
6403   mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6404   mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6405   mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6406   mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6407  [(set_attr "length" "4,4,4,4,8,8,8,8")
6408   (set_attr "type" "ffarith")
6409   (set_attr "conds" "use")]
6410)
6411
6412
6413;; Jump and linkage insns
6414
6415(define_expand "jump"
6416  [(set (pc)
6417	(label_ref (match_operand 0 "" "")))]
6418  "TARGET_EITHER"
6419  ""
6420)
6421
6422(define_insn "*arm_jump"
6423  [(set (pc)
6424	(label_ref (match_operand 0 "" "")))]
6425  "TARGET_ARM"
6426  "*
6427  {
6428    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6429      {
6430        arm_ccfsm_state += 2;
6431        return \"\";
6432      }
6433    return \"b%?\\t%l0\";
6434  }
6435  "
6436  [(set_attr "predicable" "yes")]
6437)
6438
6439(define_insn "*thumb_jump"
6440  [(set (pc)
6441	(label_ref (match_operand 0 "" "")))]
6442  "TARGET_THUMB"
6443  "*
6444  if (get_attr_length (insn) == 2)
6445    return \"b\\t%l0\";
6446  return \"bl\\t%l0\\t%@ far jump\";
6447  "
6448  [(set (attr "far_jump")
6449        (if_then_else
6450	    (eq_attr "length" "4")
6451	    (const_string "yes")
6452	    (const_string "no")))
6453   (set (attr "length") 
6454        (if_then_else
6455	    (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6456		 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6457  	    (const_int 2)
6458	    (const_int 4)))]
6459)
6460
6461(define_expand "call"
6462  [(parallel [(call (match_operand 0 "memory_operand" "")
6463	            (match_operand 1 "general_operand" ""))
6464	      (use (match_operand 2 "" ""))
6465	      (clobber (reg:SI LR_REGNUM))])]
6466  "TARGET_EITHER"
6467  "
6468  {
6469    rtx callee;
6470    
6471    /* In an untyped call, we can get NULL for operand 2.  */
6472    if (operands[2] == NULL_RTX)
6473      operands[2] = const0_rtx;
6474      
6475    /* This is to decide if we should generate indirect calls by loading the
6476       32 bit address of the callee into a register before performing the
6477       branch and link.  operand[2] encodes the long_call/short_call
6478       attribute of the function being called.  This attribute is set whenever
6479       __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6480       is used, and the short_call attribute can also be set if function is
6481       declared as static or if it has already been defined in the current
6482       compilation unit.  See arm.c and arm.h for info about this.  The third
6483       parameter to arm_is_longcall_p is used to tell it which pattern
6484       invoked it.  */
6485    callee  = XEXP (operands[0], 0);
6486    
6487    if (GET_CODE (callee) != REG
6488       && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6489      XEXP (operands[0], 0) = force_reg (Pmode, callee);
6490  }"
6491)
6492
6493(define_insn "*call_reg"
6494  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6495         (match_operand 1 "" ""))
6496   (use (match_operand 2 "" ""))
6497   (clobber (reg:SI LR_REGNUM))]
6498  "TARGET_ARM"
6499  "*
6500  return output_call (operands);
6501  "
6502  ;; length is worst case, normally it is only two
6503  [(set_attr "length" "12")
6504   (set_attr "type" "call")]
6505)
6506
6507(define_insn "*call_mem"
6508  [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6509	 (match_operand 1 "" ""))
6510   (use (match_operand 2 "" ""))
6511   (clobber (reg:SI LR_REGNUM))]
6512  "TARGET_ARM"
6513  "*
6514  return output_call_mem (operands);
6515  "
6516  [(set_attr "length" "12")
6517   (set_attr "type" "call")]
6518)
6519
6520(define_insn "*call_indirect"
6521  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6522	 (match_operand 1 "" ""))
6523   (use (match_operand 2 "" ""))
6524   (clobber (reg:SI LR_REGNUM))]
6525  "TARGET_THUMB"
6526  "*
6527  {
6528    if (TARGET_CALLER_INTERWORKING)
6529      return \"bl\\t%__interwork_call_via_%0\";
6530    else
6531      return \"bl\\t%__call_via_%0\";
6532  }"
6533  [(set_attr "type" "call")]
6534)
6535
6536(define_insn "*call_value_indirect"
6537  [(set (match_operand 0 "" "=l")
6538	(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6539	      (match_operand 2 "" "")))
6540   (use (match_operand 3 "" ""))
6541   (clobber (reg:SI LR_REGNUM))]
6542  "TARGET_THUMB"
6543  "*
6544  {
6545    if (TARGET_CALLER_INTERWORKING)
6546      return \"bl\\t%__interwork_call_via_%1\";
6547    else
6548      return \"bl\\t%__call_via_%1\";
6549  }"
6550  [(set_attr "type" "call")]
6551)
6552
6553(define_expand "call_value"
6554  [(parallel [(set (match_operand       0 "" "")
6555	           (call (match_operand 1 "memory_operand" "")
6556		         (match_operand 2 "general_operand" "")))
6557	      (use (match_operand 3 "" ""))
6558	      (clobber (reg:SI LR_REGNUM))])]
6559  "TARGET_EITHER"
6560  "
6561  {
6562    rtx callee = XEXP (operands[1], 0);
6563    
6564    /* In an untyped call, we can get NULL for operand 2.  */
6565    if (operands[3] == 0)
6566      operands[3] = const0_rtx;
6567      
6568    /* See the comment in define_expand \"call\".  */
6569    if (GET_CODE (callee) != REG
6570	&& arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6571      XEXP (operands[1], 0) = force_reg (Pmode, callee);
6572  }"
6573)
6574
6575(define_insn "*call_value_reg"
6576  [(set (match_operand 0 "" "=r,f")
6577        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6578	      (match_operand 2 "" "")))
6579   (use (match_operand 3 "" ""))
6580   (clobber (reg:SI LR_REGNUM))]
6581  "TARGET_ARM"
6582  "*
6583  return output_call (&operands[1]);
6584  "
6585  [(set_attr "length" "12")
6586   (set_attr "type" "call")]
6587)
6588
6589(define_insn "*call_value_mem"
6590  [(set (match_operand 0 "" "=r,f")
6591	(call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6592	      (match_operand 2 "" "")))
6593   (use (match_operand 3 "" ""))
6594   (clobber (reg:SI LR_REGNUM))]
6595  "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6596  "*
6597  return output_call_mem (&operands[1]);
6598  "
6599  [(set_attr "length" "12")
6600   (set_attr "type" "call")]
6601)
6602
6603;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6604;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6605
6606(define_insn "*call_symbol"
6607  [(call (mem:SI (match_operand:SI 0 "" "X"))
6608	 (match_operand 1 "" ""))
6609   (use (match_operand 2 "" ""))
6610   (clobber (reg:SI LR_REGNUM))]
6611  "TARGET_ARM
6612   && (GET_CODE (operands[0]) == SYMBOL_REF)
6613   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6614  "*
6615  {
6616    return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6617  }"
6618  [(set_attr "type" "call")]
6619)
6620
6621(define_insn "*call_value_symbol"
6622  [(set (match_operand 0 "s_register_operand" "=r,f")
6623	(call (mem:SI (match_operand:SI 1 "" "X,X"))
6624	(match_operand:SI 2 "" "")))
6625   (use (match_operand 3 "" ""))
6626   (clobber (reg:SI LR_REGNUM))]
6627  "TARGET_ARM
6628   && (GET_CODE (operands[1]) == SYMBOL_REF)
6629   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6630  "*
6631  {
6632    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6633  }"
6634  [(set_attr "type" "call")]
6635)
6636
6637(define_insn "*call_insn"
6638  [(call (mem:SI (match_operand:SI 0 "" "X"))
6639	 (match_operand:SI 1 "" ""))
6640   (use (match_operand 2 "" ""))
6641   (clobber (reg:SI LR_REGNUM))]
6642  "TARGET_THUMB
6643   && GET_CODE (operands[0]) == SYMBOL_REF
6644   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6645  "bl\\t%a0"
6646  [(set_attr "length" "4")
6647   (set_attr "type" "call")]
6648)
6649
6650(define_insn "*call_value_insn"
6651  [(set (match_operand 0 "register_operand" "=l")
6652	(call (mem:SI (match_operand 1 "" "X"))
6653	      (match_operand 2 "" "")))
6654   (use (match_operand 3 "" ""))
6655   (clobber (reg:SI LR_REGNUM))]
6656  "TARGET_THUMB
6657   && GET_CODE (operands[1]) == SYMBOL_REF
6658   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6659  "bl\\t%a1"
6660  [(set_attr "length" "4")
6661   (set_attr "type" "call")]
6662)
6663
6664;; We may also be able to do sibcalls for Thumb, but it's much harder...
6665(define_expand "sibcall"
6666  [(parallel [(call (match_operand 0 "memory_operand" "")
6667		    (match_operand 1 "general_operand" ""))
6668	      (use (match_operand 2 "" ""))
6669	      (use (reg:SI LR_REGNUM))])]
6670  "TARGET_ARM"
6671  "
6672  {
6673    if (operands[2] == NULL_RTX)
6674      operands[2] = const0_rtx;
6675  }"
6676)
6677
6678(define_expand "sibcall_value"
6679  [(parallel [(set (match_operand 0 "register_operand" "")
6680		   (call (match_operand 1 "memory_operand" "")
6681			 (match_operand 2 "general_operand" "")))
6682	      (use (match_operand 3 "" ""))
6683	      (use (reg:SI LR_REGNUM))])]
6684  "TARGET_ARM"
6685  "
6686  {
6687    if (operands[3] == NULL_RTX)
6688      operands[3] = const0_rtx;
6689  }"
6690)
6691
6692(define_insn "*sibcall_insn"
6693 [(call (mem:SI (match_operand:SI 0 "" "X"))
6694	(match_operand 1 "" ""))
6695  (use (match_operand 2 "" ""))
6696  (use (reg:SI LR_REGNUM))]
6697  "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6698  "*
6699  return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6700  "
6701  [(set_attr "type" "call")]
6702)
6703
6704(define_insn "*sibcall_value_insn"
6705 [(set (match_operand 0 "s_register_operand" "=r,f")
6706       (call (mem:SI (match_operand:SI 1 "" "X,X"))
6707	     (match_operand 2 "" "")))
6708  (use (match_operand 3 "" ""))
6709  (use (reg:SI LR_REGNUM))]
6710  "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6711  "*
6712  return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6713  "
6714  [(set_attr "type" "call")]
6715)
6716
6717;; Often the return insn will be the same as loading from memory, so set attr
6718(define_insn "return"
6719  [(return)]
6720  "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6721  "*
6722  {
6723    if (arm_ccfsm_state == 2)
6724      {
6725        arm_ccfsm_state += 2;
6726        return \"\";
6727      }
6728    return output_return_instruction (NULL, TRUE, FALSE);
6729  }"
6730  [(set_attr "type" "load")
6731   (set_attr "predicable" "yes")]
6732)
6733
6734(define_insn "*cond_return"
6735  [(set (pc)
6736        (if_then_else (match_operator 0 "arm_comparison_operator"
6737		       [(match_operand 1 "cc_register" "") (const_int 0)])
6738                      (return)
6739                      (pc)))]
6740  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6741  "*
6742  {
6743    if (arm_ccfsm_state == 2)
6744      {
6745        arm_ccfsm_state += 2;
6746        return \"\";
6747      }
6748    return output_return_instruction (operands[0], TRUE, FALSE);
6749  }"
6750  [(set_attr "conds" "use")
6751   (set_attr "type" "load")]
6752)
6753
6754(define_insn "*cond_return_inverted"
6755  [(set (pc)
6756        (if_then_else (match_operator 0 "arm_comparison_operator"
6757		       [(match_operand 1 "cc_register" "") (const_int 0)])
6758                      (pc)
6759		      (return)))]
6760  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6761  "*
6762  {
6763    if (arm_ccfsm_state == 2)
6764      {
6765        arm_ccfsm_state += 2;
6766        return \"\";
6767      }
6768    return output_return_instruction (operands[0], TRUE, TRUE);
6769  }"
6770  [(set_attr "conds" "use")
6771   (set_attr "type" "load")]
6772)
6773
6774;; Call subroutine returning any type.
6775
6776(define_expand "untyped_call"
6777  [(parallel [(call (match_operand 0 "" "")
6778		    (const_int 0))
6779	      (match_operand 1 "" "")
6780	      (match_operand 2 "" "")])]
6781  "TARGET_ARM"
6782  "
6783  {
6784    int i;
6785
6786    emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6787
6788    for (i = 0; i < XVECLEN (operands[2], 0); i++)
6789      {
6790	rtx set = XVECEXP (operands[2], 0, i);
6791
6792	emit_move_insn (SET_DEST (set), SET_SRC (set));
6793      }
6794
6795    /* The optimizer does not know that the call sets the function value
6796       registers we stored in the result block.  We avoid problems by
6797       claiming that all hard registers are used and clobbered at this
6798       point.  */
6799    emit_insn (gen_blockage ());
6800
6801    DONE;
6802  }"
6803)
6804
6805;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6806;; all of memory.  This blocks insns from being moved across this point.
6807
6808(define_insn "blockage"
6809  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6810  "TARGET_EITHER"
6811  ""
6812  [(set_attr "length" "0")
6813   (set_attr "type" "block")]
6814)
6815
6816(define_expand "casesi"
6817  [(match_operand:SI 0 "s_register_operand" "")	; index to jump on
6818   (match_operand:SI 1 "const_int_operand" "")	; lower bound
6819   (match_operand:SI 2 "const_int_operand" "")	; total range
6820   (match_operand:SI 3 "" "")			; table label
6821   (match_operand:SI 4 "" "")]			; Out of range label
6822  "TARGET_ARM"
6823  "
6824  {
6825    rtx reg;
6826    if (operands[1] != const0_rtx)
6827      {
6828	reg = gen_reg_rtx (SImode);
6829
6830	emit_insn (gen_addsi3 (reg, operands[0],
6831			       GEN_INT (-INTVAL (operands[1]))));
6832	operands[0] = reg;
6833      }
6834
6835    if (!const_ok_for_arm (INTVAL (operands[2])))
6836      operands[2] = force_reg (SImode, operands[2]);
6837
6838    emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6839					 operands[4]));
6840    DONE;
6841  }"
6842)
6843
6844;; The USE in this pattern is needed to tell flow analysis that this is
6845;; a CASESI insn.  It has no other purpose.
6846(define_insn "casesi_internal"
6847  [(parallel [(set (pc)
6848	       (if_then_else
6849		(leu (match_operand:SI 0 "s_register_operand" "r")
6850		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
6851		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6852				 (label_ref (match_operand 2 "" ""))))
6853		(label_ref (match_operand 3 "" ""))))
6854	      (clobber (reg:CC CC_REGNUM))
6855	      (use (label_ref (match_dup 2)))])]
6856  "TARGET_ARM"
6857  "*
6858    if (flag_pic)
6859      return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6860    return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6861  "
6862  [(set_attr "conds" "clob")
6863   (set_attr "length" "12")]
6864)
6865
6866(define_expand "indirect_jump"
6867  [(set (pc)
6868	(match_operand:SI 0 "s_register_operand" ""))]
6869  "TARGET_EITHER"
6870  ""
6871)
6872
6873(define_insn "*arm_indirect_jump"
6874  [(set (pc)
6875	(match_operand:SI 0 "s_register_operand" "r"))]
6876  "TARGET_ARM"
6877  "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6878  [(set_attr "predicable" "yes")]
6879)
6880
6881;; Although not supported by the define_expand above,
6882;; cse/combine may generate this form.
6883(define_insn "*load_indirect_jump"
6884  [(set (pc)
6885	(match_operand:SI 0 "memory_operand" "m"))]
6886  "TARGET_ARM"
6887  "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6888  [(set_attr "type" "load")
6889   (set_attr "pool_range" "4096")
6890   (set_attr "neg_pool_range" "4084")
6891   (set_attr "predicable" "yes")]
6892)
6893
6894(define_insn "*thumb_indirect_jump"
6895  [(set (pc)
6896	(match_operand:SI 0 "register_operand" "l*r"))]
6897  "TARGET_THUMB"
6898  "mov\\tpc, %0"
6899  [(set_attr "conds" "clob")
6900   (set_attr "length" "2")]
6901)
6902
6903
6904;; Misc insns
6905
6906(define_insn "nop"
6907  [(const_int 0)]
6908  "TARGET_EITHER"
6909  "*
6910  if (TARGET_ARM)
6911    return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6912  return  \"mov\\tr8, r8\";
6913  "
6914  [(set (attr "length")
6915	(if_then_else (eq_attr "is_thumb" "yes")
6916		      (const_int 2)
6917		      (const_int 4)))]
6918)
6919
6920
6921;; Patterns to allow combination of arithmetic, cond code and shifts
6922
6923(define_insn "*arith_shiftsi"
6924  [(set (match_operand:SI 0 "s_register_operand" "=r")
6925        (match_operator:SI 1 "shiftable_operator"
6926          [(match_operator:SI 3 "shift_operator"
6927             [(match_operand:SI 4 "s_register_operand" "r")
6928              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6929           (match_operand:SI 2 "s_register_operand" "r")]))]
6930  "TARGET_ARM"
6931  "%i1%?\\t%0, %2, %4%S3"
6932  [(set_attr "predicable" "yes")
6933   (set_attr "shift" "4")
6934   ]
6935)
6936
6937(define_insn "*arith_shiftsi_compare0"
6938  [(set (reg:CC_NOOV CC_REGNUM)
6939        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6940		          [(match_operator:SI 3 "shift_operator"
6941		            [(match_operand:SI 4 "s_register_operand" "r")
6942		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
6943		           (match_operand:SI 2 "s_register_operand" "r")])
6944			 (const_int 0)))
6945   (set (match_operand:SI 0 "s_register_operand" "=r")
6946	(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6947			 (match_dup 2)]))]
6948  "TARGET_ARM"
6949  "%i1%?s\\t%0, %2, %4%S3"
6950  [(set_attr "conds" "set")
6951   (set_attr "shift" "4")
6952   ]
6953)
6954
6955(define_insn "*arith_shiftsi_compare0_scratch"
6956  [(set (reg:CC_NOOV CC_REGNUM)
6957        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6958		          [(match_operator:SI 3 "shift_operator"
6959		            [(match_operand:SI 4 "s_register_operand" "r")
6960		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
6961		           (match_operand:SI 2 "s_register_operand" "r")])
6962			 (const_int 0)))
6963   (clobber (match_scratch:SI 0 "=r"))]
6964  "TARGET_ARM"
6965  "%i1%?s\\t%0, %2, %4%S3"
6966  [(set_attr "conds" "set")
6967   (set_attr "shift" "4")
6968   ]
6969)
6970
6971(define_insn "*sub_shiftsi"
6972  [(set (match_operand:SI 0 "s_register_operand" "=r")
6973	(minus:SI (match_operand:SI 1 "s_register_operand" "r")
6974		  (match_operator:SI 2 "shift_operator"
6975		   [(match_operand:SI 3 "s_register_operand" "r")
6976		    (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6977  "TARGET_ARM"
6978  "sub%?\\t%0, %1, %3%S2"
6979  [(set_attr "predicable" "yes")
6980   (set_attr "shift" "3")
6981   ]
6982)
6983
6984(define_insn "*sub_shiftsi_compare0"
6985  [(set (reg:CC_NOOV CC_REGNUM)
6986	(compare:CC_NOOV
6987	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6988		   (match_operator:SI 2 "shift_operator"
6989		    [(match_operand:SI 3 "s_register_operand" "r")
6990		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6991	 (const_int 0)))
6992   (set (match_operand:SI 0 "s_register_operand" "=r")
6993	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6994						 (match_dup 4)])))]
6995  "TARGET_ARM"
6996  "sub%?s\\t%0, %1, %3%S2"
6997  [(set_attr "conds" "set")
6998   (set_attr "shift" "3") 
6999   ]
7000)
7001
7002(define_insn "*sub_shiftsi_compare0_scratch"
7003  [(set (reg:CC_NOOV CC_REGNUM)
7004	(compare:CC_NOOV
7005	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7006		   (match_operator:SI 2 "shift_operator"
7007		    [(match_operand:SI 3 "s_register_operand" "r")
7008		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7009	 (const_int 0)))
7010   (clobber (match_scratch:SI 0 "=r"))]
7011  "TARGET_ARM"
7012  "sub%?s\\t%0, %1, %3%S2"
7013  [(set_attr "conds" "set")
7014   (set_attr "shift" "3") 
7015   ]
7016)
7017
7018;; These variants of the above insns can occur if the first operand is the
7019;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
7020;; seem to be a way around it.  Most of the predicates have to be null
7021;; because the format can be generated part way through reload, so
7022;; if we don't match it as soon as it becomes available, reload doesn't know
7023;; how to reload pseudos that haven't got hard registers; the constraints will
7024;; sort everything out.
7025
7026(define_insn "*reload_mulsi3"
7027  [(set (match_operand:SI 0 "" "=&r")
7028	(plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
7029			   [(match_operand:SI 3 "" "r")
7030			    (match_operand:SI 4 "" "rM")])
7031			  (match_operand:SI 2 "" "r"))
7032		 (match_operand:SI 1 "const_int_operand" "n")))]
7033  "TARGET_ARM && reload_in_progress"
7034  "*
7035  output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
7036  operands[2] = operands[1];
7037  operands[1] = operands[0];
7038  return output_add_immediate (operands);
7039  "
7040  [
7041   ; we have no idea how long the add_immediate is, it could be up to 4.
7042   (set_attr "length" "20")]
7043)
7044
7045(define_insn "*reload_mulsi_compare0"
7046  [(set (reg:CC_NOOV CC_REGNUM)
7047	(compare:CC_NOOV (plus:SI
7048			  (plus:SI 
7049			   (match_operator:SI 5 "shift_operator"
7050			    [(match_operand:SI 3 "" "r")
7051			     (match_operand:SI 4 "" "rM")])
7052			   (match_operand:SI 1 "" "r"))
7053			  (match_operand:SI 2 "const_int_operand" "n"))
7054			 (const_int 0)))
7055   (set (match_operand:SI 0 "" "=&r")
7056	(plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
7057			  (match_dup 1))
7058		 (match_dup 2)))]
7059  "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7060  "*
7061    output_add_immediate (operands);
7062    return \"add%?s\\t%0, %0, %3%S5\";
7063  "
7064  [(set_attr "conds" "set")
7065   (set_attr "shift" "3")
7066   (set_attr "length" "20")]
7067)
7068
7069(define_insn "*reload_mulsi_compare0_scratch"
7070  [(set (reg:CC_NOOV CC_REGNUM)
7071	(compare:CC_NOOV (plus:SI
7072			  (plus:SI 
7073			   (match_operator:SI 5 "shift_operator"
7074			    [(match_operand:SI 3 "" "r")
7075			     (match_operand:SI 4 "" "rM")])
7076			   (match_operand:SI 1 "" "r"))
7077			  (match_operand:SI 2 "const_int_operand" "n"))
7078			 (const_int 0)))
7079   (clobber (match_scratch:SI 0 "=&r"))]
7080  "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7081  "*
7082    output_add_immediate (operands);
7083    return \"add%?s\\t%0, %0, %3%S5\";
7084  "
7085  [(set_attr "conds" "set")
7086   (set_attr "shift" "3")
7087   (set_attr "length" "20")]
7088)
7089
7090;; These are similar, but are needed when the mla pattern contains the
7091;; eliminated register as operand 3.
7092
7093(define_insn "*reload_muladdsi"
7094  [(set (match_operand:SI 0 "" "=&r,&r")
7095	(plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
7096				   (match_operand:SI 2 "" "r,r"))
7097			  (match_operand:SI 3 "" "r,r"))
7098		 (match_operand:SI 4 "const_int_operand" "n,n")))]
7099  "TARGET_ARM && reload_in_progress"
7100  "*
7101  output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
7102  operands[2] = operands[4];
7103  operands[1] = operands[0];
7104  return output_add_immediate (operands);
7105  "
7106  [(set_attr "length" "20")
7107   (set_attr "type" "mult")]
7108)
7109
7110(define_insn "*reload_muladdsi_compare0"
7111  [(set (reg:CC_NOOV CC_REGNUM)
7112	(compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7113					    (match_operand:SI 3 "" "r")
7114					    (match_operand:SI 4 "" "r"))
7115					   (match_operand:SI 1 "" "r"))
7116				  (match_operand:SI 2 "const_int_operand" "n"))
7117			 (const_int 0)))
7118   (set (match_operand:SI 0 "" "=&r")
7119	(plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
7120		 (match_dup 2)))]
7121  "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7122  "*
7123    output_add_immediate (operands);
7124    output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
7125    return \"\";
7126  "
7127  [(set_attr "length" "20")
7128   (set_attr "conds" "set")
7129   (set_attr "type" "mult")]
7130)
7131
7132(define_insn "*reload_muladdsi_compare0_scratch"
7133  [(set (reg:CC_NOOV CC_REGNUM)
7134	(compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7135					    (match_operand:SI 3 "" "r")
7136					    (match_operand:SI 4 "" "r"))
7137					   (match_operand:SI 1 "" "r"))
7138				  (match_operand:SI 2 "const_int_operand" "n"))
7139			 (const_int 0)))
7140   (clobber (match_scratch:SI 0 "=&r"))]
7141  "TARGET_ARM && reload_in_progress"
7142  "*
7143    output_add_immediate (operands);
7144    return \"mla%?s\\t%0, %3, %4, %0\";
7145  "
7146  [(set_attr "length" "20")
7147   (set_attr "conds" "set")
7148   (set_attr "type" "mult")]
7149)
7150
7151
7152
7153(define_insn "*and_scc"
7154  [(set (match_operand:SI 0 "s_register_operand" "=r")
7155	(and:SI (match_operator:SI 1 "arm_comparison_operator"
7156		 [(match_operand 3 "cc_register" "") (const_int 0)])
7157		(match_operand:SI 2 "s_register_operand" "r")))]
7158  "TARGET_ARM"
7159  "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7160  [(set_attr "conds" "use")
7161   (set_attr "length" "8")]
7162)
7163
7164(define_insn "*ior_scc"
7165  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7166	(ior:SI (match_operator:SI 2 "arm_comparison_operator"
7167		 [(match_operand 3 "cc_register" "") (const_int 0)])
7168		(match_operand:SI 1 "s_register_operand" "0,?r")))]
7169  "TARGET_ARM"
7170  "@
7171   orr%d2\\t%0, %1, #1
7172   mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7173  [(set_attr "conds" "use")
7174   (set_attr "length" "4,8")]
7175)
7176
7177(define_insn "*compare_scc"
7178  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7179	(match_operator:SI 1 "arm_comparison_operator"
7180	 [(match_operand:SI 2 "s_register_operand" "r,r")
7181	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7182   (clobber (reg:CC CC_REGNUM))]
7183  "TARGET_ARM"
7184  "*
7185    if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7186      return \"mov\\t%0, %2, lsr #31\";
7187
7188    if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7189      return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7190
7191    if (GET_CODE (operands[1]) == NE)
7192      {
7193        if (which_alternative == 1)
7194	  return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7195        return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7196      }
7197    if (which_alternative == 1)
7198      output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7199    else
7200      output_asm_insn (\"cmp\\t%2, %3\", operands);
7201    return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7202  "
7203  [(set_attr "conds" "clob")
7204   (set_attr "length" "12")]
7205)
7206
7207(define_insn "*cond_move"
7208  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7209	(if_then_else:SI (match_operator 3 "equality_operator"
7210			  [(match_operator 4 "arm_comparison_operator"
7211			    [(match_operand 5 "cc_register" "") (const_int 0)])
7212			   (const_int 0)])
7213			 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7214			 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7215  "TARGET_ARM"
7216  "*
7217    if (GET_CODE (operands[3]) == NE)
7218      {
7219        if (which_alternative != 1)
7220	  output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7221        if (which_alternative != 0)
7222	  output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7223        return \"\";
7224      }
7225    if (which_alternative != 0)
7226      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7227    if (which_alternative != 1)
7228      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7229    return \"\";
7230  "
7231  [(set_attr "conds" "use")
7232   (set_attr "length" "4,4,8")]
7233)
7234
7235(define_insn "*cond_arith"
7236  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7237        (match_operator:SI 5 "shiftable_operator" 
7238	 [(match_operator:SI 4 "arm_comparison_operator"
7239           [(match_operand:SI 2 "s_register_operand" "r,r")
7240	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7241          (match_operand:SI 1 "s_register_operand" "0,?r")]))
7242   (clobber (reg:CC CC_REGNUM))]
7243  "TARGET_ARM"
7244  "*
7245    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7246      return \"%i5\\t%0, %1, %2, lsr #31\";
7247
7248    output_asm_insn (\"cmp\\t%2, %3\", operands);
7249    if (GET_CODE (operands[5]) == AND)
7250      output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7251    else if (GET_CODE (operands[5]) == MINUS)
7252      output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7253    else if (which_alternative != 0)
7254      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7255    return \"%i5%d4\\t%0, %1, #1\";
7256  "
7257  [(set_attr "conds" "clob")
7258   (set_attr "length" "12")]
7259)
7260
7261(define_insn "*cond_sub"
7262  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7263        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7264		  (match_operator:SI 4 "arm_comparison_operator"
7265                   [(match_operand:SI 2 "s_register_operand" "r,r")
7266		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7267   (clobber (reg:CC CC_REGNUM))]
7268  "TARGET_ARM"
7269  "*
7270    output_asm_insn (\"cmp\\t%2, %3\", operands);
7271    if (which_alternative != 0)
7272      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7273    return \"sub%d4\\t%0, %1, #1\";
7274  "
7275  [(set_attr "conds" "clob")
7276   (set_attr "length" "8,12")]
7277)
7278
7279(define_insn "*cmp_ite0"
7280  [(set (match_operand 6 "dominant_cc_register" "")
7281	(compare
7282	 (if_then_else:SI
7283	  (match_operator 4 "arm_comparison_operator"
7284	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7285	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7286	  (match_operator:SI 5 "arm_comparison_operator"
7287	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7288	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7289	  (const_int 0))
7290	 (const_int 0)))]
7291  "TARGET_ARM"
7292  "*
7293  {
7294    static const char * const opcodes[4][2] =
7295    {
7296      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7297       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7298      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7299       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7300      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7301       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7302      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7303       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7304    };
7305    int swap =
7306      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7307
7308    return opcodes[which_alternative][swap];
7309  }"
7310  [(set_attr "conds" "set")
7311   (set_attr "length" "8")]
7312)
7313
7314(define_insn "*cmp_ite1"
7315  [(set (match_operand 6 "dominant_cc_register" "")
7316	(compare
7317	 (if_then_else:SI
7318	  (match_operator 4 "arm_comparison_operator"
7319	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7320	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7321	  (match_operator:SI 5 "arm_comparison_operator"
7322	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7323	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7324	  (const_int 1))
7325	 (const_int 0)))]
7326  "TARGET_ARM"
7327  "*
7328  {
7329    static const char * const opcodes[4][2] =
7330    {
7331      {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7332       \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7333      {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7334       \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7335      {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7336       \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7337      {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7338       \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7339    };
7340    int swap =
7341      comparison_dominates_p (GET_CODE (operands[5]),
7342			      reverse_condition (GET_CODE (operands[4])));
7343
7344    return opcodes[which_alternative][swap];
7345  }"
7346  [(set_attr "conds" "set")
7347   (set_attr "length" "8")]
7348)
7349
7350(define_insn "*cmp_and"
7351  [(set (match_operand 6 "dominant_cc_register" "")
7352	(compare
7353	 (and:SI
7354	  (match_operator 4 "arm_comparison_operator"
7355	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7356	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7357	  (match_operator:SI 5 "arm_comparison_operator"
7358	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7359	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7360	 (const_int 0)))]
7361  "TARGET_ARM"
7362  "*
7363  {
7364    static const char *const opcodes[4][2] =
7365    {
7366      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7367       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7368      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7369       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7370      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7371       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7372      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7373       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7374    };
7375    int swap =
7376      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7377
7378    return opcodes[which_alternative][swap];
7379  }"
7380  [(set_attr "conds" "set")
7381   (set_attr "predicable" "no")
7382   (set_attr "length" "8")]
7383)
7384
7385(define_insn "*cmp_ior"
7386  [(set (match_operand 6 "dominant_cc_register" "")
7387	(compare
7388	 (ior:SI
7389	  (match_operator 4 "arm_comparison_operator"
7390	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7391	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7392	  (match_operator:SI 5 "arm_comparison_operator"
7393	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7394	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7395	 (const_int 0)))]
7396  "TARGET_ARM"
7397  "*
7398{
7399  static const char *const opcodes[4][2] =
7400  {
7401    {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7402     \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7403    {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7404     \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7405    {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7406     \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7407    {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7408     \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7409  };
7410  int swap =
7411    comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7412
7413  return opcodes[which_alternative][swap];
7414}
7415"
7416  [(set_attr "conds" "set")
7417   (set_attr "length" "8")]
7418)
7419
7420(define_insn "*negscc"
7421  [(set (match_operand:SI 0 "s_register_operand" "=r")
7422	(neg:SI (match_operator 3 "arm_comparison_operator"
7423		 [(match_operand:SI 1 "s_register_operand" "r")
7424		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7425   (clobber (reg:CC CC_REGNUM))]
7426  "TARGET_ARM"
7427  "*
7428  if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7429    return \"mov\\t%0, %1, asr #31\";
7430
7431  if (GET_CODE (operands[3]) == NE)
7432    return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7433
7434  if (GET_CODE (operands[3]) == GT)
7435    return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7436
7437  output_asm_insn (\"cmp\\t%1, %2\", operands);
7438  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7439  return \"mvn%d3\\t%0, #0\";
7440  "
7441  [(set_attr "conds" "clob")
7442   (set_attr "length" "12")]
7443)
7444
7445(define_insn "movcond"
7446  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7447	(if_then_else:SI
7448	 (match_operator 5 "arm_comparison_operator"
7449	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
7450	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7451	 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7452	 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7453   (clobber (reg:CC CC_REGNUM))]
7454  "TARGET_ARM"
7455  "*
7456  if (GET_CODE (operands[5]) == LT
7457      && (operands[4] == const0_rtx))
7458    {
7459      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7460	{
7461	  if (operands[2] == const0_rtx)
7462	    return \"and\\t%0, %1, %3, asr #31\";
7463	  return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7464	}
7465      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7466	{
7467	  if (operands[1] == const0_rtx)
7468	    return \"bic\\t%0, %2, %3, asr #31\";
7469	  return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7470	}
7471      /* The only case that falls through to here is when both ops 1 & 2
7472	 are constants */
7473    }
7474
7475  if (GET_CODE (operands[5]) == GE
7476      && (operands[4] == const0_rtx))
7477    {
7478      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7479	{
7480	  if (operands[2] == const0_rtx)
7481	    return \"bic\\t%0, %1, %3, asr #31\";
7482	  return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7483	}
7484      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7485	{
7486	  if (operands[1] == const0_rtx)
7487	    return \"and\\t%0, %2, %3, asr #31\";
7488	  return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7489	}
7490      /* The only case that falls through to here is when both ops 1 & 2
7491	 are constants */
7492    }
7493  if (GET_CODE (operands[4]) == CONST_INT
7494      && !const_ok_for_arm (INTVAL (operands[4])))
7495    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7496  else
7497    output_asm_insn (\"cmp\\t%3, %4\", operands);
7498  if (which_alternative != 0)
7499    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7500  if (which_alternative != 1)
7501    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7502  return \"\";
7503  "
7504  [(set_attr "conds" "clob")
7505   (set_attr "length" "8,8,12")]
7506)
7507
7508(define_insn "*ifcompare_plus_move"
7509  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7510	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7511			  [(match_operand:SI 4 "s_register_operand" "r,r")
7512			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7513			 (plus:SI
7514			  (match_operand:SI 2 "s_register_operand" "r,r")
7515			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7516			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7517   (clobber (reg:CC CC_REGNUM))]
7518  "TARGET_ARM"
7519  "#"
7520  [(set_attr "conds" "clob")
7521   (set_attr "length" "8,12")]
7522)
7523
7524(define_insn "*if_plus_move"
7525  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7526	(if_then_else:SI
7527	 (match_operator 4 "arm_comparison_operator"
7528	  [(match_operand 5 "cc_register" "") (const_int 0)])
7529	 (plus:SI
7530	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7531	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7532	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7533  "TARGET_ARM"
7534  "@
7535   add%d4\\t%0, %2, %3
7536   sub%d4\\t%0, %2, #%n3
7537   add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7538   sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7539  [(set_attr "conds" "use")
7540   (set_attr "length" "4,4,8,8")
7541   (set_attr "type" "*,*,*,*")]
7542)
7543
7544(define_insn "*ifcompare_move_plus"
7545  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7546	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7547			  [(match_operand:SI 4 "s_register_operand" "r,r")
7548			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7549			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7550			 (plus:SI
7551			  (match_operand:SI 2 "s_register_operand" "r,r")
7552			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7553   (clobber (reg:CC CC_REGNUM))]
7554  "TARGET_ARM"
7555  "#"
7556  [(set_attr "conds" "clob")
7557   (set_attr "length" "8,12")]
7558)
7559
7560(define_insn "*if_move_plus"
7561  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7562	(if_then_else:SI
7563	 (match_operator 4 "arm_comparison_operator"
7564	  [(match_operand 5 "cc_register" "") (const_int 0)])
7565	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7566	 (plus:SI
7567	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7568	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7569  "TARGET_ARM"
7570  "@
7571   add%D4\\t%0, %2, %3
7572   sub%D4\\t%0, %2, #%n3
7573   add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7574   sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7575  [(set_attr "conds" "use")
7576   (set_attr "length" "4,4,8,8")
7577   (set_attr "type" "*,*,*,*")]
7578)
7579
7580(define_insn "*ifcompare_arith_arith"
7581  [(set (match_operand:SI 0 "s_register_operand" "=r")
7582	(if_then_else:SI (match_operator 9 "arm_comparison_operator"
7583			  [(match_operand:SI 5 "s_register_operand" "r")
7584			   (match_operand:SI 6 "arm_add_operand" "rIL")])
7585			 (match_operator:SI 8 "shiftable_operator"
7586			  [(match_operand:SI 1 "s_register_operand" "r")
7587			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
7588			 (match_operator:SI 7 "shiftable_operator"
7589			  [(match_operand:SI 3 "s_register_operand" "r")
7590			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7591   (clobber (reg:CC CC_REGNUM))]
7592  "TARGET_ARM"
7593  "#"
7594  [(set_attr "conds" "clob")
7595   (set_attr "length" "12")]
7596)
7597
7598(define_insn "*if_arith_arith"
7599  [(set (match_operand:SI 0 "s_register_operand" "=r")
7600	(if_then_else:SI (match_operator 5 "arm_comparison_operator"
7601			  [(match_operand 8 "cc_register" "") (const_int 0)])
7602			 (match_operator:SI 6 "shiftable_operator"
7603			  [(match_operand:SI 1 "s_register_operand" "r")
7604			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
7605			 (match_operator:SI 7 "shiftable_operator"
7606			  [(match_operand:SI 3 "s_register_operand" "r")
7607			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7608  "TARGET_ARM"
7609  "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7610  [(set_attr "conds" "use")
7611   (set_attr "length" "8")]
7612)
7613
7614(define_insn "*ifcompare_arith_move"
7615  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7616	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7617			  [(match_operand:SI 2 "s_register_operand" "r,r")
7618			   (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7619			 (match_operator:SI 7 "shiftable_operator"
7620			  [(match_operand:SI 4 "s_register_operand" "r,r")
7621			   (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7622			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7623   (clobber (reg:CC CC_REGNUM))]
7624  "TARGET_ARM"
7625  "*
7626  /* If we have an operation where (op x 0) is the identity operation and
7627     the conditional operator is LT or GE and we are comparing against zero and
7628     everything is in registers then we can do this in two instructions */
7629  if (operands[3] == const0_rtx
7630      && GET_CODE (operands[7]) != AND
7631      && GET_CODE (operands[5]) == REG
7632      && GET_CODE (operands[1]) == REG 
7633      && REGNO (operands[1]) == REGNO (operands[4])
7634      && REGNO (operands[4]) != REGNO (operands[0]))
7635    {
7636      if (GET_CODE (operands[6]) == LT)
7637	return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7638      else if (GET_CODE (operands[6]) == GE)
7639	return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7640    }
7641  if (GET_CODE (operands[3]) == CONST_INT
7642      && !const_ok_for_arm (INTVAL (operands[3])))
7643    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7644  else
7645    output_asm_insn (\"cmp\\t%2, %3\", operands);
7646  output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7647  if (which_alternative != 0)
7648    return \"mov%D6\\t%0, %1\";
7649  return \"\";
7650  "
7651  [(set_attr "conds" "clob")
7652   (set_attr "length" "8,12")]
7653)
7654
7655(define_insn "*if_arith_move"
7656  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7657	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
7658			  [(match_operand 6 "cc_register" "") (const_int 0)])
7659			 (match_operator:SI 5 "shiftable_operator"
7660			  [(match_operand:SI 2 "s_register_operand" "r,r")
7661			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7662			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7663  "TARGET_ARM"
7664  "@
7665   %I5%d4\\t%0, %2, %3
7666   %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7667  [(set_attr "conds" "use")
7668   (set_attr "length" "4,8")
7669   (set_attr "type" "*,*")]
7670)
7671
7672(define_insn "*ifcompare_move_arith"
7673  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7674	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7675			  [(match_operand:SI 4 "s_register_operand" "r,r")
7676			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7677			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7678			 (match_operator:SI 7 "shiftable_operator"
7679			  [(match_operand:SI 2 "s_register_operand" "r,r")
7680			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7681   (clobber (reg:CC CC_REGNUM))]
7682  "TARGET_ARM"
7683  "*
7684  /* If we have an operation where (op x 0) is the identity operation and
7685     the conditional operator is LT or GE and we are comparing against zero and
7686     everything is in registers then we can do this in two instructions */
7687  if (operands[5] == const0_rtx
7688      && GET_CODE (operands[7]) != AND
7689      && GET_CODE (operands[3]) == REG
7690      && GET_CODE (operands[1]) == REG 
7691      && REGNO (operands[1]) == REGNO (operands[2])
7692      && REGNO (operands[2]) != REGNO (operands[0]))
7693    {
7694      if (GET_CODE (operands[6]) == GE)
7695	return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7696      else if (GET_CODE (operands[6]) == LT)
7697	return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7698    }
7699
7700  if (GET_CODE (operands[5]) == CONST_INT
7701      && !const_ok_for_arm (INTVAL (operands[5])))
7702    output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7703  else
7704    output_asm_insn (\"cmp\\t%4, %5\", operands);
7705
7706  if (which_alternative != 0)
7707    output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7708  return \"%I7%D6\\t%0, %2, %3\";
7709  "
7710  [(set_attr "conds" "clob")
7711   (set_attr "length" "8,12")]
7712)
7713
7714(define_insn "*if_move_arith"
7715  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7716	(if_then_else:SI
7717	 (match_operator 4 "arm_comparison_operator"
7718	  [(match_operand 6 "cc_register" "") (const_int 0)])
7719	 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7720	 (match_operator:SI 5 "shiftable_operator"
7721	  [(match_operand:SI 2 "s_register_operand" "r,r")
7722	   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7723  "TARGET_ARM"
7724  "@
7725   %I5%D4\\t%0, %2, %3
7726   %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7727  [(set_attr "conds" "use")
7728   (set_attr "length" "4,8")
7729   (set_attr "type" "*,*")]
7730)
7731
7732(define_insn "*ifcompare_move_not"
7733  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7734	(if_then_else:SI
7735	 (match_operator 5 "arm_comparison_operator"
7736	  [(match_operand:SI 3 "s_register_operand" "r,r")
7737	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7738	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7739	 (not:SI
7740	  (match_operand:SI 2 "s_register_operand" "r,r"))))
7741   (clobber (reg:CC CC_REGNUM))]
7742  "TARGET_ARM"
7743  "#"
7744  [(set_attr "conds" "clob")
7745   (set_attr "length" "8,12")]
7746)
7747
7748(define_insn "*if_move_not"
7749  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7750	(if_then_else:SI
7751	 (match_operator 4 "arm_comparison_operator"
7752	  [(match_operand 3 "cc_register" "") (const_int 0)])
7753	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7754	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7755  "TARGET_ARM"
7756  "@
7757   mvn%D4\\t%0, %2
7758   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7759   mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7760  [(set_attr "conds" "use")
7761   (set_attr "length" "4,8,8")]
7762)
7763
7764(define_insn "*ifcompare_not_move"
7765  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7766	(if_then_else:SI 
7767	 (match_operator 5 "arm_comparison_operator"
7768	  [(match_operand:SI 3 "s_register_operand" "r,r")
7769	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7770	 (not:SI
7771	  (match_operand:SI 2 "s_register_operand" "r,r"))
7772	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7773   (clobber (reg:CC CC_REGNUM))]
7774  "TARGET_ARM"
7775  "#"
7776  [(set_attr "conds" "clob")
7777   (set_attr "length" "8,12")]
7778)
7779
7780(define_insn "*if_not_move"
7781  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7782	(if_then_else:SI
7783	 (match_operator 4 "arm_comparison_operator"
7784	  [(match_operand 3 "cc_register" "") (const_int 0)])
7785	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7786	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7787  "TARGET_ARM"
7788  "@
7789   mvn%d4\\t%0, %2
7790   mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7791   mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7792  [(set_attr "conds" "use")
7793   (set_attr "length" "4,8,8")]
7794)
7795
7796(define_insn "*ifcompare_shift_move"
7797  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7798	(if_then_else:SI
7799	 (match_operator 6 "arm_comparison_operator"
7800	  [(match_operand:SI 4 "s_register_operand" "r,r")
7801	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7802	 (match_operator:SI 7 "shift_operator"
7803	  [(match_operand:SI 2 "s_register_operand" "r,r")
7804	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7805	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7806   (clobber (reg:CC CC_REGNUM))]
7807  "TARGET_ARM"
7808  "#"
7809  [(set_attr "conds" "clob")
7810   (set_attr "length" "8,12")]
7811)
7812
7813(define_insn "*if_shift_move"
7814  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7815	(if_then_else:SI
7816	 (match_operator 5 "arm_comparison_operator"
7817	  [(match_operand 6 "cc_register" "") (const_int 0)])
7818	 (match_operator:SI 4 "shift_operator"
7819	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
7820	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7821	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7822  "TARGET_ARM"
7823  "@
7824   mov%d5\\t%0, %2%S4
7825   mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7826   mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7827  [(set_attr "conds" "use")
7828   (set_attr "shift" "2")
7829   (set_attr "length" "4,8,8")]
7830)
7831
7832(define_insn "*ifcompare_move_shift"
7833  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7834	(if_then_else:SI
7835	 (match_operator 6 "arm_comparison_operator"
7836	  [(match_operand:SI 4 "s_register_operand" "r,r")
7837	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7838	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7839	 (match_operator:SI 7 "shift_operator"
7840	  [(match_operand:SI 2 "s_register_operand" "r,r")
7841	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7842   (clobber (reg:CC CC_REGNUM))]
7843  "TARGET_ARM"
7844  "#"
7845  [(set_attr "conds" "clob")
7846   (set_attr "length" "8,12")]
7847)
7848
7849(define_insn "*if_move_shift"
7850  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7851	(if_then_else:SI
7852	 (match_operator 5 "arm_comparison_operator"
7853	  [(match_operand 6 "cc_register" "") (const_int 0)])
7854	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7855	 (match_operator:SI 4 "shift_operator"
7856	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
7857	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7858  "TARGET_ARM"
7859  "@
7860   mov%D5\\t%0, %2%S4
7861   mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7862   mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7863  [(set_attr "conds" "use")
7864   (set_attr "shift" "2")
7865   (set_attr "length" "4,8,8")]
7866)
7867
7868(define_insn "*ifcompare_shift_shift"
7869  [(set (match_operand:SI 0 "s_register_operand" "=r")
7870	(if_then_else:SI
7871	 (match_operator 7 "arm_comparison_operator"
7872	  [(match_operand:SI 5 "s_register_operand" "r")
7873	   (match_operand:SI 6 "arm_add_operand" "rIL")])
7874	 (match_operator:SI 8 "shift_operator"
7875	  [(match_operand:SI 1 "s_register_operand" "r")
7876	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
7877	 (match_operator:SI 9 "shift_operator"
7878	  [(match_operand:SI 3 "s_register_operand" "r")
7879	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7880   (clobber (reg:CC CC_REGNUM))]
7881  "TARGET_ARM"
7882  "#"
7883  [(set_attr "conds" "clob")
7884   (set_attr "length" "12")]
7885)
7886
7887(define_insn "*if_shift_shift"
7888  [(set (match_operand:SI 0 "s_register_operand" "=r")
7889	(if_then_else:SI
7890	 (match_operator 5 "arm_comparison_operator"
7891	  [(match_operand 8 "cc_register" "") (const_int 0)])
7892	 (match_operator:SI 6 "shift_operator"
7893	  [(match_operand:SI 1 "s_register_operand" "r")
7894	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
7895	 (match_operator:SI 7 "shift_operator"
7896	  [(match_operand:SI 3 "s_register_operand" "r")
7897	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7898  "TARGET_ARM"
7899  "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7900  [(set_attr "conds" "use")
7901   (set_attr "shift" "1")
7902   (set_attr "length" "8")]
7903)
7904
7905(define_insn "*ifcompare_not_arith"
7906  [(set (match_operand:SI 0 "s_register_operand" "=r")
7907	(if_then_else:SI
7908	 (match_operator 6 "arm_comparison_operator"
7909	  [(match_operand:SI 4 "s_register_operand" "r")
7910	   (match_operand:SI 5 "arm_add_operand" "rIL")])
7911	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7912	 (match_operator:SI 7 "shiftable_operator"
7913	  [(match_operand:SI 2 "s_register_operand" "r")
7914	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7915   (clobber (reg:CC CC_REGNUM))]
7916  "TARGET_ARM"
7917  "#"
7918  [(set_attr "conds" "clob")
7919   (set_attr "length" "12")]
7920)
7921
7922(define_insn "*if_not_arith"
7923  [(set (match_operand:SI 0 "s_register_operand" "=r")
7924	(if_then_else:SI
7925	 (match_operator 5 "arm_comparison_operator"
7926	  [(match_operand 4 "cc_register" "") (const_int 0)])
7927	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7928	 (match_operator:SI 6 "shiftable_operator"
7929	  [(match_operand:SI 2 "s_register_operand" "r")
7930	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7931  "TARGET_ARM"
7932  "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7933  [(set_attr "conds" "use")
7934   (set_attr "length" "8")]
7935)
7936
7937(define_insn "*ifcompare_arith_not"
7938  [(set (match_operand:SI 0 "s_register_operand" "=r")
7939	(if_then_else:SI
7940	 (match_operator 6 "arm_comparison_operator"
7941	  [(match_operand:SI 4 "s_register_operand" "r")
7942	   (match_operand:SI 5 "arm_add_operand" "rIL")])
7943	 (match_operator:SI 7 "shiftable_operator"
7944	  [(match_operand:SI 2 "s_register_operand" "r")
7945	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
7946	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7947   (clobber (reg:CC CC_REGNUM))]
7948  "TARGET_ARM"
7949  "#"
7950  [(set_attr "conds" "clob")
7951   (set_attr "length" "12")]
7952)
7953
7954(define_insn "*if_arith_not"
7955  [(set (match_operand:SI 0 "s_register_operand" "=r")
7956	(if_then_else:SI
7957	 (match_operator 5 "arm_comparison_operator"
7958	  [(match_operand 4 "cc_register" "") (const_int 0)])
7959	 (match_operator:SI 6 "shiftable_operator"
7960	  [(match_operand:SI 2 "s_register_operand" "r")
7961	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
7962	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7963  "TARGET_ARM"
7964  "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7965  [(set_attr "conds" "use")
7966   (set_attr "length" "8")]
7967)
7968
7969(define_insn "*ifcompare_neg_move"
7970  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7971	(if_then_else:SI
7972	 (match_operator 5 "arm_comparison_operator"
7973	  [(match_operand:SI 3 "s_register_operand" "r,r")
7974	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7975	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7976	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7977   (clobber (reg:CC CC_REGNUM))]
7978  "TARGET_ARM"
7979  "#"
7980  [(set_attr "conds" "clob")
7981   (set_attr "length" "8,12")]
7982)
7983
7984(define_insn "*if_neg_move"
7985  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7986	(if_then_else:SI
7987	 (match_operator 4 "arm_comparison_operator"
7988	  [(match_operand 3 "cc_register" "") (const_int 0)])
7989	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7990	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7991  "TARGET_ARM"
7992  "@
7993   rsb%d4\\t%0, %2, #0
7994   mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7995   mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7996  [(set_attr "conds" "use")
7997   (set_attr "length" "4,8,8")]
7998)
7999
8000(define_insn "*ifcompare_move_neg"
8001  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8002	(if_then_else:SI
8003	 (match_operator 5 "arm_comparison_operator"
8004	  [(match_operand:SI 3 "s_register_operand" "r,r")
8005	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8006	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8007	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8008   (clobber (reg:CC CC_REGNUM))]
8009  "TARGET_ARM"
8010  "#"
8011  [(set_attr "conds" "clob")
8012   (set_attr "length" "8,12")]
8013)
8014
8015(define_insn "*if_move_neg"
8016  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8017	(if_then_else:SI
8018	 (match_operator 4 "arm_comparison_operator"
8019	  [(match_operand 3 "cc_register" "") (const_int 0)])
8020	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8021	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8022  "TARGET_ARM"
8023  "@
8024   rsb%D4\\t%0, %2, #0
8025   mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8026   mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8027  [(set_attr "conds" "use")
8028   (set_attr "length" "4,8,8")]
8029)
8030
8031(define_insn "*arith_adjacentmem"
8032  [(set (match_operand:SI 0 "s_register_operand" "=r")
8033	(match_operator:SI 1 "shiftable_operator"
8034	 [(match_operand:SI 2 "memory_operand" "m")
8035	  (match_operand:SI 3 "memory_operand" "m")]))
8036   (clobber (match_scratch:SI 4 "=r"))]
8037  "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8038  "*
8039  {
8040    rtx ldm[3];
8041    rtx arith[4];
8042    int val1 = 0, val2 = 0;
8043
8044    if (REGNO (operands[0]) > REGNO (operands[4]))
8045      {
8046	ldm[1] = operands[4];
8047	ldm[2] = operands[0];
8048      }
8049    else
8050      {
8051	ldm[1] = operands[0];
8052	ldm[2] = operands[4];
8053      }
8054    if (GET_CODE (XEXP (operands[2], 0)) != REG)
8055      val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8056    if (GET_CODE (XEXP (operands[3], 0)) != REG)
8057      val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8058    arith[0] = operands[0];
8059    arith[3] = operands[1];
8060    if (val1 < val2)
8061      {
8062	arith[1] = ldm[1];
8063	arith[2] = ldm[2];
8064      }
8065    else
8066      {
8067	arith[1] = ldm[2];
8068	arith[2] = ldm[1];
8069      }
8070   if (val1 && val2)
8071      {
8072	rtx ops[3];
8073	ldm[0] = ops[0] = operands[4];
8074	ops[1] = XEXP (XEXP (operands[2], 0), 0);
8075	ops[2] = XEXP (XEXP (operands[2], 0), 1);
8076	output_add_immediate (ops);
8077	if (val1 < val2)
8078	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8079	else
8080	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8081      }
8082    else if (val1)
8083      {
8084	ldm[0] = XEXP (operands[3], 0);
8085	if (val1 < val2)
8086	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8087	else
8088	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8089      }
8090    else
8091      {
8092	ldm[0] = XEXP (operands[2], 0);
8093	if (val1 < val2)
8094	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8095	else
8096	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8097      }
8098    output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8099    return \"\";
8100  }"
8101  [(set_attr "length" "12")
8102   (set_attr "predicable" "yes")
8103   (set_attr "type" "load")]
8104)
8105
8106;; the arm can support extended pre-inc instructions
8107
8108;; In all these cases, we use operands 0 and 1 for the register being
8109;; incremented because those are the operands that local-alloc will
8110;; tie and these are the pair most likely to be tieable (and the ones
8111;; that will benefit the most).
8112
8113;; We reject the frame pointer if it occurs anywhere in these patterns since
8114;; elimination will cause too many headaches.
8115
8116(define_insn "*strqi_preinc"
8117  [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8118			 (match_operand:SI 2 "index_operand" "rJ")))
8119	(match_operand:QI 3 "s_register_operand" "r"))
8120   (set (match_operand:SI 0 "s_register_operand" "=r")
8121	(plus:SI (match_dup 1) (match_dup 2)))]
8122  "TARGET_ARM
8123   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8124   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8125   && (GET_CODE (operands[2]) != REG
8126       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8127  "str%?b\\t%3, [%0, %2]!"
8128  [(set_attr "type" "store1")
8129   (set_attr "predicable" "yes")]
8130)
8131
8132(define_insn "*strqi_predec"
8133  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8134			  (match_operand:SI 2 "s_register_operand" "r")))
8135	(match_operand:QI 3 "s_register_operand" "r"))
8136   (set (match_operand:SI 0 "s_register_operand" "=r")
8137	(minus:SI (match_dup 1) (match_dup 2)))]
8138  "TARGET_ARM
8139   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8140   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8141   && (GET_CODE (operands[2]) != REG
8142       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8143  "str%?b\\t%3, [%0, -%2]!"
8144  [(set_attr "type" "store1")
8145   (set_attr "predicable" "yes")]
8146)
8147
8148(define_insn "*loadqi_preinc"
8149  [(set (match_operand:QI 3 "s_register_operand" "=r")
8150	(mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8151			 (match_operand:SI 2 "index_operand" "rJ"))))
8152   (set (match_operand:SI 0 "s_register_operand" "=r")
8153	(plus:SI (match_dup 1) (match_dup 2)))]
8154  "TARGET_ARM
8155   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8156   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8157   && (GET_CODE (operands[2]) != REG
8158       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8159  "ldr%?b\\t%3, [%0, %2]!"
8160  [(set_attr "type" "load")
8161   (set_attr "predicable" "yes")]
8162)
8163
8164(define_insn "*loadqi_predec"
8165  [(set (match_operand:QI 3 "s_register_operand" "=r")
8166	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8167			  (match_operand:SI 2 "s_register_operand" "r"))))
8168   (set (match_operand:SI 0 "s_register_operand" "=r")
8169	(minus:SI (match_dup 1) (match_dup 2)))]
8170  "TARGET_ARM
8171   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8172   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8173   && (GET_CODE (operands[2]) != REG
8174       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8175  "ldr%?b\\t%3, [%0, -%2]!"
8176  [(set_attr "type" "load")
8177   (set_attr "predicable" "yes")]
8178)
8179
8180(define_insn "*loadqisi_preinc"
8181  [(set (match_operand:SI 3 "s_register_operand" "=r")
8182	(zero_extend:SI
8183	 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8184			  (match_operand:SI 2 "index_operand" "rJ")))))
8185   (set (match_operand:SI 0 "s_register_operand" "=r")
8186	(plus:SI (match_dup 1) (match_dup 2)))]
8187  "TARGET_ARM
8188   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8189   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8190   && (GET_CODE (operands[2]) != REG
8191       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8192  "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8193  [(set_attr "type" "load")
8194   (set_attr "predicable" "yes")]
8195)
8196
8197(define_insn "*loadqisi_predec"
8198  [(set (match_operand:SI 3 "s_register_operand" "=r")
8199	(zero_extend:SI
8200	 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8201			   (match_operand:SI 2 "s_register_operand" "r")))))
8202   (set (match_operand:SI 0 "s_register_operand" "=r")
8203	(minus:SI (match_dup 1) (match_dup 2)))]
8204  "TARGET_ARM
8205   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8206   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8207   && (GET_CODE (operands[2]) != REG
8208       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8209  "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8210  [(set_attr "type" "load")
8211   (set_attr "predicable" "yes")]
8212)
8213
8214(define_insn "*strsi_preinc"
8215  [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8216			 (match_operand:SI 2 "index_operand" "rJ")))
8217	(match_operand:SI 3 "s_register_operand" "r"))
8218   (set (match_operand:SI 0 "s_register_operand" "=r")
8219	(plus:SI (match_dup 1) (match_dup 2)))]
8220  "TARGET_ARM
8221   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8222   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8223   && (GET_CODE (operands[2]) != REG
8224       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8225  "str%?\\t%3, [%0, %2]!"
8226  [(set_attr "type" "store1")
8227   (set_attr "predicable" "yes")]
8228)
8229
8230(define_insn "*strsi_predec"
8231  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8232			  (match_operand:SI 2 "s_register_operand" "r")))
8233	(match_operand:SI 3 "s_register_operand" "r"))
8234   (set (match_operand:SI 0 "s_register_operand" "=r")
8235	(minus:SI (match_dup 1) (match_dup 2)))]
8236  "TARGET_ARM
8237   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8238   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8239   && (GET_CODE (operands[2]) != REG
8240       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8241  "str%?\\t%3, [%0, -%2]!"
8242  [(set_attr "type" "store1")
8243   (set_attr "predicable" "yes")]
8244)
8245
8246(define_insn "*loadsi_preinc"
8247  [(set (match_operand:SI 3 "s_register_operand" "=r")
8248	(mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8249			 (match_operand:SI 2 "index_operand" "rJ"))))
8250   (set (match_operand:SI 0 "s_register_operand" "=r")
8251	(plus:SI (match_dup 1) (match_dup 2)))]
8252  "TARGET_ARM
8253   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8254   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8255   && (GET_CODE (operands[2]) != REG
8256       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8257  "ldr%?\\t%3, [%0, %2]!"
8258  [(set_attr "type" "load")
8259   (set_attr "predicable" "yes")]
8260)
8261
8262(define_insn "*loadsi_predec"
8263  [(set (match_operand:SI 3 "s_register_operand" "=r")
8264	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8265			  (match_operand:SI 2 "s_register_operand" "r"))))
8266   (set (match_operand:SI 0 "s_register_operand" "=r")
8267	(minus:SI (match_dup 1) (match_dup 2)))]
8268  "TARGET_ARM
8269   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8270   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8271   && (GET_CODE (operands[2]) != REG
8272       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8273  "ldr%?\\t%3, [%0, -%2]!"
8274  [(set_attr "type" "load")
8275   (set_attr "predicable" "yes")]
8276)
8277
8278(define_insn "*loadhi_preinc"
8279  [(set (match_operand:HI 3 "s_register_operand" "=r")
8280	(mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8281			 (match_operand:SI 2 "index_operand" "rJ"))))
8282   (set (match_operand:SI 0 "s_register_operand" "=r")
8283	(plus:SI (match_dup 1) (match_dup 2)))]
8284  "TARGET_ARM
8285   && !BYTES_BIG_ENDIAN
8286   && !TARGET_MMU_TRAPS
8287   && !arm_arch4
8288   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8289   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8290   && (GET_CODE (operands[2]) != REG
8291       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8292  "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8293  [(set_attr "type" "load")
8294   (set_attr "predicable" "yes")]
8295)
8296
8297(define_insn "*loadhi_predec"
8298  [(set (match_operand:HI 3 "s_register_operand" "=r")
8299	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8300			  (match_operand:SI 2 "s_register_operand" "r"))))
8301   (set (match_operand:SI 0 "s_register_operand" "=r")
8302	(minus:SI (match_dup 1) (match_dup 2)))]
8303  "TARGET_ARM
8304   && !BYTES_BIG_ENDIAN
8305   && !TARGET_MMU_TRAPS
8306   && !arm_arch4
8307   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8308   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8309   && (GET_CODE (operands[2]) != REG
8310       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8311  "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8312  [(set_attr "type" "load")
8313   (set_attr "predicable" "yes")]
8314)
8315
8316(define_insn "*strqi_shiftpreinc"
8317  [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8318			  [(match_operand:SI 3 "s_register_operand" "r")
8319			   (match_operand:SI 4 "const_shift_operand" "n")])
8320			 (match_operand:SI 1 "s_register_operand" "0")))
8321	(match_operand:QI 5 "s_register_operand" "r"))
8322   (set (match_operand:SI 0 "s_register_operand" "=r")
8323	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8324		 (match_dup 1)))]
8325  "TARGET_ARM
8326   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8327   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8328   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8329  "str%?b\\t%5, [%0, %3%S2]!"
8330  [(set_attr "type" "store1")
8331   (set_attr "predicable" "yes")]
8332)
8333
8334(define_insn "*strqi_shiftpredec"
8335  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8336			  (match_operator:SI 2 "shift_operator"
8337			   [(match_operand:SI 3 "s_register_operand" "r")
8338			    (match_operand:SI 4 "const_shift_operand" "n")])))
8339	(match_operand:QI 5 "s_register_operand" "r"))
8340   (set (match_operand:SI 0 "s_register_operand" "=r")
8341	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8342						 (match_dup 4)])))]
8343  "TARGET_ARM
8344   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8345   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8346   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8347  "str%?b\\t%5, [%0, -%3%S2]!"
8348  [(set_attr "type" "store1")
8349   (set_attr "predicable" "yes")]
8350)
8351
8352(define_insn "*loadqi_shiftpreinc"
8353  [(set (match_operand:QI 5 "s_register_operand" "=r")
8354	(mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8355			  [(match_operand:SI 3 "s_register_operand" "r")
8356			   (match_operand:SI 4 "const_shift_operand" "n")])
8357			 (match_operand:SI 1 "s_register_operand" "0"))))
8358   (set (match_operand:SI 0 "s_register_operand" "=r")
8359	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8360		 (match_dup 1)))]
8361  "TARGET_ARM
8362   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8363   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8364   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8365  "ldr%?b\\t%5, [%0, %3%S2]!"
8366  [(set_attr "type" "load")
8367   (set_attr "predicable" "yes")]
8368)
8369
8370(define_insn "*loadqi_shiftpredec"
8371  [(set (match_operand:QI 5 "s_register_operand" "=r")
8372	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8373			  (match_operator:SI 2 "shift_operator"
8374			   [(match_operand:SI 3 "s_register_operand" "r")
8375			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8376   (set (match_operand:SI 0 "s_register_operand" "=r")
8377	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8378						 (match_dup 4)])))]
8379  "TARGET_ARM
8380   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8381   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8382   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8383  "ldr%?b\\t%5, [%0, -%3%S2]!"
8384  [(set_attr "type" "load")
8385   (set_attr "predicable" "yes")]
8386)
8387
8388(define_insn "*strsi_shiftpreinc"
8389  [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8390			  [(match_operand:SI 3 "s_register_operand" "r")
8391			   (match_operand:SI 4 "const_shift_operand" "n")])
8392			 (match_operand:SI 1 "s_register_operand" "0")))
8393	(match_operand:SI 5 "s_register_operand" "r"))
8394   (set (match_operand:SI 0 "s_register_operand" "=r")
8395	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8396		 (match_dup 1)))]
8397  "TARGET_ARM
8398   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8399   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8400   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8401  "str%?\\t%5, [%0, %3%S2]!"
8402  [(set_attr "type" "store1")
8403   (set_attr "predicable" "yes")]
8404)
8405
8406(define_insn "*strsi_shiftpredec"
8407  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8408			  (match_operator:SI 2 "shift_operator"
8409			   [(match_operand:SI 3 "s_register_operand" "r")
8410			    (match_operand:SI 4 "const_shift_operand" "n")])))
8411	(match_operand:SI 5 "s_register_operand" "r"))
8412   (set (match_operand:SI 0 "s_register_operand" "=r")
8413	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8414						 (match_dup 4)])))]
8415  "TARGET_ARM
8416   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8417   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8418   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8419  "str%?\\t%5, [%0, -%3%S2]!"
8420  [(set_attr "type" "store1")
8421   (set_attr "predicable" "yes")]
8422)
8423
8424(define_insn "*loadsi_shiftpreinc"
8425  [(set (match_operand:SI 5 "s_register_operand" "=r")
8426	(mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8427			  [(match_operand:SI 3 "s_register_operand" "r")
8428			   (match_operand:SI 4 "const_shift_operand" "n")])
8429			 (match_operand:SI 1 "s_register_operand" "0"))))
8430   (set (match_operand:SI 0 "s_register_operand" "=r")
8431	(plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8432		 (match_dup 1)))]
8433  "TARGET_ARM
8434   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8435   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8436   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8437  "ldr%?\\t%5, [%0, %3%S2]!"
8438  [(set_attr "type" "load")
8439   (set_attr "predicable" "yes")]
8440)
8441
8442(define_insn "*loadsi_shiftpredec"
8443  [(set (match_operand:SI 5 "s_register_operand" "=r")
8444	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8445			  (match_operator:SI 2 "shift_operator"
8446			   [(match_operand:SI 3 "s_register_operand" "r")
8447			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8448   (set (match_operand:SI 0 "s_register_operand" "=r")
8449	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8450						 (match_dup 4)])))]
8451  "TARGET_ARM
8452   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8453   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8454   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8455  "ldr%?\\t%5, [%0, -%3%S2]!"
8456  [(set_attr "type" "load")
8457   (set_attr "predicable" "yes")])
8458
8459(define_insn "*loadhi_shiftpreinc"
8460  [(set (match_operand:HI 5 "s_register_operand" "=r")
8461	(mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8462			  [(match_operand:SI 3 "s_register_operand" "r")
8463			   (match_operand:SI 4 "const_shift_operand" "n")])
8464			 (match_operand:SI 1 "s_register_operand" "0"))))
8465   (set (match_operand:SI 0 "s_register_operand" "=r")
8466	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8467		 (match_dup 1)))]
8468  "TARGET_ARM
8469   && !BYTES_BIG_ENDIAN
8470   && !TARGET_MMU_TRAPS
8471   && !arm_arch4
8472   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8473   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8474   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8475  "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8476  [(set_attr "type" "load")
8477   (set_attr "predicable" "yes")]
8478)
8479
8480(define_insn "*loadhi_shiftpredec"
8481  [(set (match_operand:HI 5 "s_register_operand" "=r")
8482	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8483			  (match_operator:SI 2 "shift_operator"
8484			   [(match_operand:SI 3 "s_register_operand" "r")
8485			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8486   (set (match_operand:SI 0 "s_register_operand" "=r")
8487	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8488						 (match_dup 4)])))]
8489  "TARGET_ARM
8490   && !BYTES_BIG_ENDIAN
8491   && !TARGET_MMU_TRAPS
8492   && !arm_arch4
8493   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8494   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8495   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8496  "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8497  [(set_attr "type" "load")
8498   (set_attr "predicable" "yes")]
8499)
8500
8501; It can also support extended post-inc expressions, but combine doesn't
8502; try these....
8503; It doesn't seem worth adding peepholes for anything but the most common
8504; cases since, unlike combine, the increment must immediately follow the load
8505; for this pattern to match.
8506; We must watch to see that the source/destination register isn't also the
8507; same as the base address register, and that if the index is a register,
8508; that it is not the same as the base address register.  In such cases the
8509; instruction that we would generate would have UNPREDICTABLE behaviour so 
8510; we cannot use it.
8511
8512(define_peephole
8513  [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8514	(match_operand:QI 2 "s_register_operand" "r"))
8515   (set (match_dup 0)
8516	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8517  "TARGET_ARM
8518   && (REGNO (operands[2]) != REGNO (operands[0]))
8519   && (GET_CODE (operands[1]) != REG
8520       || (REGNO (operands[1]) != REGNO (operands[0])))"
8521  "str%?b\\t%2, [%0], %1"
8522)
8523
8524(define_peephole
8525  [(set (match_operand:QI 0 "s_register_operand" "=r")
8526	(mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8527   (set (match_dup 1)
8528	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8529  "TARGET_ARM
8530   && REGNO (operands[0]) != REGNO(operands[1])
8531   && (GET_CODE (operands[2]) != REG
8532       || REGNO(operands[0]) != REGNO (operands[2]))"
8533  "ldr%?b\\t%0, [%1], %2"
8534)
8535
8536(define_peephole
8537  [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8538	(match_operand:SI 2 "s_register_operand" "r"))
8539   (set (match_dup 0)
8540	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8541  "TARGET_ARM
8542   && (REGNO (operands[2]) != REGNO (operands[0]))
8543   && (GET_CODE (operands[1]) != REG
8544       || (REGNO (operands[1]) != REGNO (operands[0])))"
8545  "str%?\\t%2, [%0], %1"
8546)
8547
8548(define_peephole
8549  [(set (match_operand:HI 0 "s_register_operand" "=r")
8550	(mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8551   (set (match_dup 1)
8552	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8553  "TARGET_ARM
8554   && !BYTES_BIG_ENDIAN
8555   && !TARGET_MMU_TRAPS
8556   && !arm_arch4
8557   && REGNO (operands[0]) != REGNO(operands[1])
8558   && (GET_CODE (operands[2]) != REG
8559       || REGNO(operands[0]) != REGNO (operands[2]))"
8560  "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8561)
8562
8563(define_peephole
8564  [(set (match_operand:SI 0 "s_register_operand" "=r")
8565	(mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8566   (set (match_dup 1)
8567	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8568  "TARGET_ARM
8569   && REGNO (operands[0]) != REGNO(operands[1])
8570   && (GET_CODE (operands[2]) != REG
8571       || REGNO(operands[0]) != REGNO (operands[2]))"
8572  "ldr%?\\t%0, [%1], %2"
8573)
8574
8575(define_peephole
8576  [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8577			 (match_operand:SI 1 "index_operand" "rJ")))
8578	(match_operand:QI 2 "s_register_operand" "r"))
8579   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8580  "TARGET_ARM
8581   && (REGNO (operands[2]) != REGNO (operands[0]))
8582   && (GET_CODE (operands[1]) != REG
8583       || (REGNO (operands[1]) != REGNO (operands[0])))"
8584  "str%?b\\t%2, [%0, %1]!"
8585)
8586
8587(define_peephole
8588  [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8589			  [(match_operand:SI 0 "s_register_operand" "r")
8590			   (match_operand:SI 1 "const_int_operand" "n")])
8591			 (match_operand:SI 2 "s_register_operand" "+r")))
8592	(match_operand:QI 3 "s_register_operand" "r"))
8593   (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8594			       (match_dup 2)))]
8595  "TARGET_ARM
8596   && (REGNO (operands[3]) != REGNO (operands[2]))
8597   && (REGNO (operands[0]) != REGNO (operands[2]))"
8598  "str%?b\\t%3, [%2, %0%S4]!"
8599)
8600
8601; This pattern is never tried by combine, so do it as a peephole
8602
8603(define_peephole2
8604  [(set (match_operand:SI 0 "s_register_operand" "")
8605	(match_operand:SI 1 "s_register_operand" ""))
8606   (set (reg:CC CC_REGNUM)
8607	(compare:CC (match_dup 1) (const_int 0)))]
8608  "TARGET_ARM
8609  "
8610  [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8611	      (set (match_dup 0) (match_dup 1))])]
8612  ""
8613)
8614
8615; Peepholes to spot possible load- and store-multiples, if the ordering is
8616; reversed, check that the memory references aren't volatile.
8617
8618(define_peephole
8619  [(set (match_operand:SI 0 "s_register_operand" "=r")
8620        (match_operand:SI 4 "memory_operand" "m"))
8621   (set (match_operand:SI 1 "s_register_operand" "=r")
8622        (match_operand:SI 5 "memory_operand" "m"))
8623   (set (match_operand:SI 2 "s_register_operand" "=r")
8624        (match_operand:SI 6 "memory_operand" "m"))
8625   (set (match_operand:SI 3 "s_register_operand" "=r")
8626        (match_operand:SI 7 "memory_operand" "m"))]
8627  "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8628  "*
8629  return emit_ldm_seq (operands, 4);
8630  "
8631)
8632
8633(define_peephole
8634  [(set (match_operand:SI 0 "s_register_operand" "=r")
8635        (match_operand:SI 3 "memory_operand" "m"))
8636   (set (match_operand:SI 1 "s_register_operand" "=r")
8637        (match_operand:SI 4 "memory_operand" "m"))
8638   (set (match_operand:SI 2 "s_register_operand" "=r")
8639        (match_operand:SI 5 "memory_operand" "m"))]
8640  "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8641  "*
8642  return emit_ldm_seq (operands, 3);
8643  "
8644)
8645
8646(define_peephole
8647  [(set (match_operand:SI 0 "s_register_operand" "=r")
8648        (match_operand:SI 2 "memory_operand" "m"))
8649   (set (match_operand:SI 1 "s_register_operand" "=r")
8650        (match_operand:SI 3 "memory_operand" "m"))]
8651  "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8652  "*
8653  return emit_ldm_seq (operands, 2);
8654  "
8655)
8656
8657(define_peephole
8658  [(set (match_operand:SI 4 "memory_operand" "=m")
8659        (match_operand:SI 0 "s_register_operand" "r"))
8660   (set (match_operand:SI 5 "memory_operand" "=m")
8661        (match_operand:SI 1 "s_register_operand" "r"))
8662   (set (match_operand:SI 6 "memory_operand" "=m")
8663        (match_operand:SI 2 "s_register_operand" "r"))
8664   (set (match_operand:SI 7 "memory_operand" "=m")
8665        (match_operand:SI 3 "s_register_operand" "r"))]
8666  "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8667  "*
8668  return emit_stm_seq (operands, 4);
8669  "
8670)
8671
8672(define_peephole
8673  [(set (match_operand:SI 3 "memory_operand" "=m")
8674        (match_operand:SI 0 "s_register_operand" "r"))
8675   (set (match_operand:SI 4 "memory_operand" "=m")
8676        (match_operand:SI 1 "s_register_operand" "r"))
8677   (set (match_operand:SI 5 "memory_operand" "=m")
8678        (match_operand:SI 2 "s_register_operand" "r"))]
8679  "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8680  "*
8681  return emit_stm_seq (operands, 3);
8682  "
8683)
8684
8685(define_peephole
8686  [(set (match_operand:SI 2 "memory_operand" "=m")
8687        (match_operand:SI 0 "s_register_operand" "r"))
8688   (set (match_operand:SI 3 "memory_operand" "=m")
8689        (match_operand:SI 1 "s_register_operand" "r"))]
8690  "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8691  "*
8692  return emit_stm_seq (operands, 2);
8693  "
8694)
8695
8696(define_split
8697  [(set (match_operand:SI 0 "s_register_operand" "")
8698	(and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8699		       (const_int 0))
8700		(neg:SI (match_operator:SI 2 "arm_comparison_operator"
8701			 [(match_operand:SI 3 "s_register_operand" "")
8702			  (match_operand:SI 4 "arm_rhs_operand" "")]))))
8703   (clobber (match_operand:SI 5 "s_register_operand" ""))]
8704  "TARGET_ARM"
8705  [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8706   (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8707			      (match_dup 5)))]
8708  ""
8709)
8710
8711;; This split can be used because CC_Z mode implies that the following
8712;; branch will be an equality, or an unsigned inequality, so the sign
8713;; extension is not needed.
8714
8715(define_split
8716  [(set (reg:CC_Z CC_REGNUM)
8717	(compare:CC_Z
8718	 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8719		    (const_int 24))
8720	 (match_operand 1 "const_int_operand" "")))
8721   (clobber (match_scratch:SI 2 ""))]
8722  "TARGET_ARM
8723   && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8724       == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8725  [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8726   (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8727  "
8728  operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8729  "
8730)
8731
8732(define_expand "prologue"
8733  [(clobber (const_int 0))]
8734  "TARGET_EITHER"
8735  "if (TARGET_ARM)
8736     arm_expand_prologue ();
8737   else
8738     thumb_expand_prologue ();
8739  DONE;
8740  "
8741)
8742
8743(define_expand "epilogue"
8744  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8745  "TARGET_EITHER"
8746  "
8747  if (TARGET_THUMB)
8748    thumb_expand_epilogue ();
8749  else if (USE_RETURN_INSN (FALSE))
8750    {
8751      emit_jump_insn (gen_return ());
8752      DONE;
8753    }
8754  emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8755	gen_rtvec (1,
8756		gen_rtx_RETURN (VOIDmode)),
8757	VUNSPEC_EPILOGUE));
8758  DONE;
8759  "
8760)
8761
8762(define_insn "sibcall_epilogue"
8763  [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8764  "TARGET_ARM"
8765  "*
8766  output_asm_insn (\"%@ Sibcall epilogue\", operands);
8767  if (USE_RETURN_INSN (FALSE))
8768    return output_return_instruction (NULL, FALSE, FALSE);
8769  return arm_output_epilogue (FALSE);
8770  "
8771;; Length is absolute worst case
8772  [(set_attr "length" "44")
8773   (set_attr "type" "block")]
8774)
8775
8776(define_insn "*epilogue_insns"
8777  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8778  "TARGET_EITHER"
8779  "*
8780  if (TARGET_ARM)
8781    return arm_output_epilogue (TRUE);
8782  else /* TARGET_THUMB */
8783    return thumb_unexpanded_epilogue ();
8784  "
8785  ; Length is absolute worst case
8786  [(set_attr "length" "44")
8787   (set_attr "type" "block")]
8788)
8789
8790(define_expand "eh_epilogue"
8791  [(use (match_operand:SI 0 "register_operand" "r"))
8792   (use (match_operand:SI 1 "register_operand" "r"))
8793   (use (match_operand:SI 2 "register_operand" "r"))]
8794  "TARGET_EITHER"
8795  "
8796  {
8797    cfun->machine->eh_epilogue_sp_ofs = operands[1];
8798    if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8799      {
8800	rtx ra = gen_rtx_REG (Pmode, 2);
8801
8802	emit_move_insn (ra, operands[2]);
8803	operands[2] = ra;
8804      }
8805    /* This is a hack -- we may have crystalized the function type too
8806       early.  */
8807    cfun->machine->func_type = 0;
8808  }"
8809)
8810
8811;; This split is only used during output to reduce the number of patterns
8812;; that need assembler instructions adding to them.  We allowed the setting
8813;; of the conditions to be implicit during rtl generation so that
8814;; the conditional compare patterns would work.  However this conflicts to
8815;; some extent with the conditional data operations, so we have to split them
8816;; up again here.
8817
8818(define_split
8819  [(set (match_operand:SI 0 "s_register_operand" "")
8820	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8821			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8822			 (match_dup 0)
8823			 (match_operand 4 "" "")))
8824   (clobber (reg:CC CC_REGNUM))]
8825  "TARGET_ARM && reload_completed"
8826  [(set (match_dup 5) (match_dup 6))
8827   (cond_exec (match_dup 7)
8828	      (set (match_dup 0) (match_dup 4)))]
8829  "
8830  {
8831    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8832					     operands[2], operands[3]);
8833    enum rtx_code rc = GET_CODE (operands[1]);
8834
8835    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8836    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8837    if (mode == CCFPmode || mode == CCFPEmode)
8838      rc = reverse_condition_maybe_unordered (rc);
8839    else
8840      rc = reverse_condition (rc);
8841
8842    operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8843  }"
8844)
8845
8846(define_split
8847  [(set (match_operand:SI 0 "s_register_operand" "")
8848	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8849			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8850			 (match_operand 4 "" "")
8851			 (match_dup 0)))
8852   (clobber (reg:CC CC_REGNUM))]
8853  "TARGET_ARM && reload_completed"
8854  [(set (match_dup 5) (match_dup 6))
8855   (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8856	      (set (match_dup 0) (match_dup 4)))]
8857  "
8858  {
8859    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8860					     operands[2], operands[3]);
8861
8862    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8863    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8864  }"
8865)
8866
8867(define_split
8868  [(set (match_operand:SI 0 "s_register_operand" "")
8869	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8870			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8871			 (match_operand 4 "" "")
8872			 (match_operand 5 "" "")))
8873   (clobber (reg:CC CC_REGNUM))]
8874  "TARGET_ARM && reload_completed"
8875  [(set (match_dup 6) (match_dup 7))
8876   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8877	      (set (match_dup 0) (match_dup 4)))
8878   (cond_exec (match_dup 8)
8879	      (set (match_dup 0) (match_dup 5)))]
8880  "
8881  {
8882    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8883					     operands[2], operands[3]);
8884    enum rtx_code rc = GET_CODE (operands[1]);
8885
8886    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8887    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8888    if (mode == CCFPmode || mode == CCFPEmode)
8889      rc = reverse_condition_maybe_unordered (rc);
8890    else
8891      rc = reverse_condition (rc);
8892
8893    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8894  }"
8895)
8896
8897(define_split
8898  [(set (match_operand:SI 0 "s_register_operand" "")
8899	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8900			  [(match_operand:SI 2 "s_register_operand" "")
8901			   (match_operand:SI 3 "arm_add_operand" "")])
8902			 (match_operand:SI 4 "arm_rhs_operand" "")
8903			 (not:SI
8904			  (match_operand:SI 5 "s_register_operand" ""))))
8905   (clobber (reg:CC CC_REGNUM))]
8906  "TARGET_ARM && reload_completed"
8907  [(set (match_dup 6) (match_dup 7))
8908   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8909	      (set (match_dup 0) (match_dup 4)))
8910   (cond_exec (match_dup 8)
8911	      (set (match_dup 0) (not:SI (match_dup 5))))]
8912  "
8913  {
8914    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8915					     operands[2], operands[3]);
8916    enum rtx_code rc = GET_CODE (operands[1]);
8917
8918    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8919    operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8920    if (mode == CCFPmode || mode == CCFPEmode)
8921      rc = reverse_condition_maybe_unordered (rc);
8922    else
8923      rc = reverse_condition (rc);
8924
8925    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8926  }"
8927)
8928
8929(define_insn "*cond_move_not"
8930  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8931	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
8932			  [(match_operand 3 "cc_register" "") (const_int 0)])
8933			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8934			 (not:SI
8935			  (match_operand:SI 2 "s_register_operand" "r,r"))))]
8936  "TARGET_ARM"
8937  "@
8938   mvn%D4\\t%0, %2
8939   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8940  [(set_attr "conds" "use")
8941   (set_attr "length" "4,8")]
8942)
8943
8944;; The next two patterns occur when an AND operation is followed by a
8945;; scc insn sequence 
8946
8947(define_insn "*sign_extract_onebit"
8948  [(set (match_operand:SI 0 "s_register_operand" "=r")
8949	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8950			 (const_int 1)
8951			 (match_operand:SI 2 "const_int_operand" "n")))
8952    (clobber (reg:CC CC_REGNUM))]
8953  "TARGET_ARM"
8954  "*
8955    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8956    output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8957    return \"mvnne\\t%0, #0\";
8958  "
8959  [(set_attr "conds" "clob")
8960   (set_attr "length" "8")]
8961)
8962
8963(define_insn "*not_signextract_onebit"
8964  [(set (match_operand:SI 0 "s_register_operand" "=r")
8965	(not:SI
8966	 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8967			  (const_int 1)
8968			  (match_operand:SI 2 "const_int_operand" "n"))))
8969   (clobber (reg:CC CC_REGNUM))]
8970  "TARGET_ARM"
8971  "*
8972    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8973    output_asm_insn (\"tst\\t%1, %2\", operands);
8974    output_asm_insn (\"mvneq\\t%0, #0\", operands);
8975    return \"movne\\t%0, #0\";
8976  "
8977  [(set_attr "conds" "clob")
8978   (set_attr "length" "12")]
8979)
8980
8981;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8982;; expressions.  For simplicity, the first register is also in the unspec
8983;; part.
8984(define_insn "*push_multi"
8985  [(match_parallel 2 "multi_register_push"
8986    [(set (match_operand:BLK 0 "memory_operand" "=m")
8987	  (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8988		      UNSPEC_PUSH_MULT))])]
8989  "TARGET_ARM"
8990  "*
8991  {
8992    int num_saves = XVECLEN (operands[2], 0);
8993     
8994    /* For the StrongARM at least it is faster to
8995       use STR to store only a single register.  */
8996    if (num_saves == 1)
8997      output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8998    else
8999      {
9000	int i;
9001	char pattern[100];
9002
9003	strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9004
9005	for (i = 1; i < num_saves; i++)
9006	  {
9007	    strcat (pattern, \", %|\");
9008	    strcat (pattern,
9009		    reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9010	  }
9011
9012	strcat (pattern, \"}\");
9013	output_asm_insn (pattern, operands);
9014      }
9015
9016    return \"\";
9017  }"
9018  [(set_attr "type" "store4")]
9019)
9020
9021;; Similarly for the floating point registers
9022(define_insn "*push_fp_multi"
9023  [(match_parallel 2 "multi_register_push"
9024    [(set (match_operand:BLK 0 "memory_operand" "=m")
9025	  (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9026		      UNSPEC_PUSH_MULT))])]
9027  "TARGET_ARM"
9028  "*
9029  {
9030    char pattern[100];
9031
9032    sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9033    output_asm_insn (pattern, operands);
9034    return \"\";
9035  }"
9036  [(set_attr "type" "f_store")]
9037)
9038
9039;; Special patterns for dealing with the constant pool
9040
9041(define_insn "align_4"
9042  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9043  "TARGET_EITHER"
9044  "*
9045  assemble_align (32);
9046  return \"\";
9047  "
9048)
9049
9050(define_insn "consttable_end"
9051  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9052  "TARGET_EITHER"
9053  "*
9054  making_const_table = FALSE;
9055  return \"\";
9056  "
9057)
9058
9059(define_insn "consttable_1"
9060  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9061  "TARGET_THUMB"
9062  "*
9063  making_const_table = TRUE;
9064  assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9065  assemble_zeros (3);
9066  return \"\";
9067  "
9068  [(set_attr "length" "4")]
9069)
9070
9071(define_insn "consttable_2"
9072  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9073  "TARGET_THUMB"
9074  "*
9075  making_const_table = TRUE;
9076  assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9077  assemble_zeros (2);
9078  return \"\";
9079  "
9080  [(set_attr "length" "4")]
9081)
9082
9083(define_insn "consttable_4"
9084  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9085  "TARGET_EITHER"
9086  "*
9087  {
9088    making_const_table = TRUE;
9089    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9090      {
9091      case MODE_FLOAT:
9092      {
9093        union real_extract u;
9094        memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9095        assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9096        break;
9097      }
9098      default:
9099        assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9100        break;
9101      }
9102    return \"\";
9103  }"
9104  [(set_attr "length" "4")]
9105)
9106
9107(define_insn "consttable_8"
9108  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9109  "TARGET_EITHER"
9110  "*
9111  {
9112    making_const_table = TRUE;
9113    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9114      {
9115       case MODE_FLOAT:
9116        {
9117          union real_extract u;
9118          memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9119          assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9120          break;
9121        }
9122      default:
9123        assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9124        break;
9125      }
9126    return \"\";
9127  }"
9128  [(set_attr "length" "8")]
9129)
9130
9131;; Miscellaneous Thumb patterns
9132
9133(define_expand "tablejump"
9134  [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9135	      (use (label_ref (match_operand 1 "" "")))])]
9136  "TARGET_THUMB"
9137  "
9138  if (flag_pic)
9139    {
9140      /* Hopefully, CSE will eliminate this copy.  */
9141      rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9142      rtx reg2 = gen_reg_rtx (SImode);
9143
9144      emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9145      operands[0] = reg2;
9146    }
9147  "
9148)
9149
9150(define_insn "*thumb_tablejump"
9151  [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9152   (use (label_ref (match_operand 1 "" "")))]
9153  "TARGET_THUMB"
9154  "mov\\t%|pc, %0"
9155  [(set_attr "length" "2")]
9156)
9157
9158;; V5 Instructions,
9159
9160(define_insn "clz"
9161  [(set (match_operand:SI             0 "s_register_operand" "=r")
9162	(unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9163		   UNSPEC_CLZ))]
9164  "TARGET_ARM && arm_arch5"
9165  "clz\\t%0, %1")
9166
9167(define_expand "ffssi2"
9168  [(set (match_operand:SI 0 "s_register_operand" "")
9169	(ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9170  "TARGET_ARM && arm_arch5"
9171  "
9172  {
9173    rtx t1, t2, t3;
9174
9175    t1 = gen_reg_rtx (SImode);
9176    t2 = gen_reg_rtx (SImode);
9177    t3 = gen_reg_rtx (SImode);
9178
9179    emit_insn (gen_negsi2 (t1, operands[1]));
9180    emit_insn (gen_andsi3 (t2, operands[1], t1));
9181    emit_insn (gen_clz (t3, t2));
9182    emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9183    DONE;
9184  }"
9185)
9186
9187;; V5E instructions.
9188
9189(define_insn "prefetch"
9190  [(prefetch (match_operand:SI 0 "address_operand" "p")
9191	     (match_operand:SI 1 "" "")
9192	     (match_operand:SI 2 "" ""))]
9193  "TARGET_ARM && arm_arch5e"
9194  "pld\\t%a0")
9195
9196;; General predication pattern
9197
9198(define_cond_exec
9199  [(match_operator 0 "arm_comparison_operator"
9200    [(match_operand 1 "cc_register" "")
9201     (const_int 0)])]
9202  "TARGET_ARM"
9203  ""
9204)
9205
9206(define_insn "prologue_use"
9207  [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9208  ""
9209  "%@ %0 needed for prologue"
9210)
9211