1;;- Machine description for ARM for GNU compiler
2;;  Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
3;;  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;; UNSPEC Usage:
32;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
33;;   the mode is MODE_FLOAT
34;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
35;;   the mode is MODE_FLOAT
36;; 2 `push multiple' operation: operand 0 is the first register.  Subsequent
37;;   registers are in parallel (use...) expressions.
38;; 3 A symbol that has been treated properly for pic usage, that is, we
39;;   will add the pic_register value to it before trying to dereference it.
40;; Note: sin and cos are no-longer used.
41
42;; Attributes
43
44; PROG_MODE attribute is used to determine whether condition codes are
45; clobbered by a call insn: they are if in prog32 mode.  This is controlled
46; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
47(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
48
49(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
50
51; Floating Point Unit.  If we only have floating point emulation, then there
52; is no point in scheduling the floating point insns.  (Well, for best
53; performance we should try and group them together).
54
55(define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
56
57; LENGTH of an instruction (in bytes)
58(define_attr "length" "" (const_int 4))
59
60; An assembler sequence may clobber the condition codes without us knowing
61(define_asm_attributes
62 [(set_attr "conds" "clob")
63  (set_attr "length" "4")])
64
65; TYPE attribute is used to detect floating point instructions which, if
66; running on a co-processor can run in parallel with other, basic instructions
67; If write-buffer scheduling is enabled then it can also be used in the
68; scheduling of writes.
69
70; Classification of each insn
71; normal	any data instruction that doesn't hit memory or fp regs
72; mult		a multiply instruction
73; block		blockage insn, this blocks all functional units
74; float		a floating point arithmetic operation (subject to expansion)
75; fdivx		XFmode floating point division
76; fdivd		DFmode floating point division
77; fdivs		SFmode floating point division
78; fmul		Floating point multiply
79; ffmul		Fast floating point multiply
80; farith	Floating point arithmetic (4 cycle)
81; ffarith	Fast floating point arithmetic (2 cycle)
82; float_em	a floating point arithmetic operation that is normally emulated
83;		even on a machine with an fpa.
84; f_load	a floating point load from memory
85; f_store	a floating point store to memory
86; f_mem_r	a transfer of a floating point register to a real reg via mem
87; r_mem_f	the reverse of f_mem_r
88; f_2_r		fast transfer float to arm (no memory needed)
89; r_2_f		fast transfer arm to float
90; call		a subroutine call
91; load		any load from memory
92; store1	store 1 word to memory from arm registers
93; store2	store 2 words
94; store3	store 3 words
95; store4	store 4 words
96;
97(define_attr "type"
98	"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" 
99	(const_string "normal"))
100
101; Load scheduling, set from the arm_ld_sched variable
102; initialised by arm_override_options() 
103(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
104
105; condition codes: this one is used by final_prescan_insn to speed up
106; conditionalizing instructions.  It saves having to scan the rtl to see if
107; it uses or alters the condition codes.
108
109; USE means that the condition codes are used by the insn in the process of
110; outputting code, this means (at present) that we can't use the insn in
111; inlined branches
112
113; SET means that the purpose of the insn is to set the condition codes in a
114; well defined manner.
115
116; CLOB means that the condition codes are altered in an undefined manner, if
117; they are altered at all
118
119; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
120; but are if the branch wasn't taken; the effect is to limit the branch
121; elimination scanning.
122
123; NOCOND means that the condition codes are neither altered nor affect the
124; output of this insn
125
126(define_attr "conds" "use,set,clob,jump_clob,nocond"
127	(if_then_else (eq_attr "type" "call")
128	 (if_then_else (eq_attr "prog_mode" "prog32")
129	  (const_string "clob") (const_string "nocond"))
130	 (const_string "nocond")))
131
132; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
133; have one.  Later ones, such as StrongARM, have write-back caches, so don't
134; suffer blockages enough to warrent modelling this (and it can adversely
135; affect the schedule).
136(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
137
138(define_attr "write_conflict" "no,yes"
139  (if_then_else (eq_attr "type"
140		 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
141		(const_string "yes")
142		(const_string "no")))
143
144(define_attr "core_cycles" "single,multi"
145  (if_then_else (eq_attr "type"
146		 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
147		(const_string "single")
148	        (const_string "multi")))
149
150; The write buffer on some of the arm6 processors is hard to model exactly.
151; There is room in the buffer for up to two addresses and up to eight words
152; of memory, but the two needn't be split evenly.  When writing the two
153; addresses are fully pipelined.  However, a read from memory that is not
154; currently in the cache will block until the writes have completed.
155; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
156; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
157; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
158; cycle to add as well.
159
160;; (define_function_unit {name} {num-units} {n-users} {test}
161;;                       {ready-delay} {issue-delay} [{conflict-list}])
162(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
163				     (eq_attr "type" "fdivx")) 71 69)
164
165(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
166				     (eq_attr "type" "fdivd")) 59 57)
167
168(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
169				     (eq_attr "type" "fdivs")) 31 29)
170
171(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
172				     (eq_attr "type" "fmul")) 9 7)
173
174(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
175				     (eq_attr "type" "ffmul")) 6 4)
176
177(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
178				     (eq_attr "type" "farith")) 4 2)
179
180(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
181				     (eq_attr "type" "ffarith")) 2 2)
182
183(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
184				     (eq_attr "type" "r_2_f")) 5 3)
185
186(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
187				     (eq_attr "type" "f_2_r")) 1 2)
188
189;; The fpa10 doesn't really have a memory read unit, but it can start to
190;; speculatively execute the instruction in the pipeline, provided the data
191;; is already loaded, so pretend reads have a delay of 2 (and that the
192;; pipeline is infinite.
193
194(define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
195					 (eq_attr "type" "f_load")) 3 1)
196
197;;--------------------------------------------------------------------
198;; Write buffer
199;;--------------------------------------------------------------------
200;; Strictly we should model a 4-deep write buffer for ARM7xx based chips
201(define_function_unit "write_buf" 1 2
202  (and (eq_attr "model_wbuf" "yes")
203       (eq_attr "type" "store1,r_mem_f")) 5 3)
204(define_function_unit "write_buf" 1 2 
205  (and (eq_attr "model_wbuf" "yes")
206       (eq_attr "type" "store2")) 7 4)
207(define_function_unit "write_buf" 1 2
208  (and (eq_attr "model_wbuf" "yes")
209       (eq_attr "type" "store3")) 9 5)
210(define_function_unit "write_buf" 1 2
211  (and (eq_attr "model_wbuf" "yes")
212       (eq_attr "type" "store4")) 11 6)
213
214;;--------------------------------------------------------------------
215;; Write blockage unit
216;;--------------------------------------------------------------------
217;; The write_blockage unit models (partially), the fact that reads will stall
218;; until the write buffer empties.
219;; The f_mem_r and r_mem_f could also block, but they are to the stack,
220;; so we don't model them here
221(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
222						(eq_attr "type" "store1")) 5 5
223	[(eq_attr "write_conflict" "yes")])
224(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
225						(eq_attr "type" "store2")) 7 7
226	[(eq_attr "write_conflict" "yes")])
227(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
228						(eq_attr "type" "store3")) 9 9
229	[(eq_attr "write_conflict" "yes")])
230(define_function_unit "write_blockage" 1 0
231	(and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
232	[(eq_attr "write_conflict" "yes")])
233(define_function_unit "write_blockage" 1 0
234	(and (eq_attr "model_wbuf" "yes")
235	     (eq_attr "write_conflict" "yes")) 1 1)
236
237;;--------------------------------------------------------------------
238;; Core unit
239;;--------------------------------------------------------------------
240;; Everything must spend at least one cycle in the core unit
241(define_function_unit "core" 1 0
242  (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
243
244(define_function_unit "core" 1 0
245  (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
246
247(define_function_unit "core" 1 0
248  (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
249
250(define_function_unit "core" 1 0
251  (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
252
253(define_function_unit "core" 1 0
254  (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
255
256(define_function_unit "core" 1 0
257  (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
258
259(define_function_unit "core" 1 0
260  (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
261
262(define_function_unit "core" 1 0
263  (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
264
265(define_function_unit "core" 1 0
266  (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
267       (eq_attr "type" "mult")) 4 4)
268
269(define_function_unit "core" 1 0
270  (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
271       (eq_attr "type" "mult")) 3 2)
272
273(define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
274
275(define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
276
277(define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
278
279;; Note: For DImode insns, there is normally no reason why operands should
280;; not be in the same register, what we don't want is for something being
281;; written to partially overlap something that is an input.
282
283;; Addition insns.
284
285(define_insn "adddi3"
286  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
287	(plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
288		 (match_operand:DI 2 "s_register_operand" "r,0")))
289   (clobber (reg:CC 24))]
290  ""
291  "adds\\t%Q0, %Q1, %Q2\;adc\\t%R0, %R1, %R2"
292[(set_attr "conds" "clob")
293 (set_attr "length" "8")])
294
295(define_insn "*adddi_sesidi_di"
296  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
297	(plus:DI (sign_extend:DI
298		  (match_operand:SI 2 "s_register_operand" "r,r"))
299		 (match_operand:DI 1 "s_register_operand" "r,0")))
300   (clobber (reg:CC 24))]
301  ""
302  "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, %2, asr #31"
303[(set_attr "conds" "clob")
304 (set_attr "length" "8")])
305
306(define_insn "*adddi_zesidi_di"
307  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
308	(plus:DI (zero_extend:DI
309		  (match_operand:SI 2 "s_register_operand" "r,r"))
310		 (match_operand:DI 1 "s_register_operand" "r,0")))
311   (clobber (reg:CC 24))]
312  ""
313  "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, #0"
314[(set_attr "conds" "clob")
315 (set_attr "length" "8")])
316
317(define_expand "addsi3"
318  [(set (match_operand:SI 0 "s_register_operand" "")
319	(plus:SI (match_operand:SI 1 "s_register_operand" "")
320		 (match_operand:SI 2 "reg_or_int_operand" "")))]
321  ""
322  "
323  if (GET_CODE (operands[2]) == CONST_INT)
324    {
325      arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
326			  operands[1],
327			  (reload_in_progress || reload_completed ? 0
328			   : preserve_subexpressions_p ()));
329      DONE;
330    }
331")
332
333(define_split
334  [(set (match_operand:SI 0 "s_register_operand" "")
335	(plus:SI (match_operand:SI 1 "s_register_operand" "")
336		 (match_operand:SI 2 "const_int_operand" "")))]
337  "! (const_ok_for_arm (INTVAL (operands[2]))
338      || const_ok_for_arm (-INTVAL (operands[2])))"
339  [(clobber (const_int 0))]
340  "
341  arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
342		      operands[1], 0);
343  DONE;
344")
345
346(define_insn "*addsi3_insn"
347  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
348	(plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
349		 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
350  ""
351  "@
352   add%?\\t%0, %1, %2
353   sub%?\\t%0, %1, #%n2
354   #"
355[(set_attr "length" "4,4,16")])
356
357(define_insn "*addsi3_compare0"
358  [(set (reg:CC_NOOV 24)
359	(compare:CC_NOOV
360	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
361		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
362	 (const_int 0)))
363   (set (match_operand:SI 0 "s_register_operand" "=r,r")
364	(plus:SI (match_dup 1) (match_dup 2)))]
365  ""
366  "@
367   add%?s\\t%0, %1, %2
368   sub%?s\\t%0, %1, #%n2"
369[(set_attr "conds" "set")])
370
371(define_insn "*addsi3_compare0_scratch"
372  [(set (reg:CC_NOOV 24)
373	(compare:CC_NOOV
374	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
375		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
376	 (const_int 0)))]
377  ""
378  "@
379   cmn%?\\t%0, %1
380   cmp%?\\t%0, #%n1"
381[(set_attr "conds" "set")])
382
383;; The next four insns work because they compare the result with one of
384;; the operands, and we know that the use of the condition code is
385;; either GEU or LTU, so we can use the carry flag from the addition
386;; instead of doing the compare a second time.
387(define_insn "*addsi3_compare_op1"
388  [(set (reg:CC_C 24)
389	(compare:CC_C
390	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
391		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
392	 (match_dup 1)))
393   (set (match_operand:SI 0 "s_register_operand" "=r,r")
394	(plus:SI (match_dup 1) (match_dup 2)))]
395  ""
396  "@
397   add%?s\\t%0, %1, %2
398   sub%?s\\t%0, %1, #%n2"
399[(set_attr "conds" "set")])
400
401(define_insn "*addsi3_compare_op2"
402  [(set (reg:CC_C 24)
403	(compare:CC_C
404	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
405		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
406	 (match_dup 2)))
407   (set (match_operand:SI 0 "s_register_operand" "=r,r")
408	(plus:SI (match_dup 1) (match_dup 2)))]
409  ""
410  "@
411   add%?s\\t%0, %1, %2
412   sub%?s\\t%0, %1, #%n2"
413[(set_attr "conds" "set")])
414
415(define_insn "*compare_addsi2_op0"
416  [(set (reg:CC_C 24)
417	(compare:CC_C
418	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
419		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
420	 (match_dup 0)))]
421  ""
422  "@
423   cmn%?\\t%0, %1
424   cmp%?\\t%0, #%n1"
425[(set_attr "conds" "set")])
426
427(define_insn "*compare_addsi2_op1"
428  [(set (reg:CC_C 24)
429	(compare:CC_C
430	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
431		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
432	 (match_dup 1)))]
433  ""
434  "@
435   cmn%?\\t%0, %1
436   cmp%?\\t%0, #%n1"
437[(set_attr "conds" "set")])
438
439(define_insn "*addsi3_carryin"
440  [(set (match_operand:SI 0 "s_register_operand" "=r")
441	(plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
442		 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
443			  (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
444  ""
445  "adc%?\\t%0, %1, %2"
446[(set_attr "conds" "use")])
447
448(define_insn "*addsi3_carryin_alt1"
449  [(set (match_operand:SI 0 "s_register_operand" "=r")
450	(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
451			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
452		 (ltu:SI (reg:CC_C 24) (const_int 0))))]
453  ""
454  "adc%?\\t%0, %1, %2"
455[(set_attr "conds" "use")])
456
457(define_insn "*addsi3_carryin_alt2"
458  [(set (match_operand:SI 0 "s_register_operand" "=r")
459	(plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
460			  (match_operand:SI 1 "s_register_operand" "r"))
461		 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
462  ""
463  "adc%?\\t%0, %1, %2"
464[(set_attr "conds" "use")])
465
466(define_insn "*addsi3_carryin_alt3"
467  [(set (match_operand:SI 0 "s_register_operand" "=r")
468	(plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
469			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
470		 (match_operand:SI 1 "s_register_operand" "r")))]
471  ""
472  "adc%?\\t%0, %1, %2"
473[(set_attr "conds" "use")])
474
475(define_insn "incscc"
476  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
477        (plus:SI (match_operator:SI 2 "comparison_operator"
478                    [(match_operand 3 "cc_register" "") (const_int 0)])
479                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
480  ""
481  "@
482  add%d2\\t%0, %1, #1
483  mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
484[(set_attr "conds" "use")
485 (set_attr "length" "4,8")])
486
487; If a constant is too big to fit in a single instruction then the constant
488; will be pre-loaded into a register taking at least two insns, we might be
489; able to merge it with an add, but it depends on the exact value.
490
491(define_split
492  [(set (match_operand:SI 0 "s_register_operand" "=r")
493	(plus:SI (match_operand:SI 1 "s_register_operand" "r")
494		 (match_operand:SI 2 "const_int_operand" "n")))]
495  "!(const_ok_for_arm (INTVAL (operands[2]))
496     || const_ok_for_arm (-INTVAL (operands[2])))"
497  [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
498   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
499  "
500{
501  unsigned int val = (unsigned) INTVAL (operands[2]);
502  int i;
503  unsigned int temp;
504
505  /* this code is similar to the approach followed in movsi, but it must
506     generate exactly two insns */
507
508  for (i = 30; i >= 0; i -= 2)
509    {
510      if (val & (3 << i))
511	{
512	  i -= 6;
513	  if (i < 0) i = 0;
514	  if (const_ok_for_arm (temp = (val & ~(255 << i))))
515	    {
516	      val &= 255 << i;
517	      break;
518	    }
519	  /* we might be able to do this as (larger number - small number) */
520	  temp = ((val >> i) & 255) + 1;
521	  if (temp > 255 && i < 24)
522	    {
523	      i += 2;
524	      temp = ((val >> i) & 255) + 1;
525	    }
526	  if (const_ok_for_arm ((temp << i) - val))
527	    {
528	      i = temp << i;
529	      temp = (unsigned) - (int) (i - val);
530	      val = i;
531	      break;
532	    }
533	  FAIL;
534	}
535    }
536  /* if we got here, we have found a way of doing it in two instructions.
537     the two constants are in val and temp */
538  operands[2] = GEN_INT ((int)val);
539  operands[3] = GEN_INT ((int)temp);
540}
541")
542
543(define_insn "addsf3"
544  [(set (match_operand:SF 0 "s_register_operand" "=f,f")
545	(plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
546		 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
547  "TARGET_HARD_FLOAT"
548  "@
549   adf%?s\\t%0, %1, %2
550   suf%?s\\t%0, %1, #%N2"
551[(set_attr "type" "farith")])
552
553(define_insn "adddf3"
554  [(set (match_operand:DF 0 "s_register_operand" "=f,f")
555	(plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
556		 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
557  "TARGET_HARD_FLOAT"
558  "@
559   adf%?d\\t%0, %1, %2
560   suf%?d\\t%0, %1, #%N2"
561[(set_attr "type" "farith")])
562
563(define_insn "*adddf_df_esfdf"
564  [(set (match_operand:DF 0 "s_register_operand" "=f,f")
565	(plus:DF (float_extend:DF
566		  (match_operand:SF 1 "s_register_operand" "f,f"))
567		 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
568  "TARGET_HARD_FLOAT"
569  "@
570   adf%?d\\t%0, %1, %2
571   suf%?d\\t%0, %1, #%N2"
572[(set_attr "type" "farith")])
573
574(define_insn "*adddf_df_esfdf"
575  [(set (match_operand:DF 0 "s_register_operand" "=f")
576	(plus:DF (match_operand:DF 1 "s_register_operand" "f")
577		 (float_extend:DF
578		  (match_operand:SF 2 "s_register_operand" "f"))))]
579  "TARGET_HARD_FLOAT"
580  "adf%?d\\t%0, %1, %2"
581[(set_attr "type" "farith")])
582
583(define_insn "*adddf_esfdf_esfdf"
584  [(set (match_operand:DF 0 "s_register_operand" "=f")
585	(plus:DF (float_extend:DF 
586		  (match_operand:SF 1 "s_register_operand" "f"))
587		 (float_extend:DF
588		  (match_operand:SF 2 "s_register_operand" "f"))))]
589  "TARGET_HARD_FLOAT"
590  "adf%?d\\t%0, %1, %2"
591[(set_attr "type" "farith")])
592
593(define_insn "addxf3"
594  [(set (match_operand:XF 0 "s_register_operand" "=f,f")
595	(plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
596		 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
597  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
598  "@
599   adf%?e\\t%0, %1, %2
600   suf%?e\\t%0, %1, #%N2"
601[(set_attr "type" "farith")])
602
603(define_insn "subdi3"
604  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
605	(minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
606		  (match_operand:DI 2 "s_register_operand" "r,0,0")))
607   (clobber (reg:CC 24))]
608  ""
609  "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
610[(set_attr "conds" "clob")
611 (set_attr "length" "8")])
612
613(define_insn "*subdi_di_zesidi"
614  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
615	(minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
616		  (zero_extend:DI
617		   (match_operand:SI 2 "s_register_operand" "r,r"))))
618   (clobber (reg:CC 24))]
619  ""
620  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
621[(set_attr "conds" "clob")
622 (set_attr "length" "8")])
623
624(define_insn "*subdi_di_sesidi"
625  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
626	(minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
627		  (sign_extend:DI
628		   (match_operand:SI 2 "s_register_operand" "r,r"))))
629   (clobber (reg:CC 24))]
630  ""
631  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
632[(set_attr "conds" "clob")
633 (set_attr "length" "8")])
634
635(define_insn "*subdi_zesidi_di"
636  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
637	(minus:DI (zero_extend:DI
638		   (match_operand:SI 2 "s_register_operand" "r,r"))
639		  (match_operand:DI 1 "s_register_operand" "?r,0")))
640   (clobber (reg:CC 24))]
641  ""
642  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
643[(set_attr "conds" "clob")
644 (set_attr "length" "8")])
645
646(define_insn "*subdi_sesidi_di"
647  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
648	(minus:DI (sign_extend:DI
649		   (match_operand:SI 2 "s_register_operand" "r,r"))
650		  (match_operand:DI 1 "s_register_operand" "?r,0")))
651   (clobber (reg:CC 24))]
652  ""
653  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
654[(set_attr "conds" "clob")
655 (set_attr "length" "8")])
656
657(define_insn "*subdi_zesidi_zesidi"
658  [(set (match_operand:DI 0 "s_register_operand" "=r")
659	(minus:DI (zero_extend:DI
660		   (match_operand:SI 1 "s_register_operand" "r"))
661		  (zero_extend:DI
662		   (match_operand:SI 2 "s_register_operand" "r"))))
663   (clobber (reg:CC 24))]
664  ""
665  "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
666[(set_attr "conds" "clob")
667 (set_attr "length" "8")])
668
669(define_expand "subsi3"
670  [(set (match_operand:SI 0 "s_register_operand" "")
671	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
672		  (match_operand:SI 2 "s_register_operand" "")))]
673  ""
674  "
675  if (GET_CODE (operands[1]) == CONST_INT)
676    {
677      arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
678			  operands[2],
679			  (reload_in_progress || reload_completed ? 0
680			   : preserve_subexpressions_p ()));
681      DONE;
682    }
683")
684
685(define_insn "*subsi3_insn"
686  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
687	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
688		  (match_operand:SI 2 "s_register_operand" "r,r")))]
689  ""
690  "@
691   rsb%?\\t%0, %2, %1
692   #"
693[(set_attr "length" "4,16")])
694
695(define_split
696  [(set (match_operand:SI 0 "s_register_operand" "")
697	(minus:SI (match_operand:SI 1 "const_int_operand" "")
698		  (match_operand:SI 2 "s_register_operand" "")))]
699  "! const_ok_for_arm (INTVAL (operands[1]))"
700  [(clobber (const_int 0))]
701  "
702  arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
703		      operands[2], 0);
704  DONE;
705")
706
707(define_insn "*subsi3_compare0"
708  [(set (reg:CC_NOOV 24)
709	(compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
710				 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
711			 (const_int 0)))
712   (set (match_operand:SI 0 "s_register_operand" "=r,r")
713	(minus:SI (match_dup 1) (match_dup 2)))]
714  ""
715  "@
716   sub%?s\\t%0, %1, %2
717   rsb%?s\\t%0, %2, %1"
718[(set_attr "conds" "set")])
719
720(define_insn "decscc"
721  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
722        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
723		  (match_operator:SI 2 "comparison_operator"
724                   [(match_operand 3 "cc_register" "") (const_int 0)])))]
725  ""
726  "@
727  sub%d2\\t%0, %1, #1
728  mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
729[(set_attr "conds" "use")
730 (set_attr "length" "*,8")])
731
732(define_insn "subsf3"
733  [(set (match_operand:SF 0 "s_register_operand" "=f,f")
734	(minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
735		  (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
736  "TARGET_HARD_FLOAT"
737  "@
738   suf%?s\\t%0, %1, %2
739   rsf%?s\\t%0, %2, %1"
740[(set_attr "type" "farith")])
741
742(define_insn "subdf3"
743  [(set (match_operand:DF 0 "s_register_operand" "=f,f")
744	(minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
745		  (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
746  "TARGET_HARD_FLOAT"
747  "@
748   suf%?d\\t%0, %1, %2
749   rsf%?d\\t%0, %2, %1"
750[(set_attr "type" "farith")])
751
752(define_insn "*subdf_esfdf_df"
753  [(set (match_operand:DF 0 "s_register_operand" "=f")
754	(minus:DF (float_extend:DF
755		   (match_operand:SF 1 "s_register_operand" "f"))
756		  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
757  "TARGET_HARD_FLOAT"
758  "suf%?d\\t%0, %1, %2"
759[(set_attr "type" "farith")])
760
761(define_insn "*subdf_df_esfdf"
762  [(set (match_operand:DF 0 "s_register_operand" "=f,f")
763	(minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
764		  (float_extend:DF
765		   (match_operand:SF 2 "s_register_operand" "f,f"))))]
766  "TARGET_HARD_FLOAT"
767  "@
768   suf%?d\\t%0, %1, %2
769   rsf%?d\\t%0, %2, %1"
770[(set_attr "type" "farith")])
771
772(define_insn "*subdf_esfdf_esfdf"
773  [(set (match_operand:DF 0 "s_register_operand" "=f")
774	(minus:DF (float_extend:DF
775		   (match_operand:SF 1 "s_register_operand" "f"))
776		  (float_extend:DF
777		   (match_operand:SF 2 "s_register_operand" "f"))))]
778  "TARGET_HARD_FLOAT"
779  "suf%?d\\t%0, %1, %2"
780[(set_attr "type" "farith")])
781
782(define_insn "subxf3"
783  [(set (match_operand:XF 0 "s_register_operand" "=f,f")
784	(minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
785		  (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
786  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
787  "@
788   suf%?e\\t%0, %1, %2
789   rsf%?e\\t%0, %2, %1"
790[(set_attr "type" "farith")])
791
792;; Multiplication insns
793
794;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
795(define_insn "mulsi3"
796  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
797	(mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
798		 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
799  ""
800  "mul%?\\t%0, %2, %1"
801[(set_attr "type" "mult")])
802
803(define_insn "*mulsi3_compare0"
804  [(set (reg:CC_NOOV 24)
805	(compare:CC_NOOV (mult:SI
806			  (match_operand:SI 2 "s_register_operand" "r,r")
807			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
808			 (const_int 0)))
809   (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
810	(mult:SI (match_dup 2) (match_dup 1)))]
811  ""
812  "mul%?s\\t%0, %2, %1"
813[(set_attr "conds" "set")
814 (set_attr "type" "mult")])
815
816(define_insn "*mulsi_compare0_scratch"
817  [(set (reg:CC_NOOV 24)
818	(compare:CC_NOOV (mult:SI
819			  (match_operand:SI 2 "s_register_operand" "r,r")
820			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
821			 (const_int 0)))
822   (clobber (match_scratch:SI 0 "=&r,&r"))]
823  ""
824  "mul%?s\\t%0, %2, %1"
825[(set_attr "conds" "set")
826 (set_attr "type" "mult")])
827
828;; Unnamed templates to match MLA instruction.
829
830(define_insn "*mulsi3addsi"
831  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
832	(plus:SI
833	  (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
834		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
835	  (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
836  ""
837  "mla%?\\t%0, %2, %1, %3"
838[(set_attr "type" "mult")])
839
840(define_insn "*mulsi3addsi_compare0"
841  [(set (reg:CC_NOOV 24)
842	(compare:CC_NOOV (plus:SI
843			  (mult:SI
844			   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
845			   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
846			  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
847			 (const_int 0)))
848   (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
849	(plus:SI (mult:SI (match_dup 2) (match_dup 1))
850		 (match_dup 3)))]
851  ""
852  "mla%?s\\t%0, %2, %1, %3"
853[(set_attr "conds" "set")
854 (set_attr "type" "mult")])
855
856(define_insn "*mulsi3addsi_compare0_scratch"
857  [(set (reg:CC_NOOV 24)
858	(compare:CC_NOOV (plus:SI
859			  (mult:SI
860			   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
861			   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
862			  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
863			 (const_int 0)))
864   (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
865  ""
866  "mla%?s\\t%0, %2, %1, %3"
867[(set_attr "conds" "set")
868 (set_attr "type" "mult")])
869
870(define_insn "mulsidi3"
871  [(set (match_operand:DI 0 "s_register_operand" "=&r")
872      (mult:DI (sign_extend:DI
873                (match_operand:SI 1 "s_register_operand" "%r"))
874               (sign_extend:DI
875               (match_operand:SI 2 "s_register_operand" "r"))))]
876  "arm_fast_multiply"
877  "smull%?\\t%Q0, %R0, %1, %2"
878[(set_attr "type" "mult")])
879
880(define_insn "umulsidi3"
881  [(set (match_operand:DI 0 "s_register_operand" "=&r")
882      (mult:DI (zero_extend:DI
883                (match_operand:SI 1 "s_register_operand" "%r"))
884               (zero_extend:DI
885                (match_operand:SI 2 "s_register_operand" "r"))))]
886  "arm_fast_multiply"
887  "umull%?\\t%Q0, %R0, %1, %2"
888[(set_attr "type" "mult")])
889
890(define_insn "smulsi3_highpart"
891  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
892	(truncate:SI
893	 (lshiftrt:DI
894	  (mult:DI (sign_extend:DI
895		    (match_operand:SI 1 "s_register_operand" "%r,0"))
896		   (sign_extend:DI
897		    (match_operand:SI 2 "s_register_operand" "r,r")))
898	  (const_int 32))))
899   (clobber (match_scratch:SI 3 "=&r,&r"))]
900  "arm_fast_multiply"
901  "smull%?\\t%3, %0, %2, %1"
902[(set_attr "type" "mult")])
903
904(define_insn "umulsi3_highpart"
905  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
906	(truncate:SI
907	 (lshiftrt:DI
908	  (mult:DI (zero_extend:DI
909		    (match_operand:SI 1 "s_register_operand" "%r,0"))
910		   (zero_extend:DI
911		    (match_operand:SI 2 "s_register_operand" "r,r")))
912	  (const_int 32))))
913   (clobber (match_scratch:SI 3 "=&r,&r"))]
914  "arm_fast_multiply"
915  "umull%?\\t%3, %0, %2, %1"
916[(set_attr "type" "mult")])
917
918(define_insn "mulsf3"
919  [(set (match_operand:SF 0 "s_register_operand" "=f")
920	(mult:SF (match_operand:SF 1 "s_register_operand" "f")
921		 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
922  "TARGET_HARD_FLOAT"
923  "fml%?s\\t%0, %1, %2"
924[(set_attr "type" "ffmul")])
925
926(define_insn "muldf3"
927  [(set (match_operand:DF 0 "s_register_operand" "=f")
928	(mult:DF (match_operand:DF 1 "s_register_operand" "f")
929		 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
930  "TARGET_HARD_FLOAT"
931  "muf%?d\\t%0, %1, %2"
932[(set_attr "type" "fmul")])
933
934(define_insn "*muldf_esfdf_df"
935  [(set (match_operand:DF 0 "s_register_operand" "=f")
936	(mult:DF (float_extend:DF
937		  (match_operand:SF 1 "s_register_operand" "f"))
938		 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
939  "TARGET_HARD_FLOAT"
940  "muf%?d\\t%0, %1, %2"
941[(set_attr "type" "fmul")])
942
943(define_insn "*muldf_df_esfdf"
944  [(set (match_operand:DF 0 "s_register_operand" "=f")
945	(mult:DF (match_operand:DF 1 "s_register_operand" "f")
946		 (float_extend:DF
947		  (match_operand:SF 2 "s_register_operand" "f"))))]
948  "TARGET_HARD_FLOAT"
949  "muf%?d\\t%0, %1, %2"
950[(set_attr "type" "fmul")])
951
952(define_insn "*muldf_esfdf_esfdf"
953  [(set (match_operand:DF 0 "s_register_operand" "=f")
954	(mult:DF (float_extend:DF
955		  (match_operand:SF 1 "s_register_operand" "f"))
956		 (float_extend:DF
957		  (match_operand:SF 2 "s_register_operand" "f"))))]
958  "TARGET_HARD_FLOAT"
959  "muf%?d\\t%0, %1, %2"
960[(set_attr "type" "fmul")])
961
962(define_insn "mulxf3"
963  [(set (match_operand:XF 0 "s_register_operand" "=f")
964	(mult:XF (match_operand:XF 1 "s_register_operand" "f")
965		 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
966  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
967  "muf%?e\\t%0, %1, %2"
968[(set_attr "type" "fmul")])
969
970;; Division insns
971
972(define_insn "divsf3"
973  [(set (match_operand:SF 0 "s_register_operand" "=f,f")
974	(div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
975		(match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
976  "TARGET_HARD_FLOAT"
977  "@
978   fdv%?s\\t%0, %1, %2
979   frd%?s\\t%0, %2, %1"
980[(set_attr "type" "fdivs")])
981
982(define_insn "divdf3"
983  [(set (match_operand:DF 0 "s_register_operand" "=f,f")
984	(div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
985		(match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
986  "TARGET_HARD_FLOAT"
987  "@
988   dvf%?d\\t%0, %1, %2
989   rdf%?d\\t%0, %2, %1"
990[(set_attr "type" "fdivd")])
991
992(define_insn "*divdf_esfdf_df"
993  [(set (match_operand:DF 0 "s_register_operand" "=f")
994	(div:DF (float_extend:DF
995		 (match_operand:SF 1 "s_register_operand" "f"))
996		(match_operand:DF 2 "fpu_rhs_operand" "fG")))]
997  "TARGET_HARD_FLOAT"
998  "dvf%?d\\t%0, %1, %2"
999[(set_attr "type" "fdivd")])
1000
1001(define_insn "*divdf_df_esfdf"
1002  [(set (match_operand:DF 0 "s_register_operand" "=f")
1003	(div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1004		(float_extend:DF
1005		 (match_operand:SF 2 "s_register_operand" "f"))))]
1006  "TARGET_HARD_FLOAT"
1007  "rdf%?d\\t%0, %2, %1"
1008[(set_attr "type" "fdivd")])
1009
1010(define_insn "*divdf_esfdf_esfdf"
1011  [(set (match_operand:DF 0 "s_register_operand" "=f")
1012	(div:DF (float_extend:DF
1013		 (match_operand:SF 1 "s_register_operand" "f"))
1014		(float_extend:DF
1015		 (match_operand:SF 2 "s_register_operand" "f"))))]
1016  "TARGET_HARD_FLOAT"
1017  "dvf%?d\\t%0, %1, %2"
1018[(set_attr "type" "fdivd")])
1019
1020(define_insn "divxf3"
1021  [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1022	(div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1023		(match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1024  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1025  "@
1026   dvf%?e\\t%0, %1, %2
1027   rdf%?e\\t%0, %2, %1"
1028[(set_attr "type" "fdivx")])
1029
1030;; Modulo insns
1031
1032(define_insn "modsf3"
1033  [(set (match_operand:SF 0 "s_register_operand" "=f")
1034	(mod:SF (match_operand:SF 1 "s_register_operand" "f")
1035		(match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1036  "TARGET_HARD_FLOAT"
1037  "rmf%?s\\t%0, %1, %2"
1038[(set_attr "type" "fdivs")])
1039
1040(define_insn "moddf3"
1041  [(set (match_operand:DF 0 "s_register_operand" "=f")
1042	(mod:DF (match_operand:DF 1 "s_register_operand" "f")
1043		(match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1044  "TARGET_HARD_FLOAT"
1045  "rmf%?d\\t%0, %1, %2"
1046[(set_attr "type" "fdivd")])
1047
1048(define_insn "*moddf_esfdf_df"
1049  [(set (match_operand:DF 0 "s_register_operand" "=f")
1050	(mod:DF (float_extend:DF
1051		 (match_operand:SF 1 "s_register_operand" "f"))
1052		(match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1053  "TARGET_HARD_FLOAT"
1054  "rmf%?d\\t%0, %1, %2"
1055[(set_attr "type" "fdivd")])
1056
1057(define_insn "*moddf_df_esfdf"
1058  [(set (match_operand:DF 0 "s_register_operand" "=f")
1059	(mod:DF (match_operand:DF 1 "s_register_operand" "f")
1060		(float_extend:DF
1061		 (match_operand:SF 2 "s_register_operand" "f"))))]
1062  "TARGET_HARD_FLOAT"
1063  "rmf%?d\\t%0, %1, %2"
1064[(set_attr "type" "fdivd")])
1065
1066(define_insn "*moddf_esfdf_esfdf"
1067  [(set (match_operand:DF 0 "s_register_operand" "=f")
1068	(mod:DF (float_extend:DF
1069		 (match_operand:SF 1 "s_register_operand" "f"))
1070		(float_extend:DF
1071		 (match_operand:SF 2 "s_register_operand" "f"))))]
1072  "TARGET_HARD_FLOAT"
1073  "rmf%?d\\t%0, %1, %2"
1074[(set_attr "type" "fdivd")])
1075
1076(define_insn "modxf3"
1077  [(set (match_operand:XF 0 "s_register_operand" "=f")
1078	(mod:XF (match_operand:XF 1 "s_register_operand" "f")
1079		(match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1080  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1081  "rmf%?e\\t%0, %1, %2"
1082[(set_attr "type" "fdivx")])
1083
1084;; Boolean and,ior,xor insns
1085
1086(define_insn "anddi3"
1087  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1088	(and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1089		(match_operand:DI 2 "s_register_operand" "r,0")))]
1090  ""
1091  "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2"
1092[(set_attr "length" "8")])
1093
1094(define_insn "*anddi_zesidi_di"
1095  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1096	(and:DI (zero_extend:DI
1097		 (match_operand:SI 2 "s_register_operand" "r,r"))
1098		(match_operand:DI 1 "s_register_operand" "?r,0")))]
1099  ""
1100  "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0"
1101[(set_attr "length" "8")])
1102
1103(define_insn "*anddi_sesdi_di"
1104  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1105	(and:DI (sign_extend:DI
1106		 (match_operand:SI 2 "s_register_operand" "r,r"))
1107		(match_operand:DI 1 "s_register_operand" "?r,0")))]
1108  ""
1109  "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31"
1110[(set_attr "length" "8")])
1111
1112(define_expand "andsi3"
1113  [(set (match_operand:SI 0 "s_register_operand" "")
1114	(and:SI (match_operand:SI 1 "s_register_operand" "")
1115		(match_operand:SI 2 "reg_or_int_operand" "")))]
1116  ""
1117  "
1118  if (GET_CODE (operands[2]) == CONST_INT)
1119    {
1120      arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1121			  operands[1],
1122			  (reload_in_progress || reload_completed
1123			   ? 0 : preserve_subexpressions_p ()));
1124      DONE;
1125    }
1126")
1127
1128(define_insn "*andsi3_insn"
1129  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1130	(and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1131		(match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1132  ""
1133  "@
1134   and%?\\t%0, %1, %2
1135   bic%?\\t%0, %1, #%B2
1136   #"
1137[(set_attr "length" "4,4,16")])
1138
1139(define_split
1140  [(set (match_operand:SI 0 "s_register_operand" "")
1141	(and:SI (match_operand:SI 1 "s_register_operand" "")
1142		(match_operand:SI 2 "const_int_operand" "")))]
1143  "! (const_ok_for_arm (INTVAL (operands[2]))
1144      || const_ok_for_arm (~ INTVAL (operands[2])))"
1145  [(clobber (const_int 0))]
1146  "
1147  arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1148		       operands[1], 0);
1149  DONE;
1150")
1151
1152(define_insn "*andsi3_compare0"
1153  [(set (reg:CC_NOOV 24)
1154	(compare:CC_NOOV
1155	 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1156		 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1157	 (const_int 0)))
1158   (set (match_operand:SI 0 "s_register_operand" "=r,r")
1159	(and:SI (match_dup 1) (match_dup 2)))]
1160  ""
1161  "@
1162   and%?s\\t%0, %1, %2
1163   bic%?s\\t%0, %1, #%B2"
1164[(set_attr "conds" "set")])
1165
1166(define_insn "*andsi3_compare0_scratch"
1167  [(set (reg:CC_NOOV 24)
1168	(compare:CC_NOOV
1169	 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1170		 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1171	 (const_int 0)))
1172   (clobber (match_scratch:SI 3 "=X,r"))]
1173  ""
1174  "@
1175   tst%?\\t%0, %1
1176   bic%?s\\t%3, %0, #%B1"
1177[(set_attr "conds" "set")])
1178
1179(define_insn "*zeroextractsi_compare0_scratch"
1180  [(set (reg:CC_NOOV 24)
1181	(compare:CC_NOOV (zero_extract:SI
1182			  (match_operand:SI 0 "s_register_operand" "r")
1183		 	  (match_operand 1 "const_int_operand" "n")
1184			  (match_operand 2 "const_int_operand" "n"))
1185			 (const_int 0)))]
1186  "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1187   && INTVAL (operands[1]) > 0 
1188   && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1189   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1190  "*
1191  operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1192			 << INTVAL (operands[2]));
1193  output_asm_insn (\"tst%?\\t%0, %1\", operands);
1194  return \"\";
1195"
1196[(set_attr "conds" "set")])
1197
1198(define_insn "*ne_zeroextractsi"
1199  [(set (match_operand:SI 0 "s_register_operand" "=r")
1200	(ne:SI (zero_extract:SI
1201		(match_operand:SI 1 "s_register_operand" "r")
1202		(match_operand:SI 2 "const_int_operand" "n")
1203		(match_operand:SI 3 "const_int_operand" "n"))
1204	       (const_int 0)))]
1205  "INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1206   && INTVAL (operands[2]) > 0 
1207   && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1208   && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32"
1209  "*
1210  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1211			 << INTVAL (operands[3]));
1212  output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1213  return \"movne\\t%0, #1\";
1214"
1215[(set_attr "conds" "clob")
1216 (set_attr "length" "8")])
1217
1218;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1219;;; represented by the bitfield, then this will produce incorrect results.
1220;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1221;;; which have a real bitfield insert instruction, the truncation happens
1222;;; in the bitfield insert instruction itself.  Since arm does not have a
1223;;; bitfield insert instruction, we would have to emit code here to truncate
1224;;; the value before we insert.  This loses some of the advantage of having
1225;;; this insv pattern, so this pattern needs to be reevalutated.
1226
1227(define_expand "insv"
1228  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1229                         (match_operand:SI 1 "general_operand" "")
1230                         (match_operand:SI 2 "general_operand" ""))
1231        (match_operand:SI 3 "nonmemory_operand" ""))]
1232  ""
1233  "
1234{
1235  int start_bit = INTVAL (operands[2]);
1236  int width = INTVAL (operands[1]);
1237  HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1238  rtx target, subtarget;
1239  
1240  target = operands[0];
1241  /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1242     subreg as the final target.  */
1243  if (GET_CODE (target) == SUBREG)
1244    {
1245      subtarget = gen_reg_rtx (SImode);
1246      if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1247	  < GET_MODE_SIZE (SImode))
1248        target = SUBREG_REG (target);
1249    }
1250  else
1251    subtarget = target;    
1252    
1253  if (GET_CODE (operands[3]) == CONST_INT)
1254    {
1255      /* Since we are inserting a known constant, we may be able to
1256	 reduce the number of bits that we have to clear so that
1257	 the mask becomes simple.  */
1258      /* ??? This code does not check to see if the new mask is actually
1259	 simpler.  It may not be.  */
1260      rtx op1 = gen_reg_rtx (SImode);
1261      /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1262	 start of this pattern.  */
1263      HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1264      HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1265
1266      emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1267      emit_insn (gen_iorsi3 (subtarget, op1,
1268			     GEN_INT (op3_value << start_bit)));
1269    }
1270  else if (start_bit == 0
1271	   && ! (const_ok_for_arm (mask)
1272		 || const_ok_for_arm (~mask)))
1273    {
1274      /* A Trick, since we are setting the bottom bits in the word,
1275	 we can shift operand[3] up, operand[0] down, OR them together
1276	 and rotate the result back again.  This takes 3 insns, and
1277	 the third might be mergable into another op.  */
1278      /* The shift up copes with the possibility that operand[3] is
1279         wider than the bitfield.  */
1280      rtx op0 = gen_reg_rtx (SImode);
1281      rtx op1 = gen_reg_rtx (SImode);
1282
1283      emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1284      emit_insn (gen_iorsi3 (op1, gen_rtx_LSHIFTRT (SImode, operands[0],
1285							    operands[1]),
1286			     op0));
1287      emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1288    }
1289  else if ((width + start_bit == 32)
1290	   && ! (const_ok_for_arm (mask)
1291		 || const_ok_for_arm (~mask)))
1292    {
1293      /* Similar trick, but slightly less efficient.  */
1294
1295      rtx op0 = gen_reg_rtx (SImode);
1296      rtx op1 = gen_reg_rtx (SImode);
1297
1298      emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1299      emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1300      emit_insn (gen_iorsi3 (subtarget,
1301			     gen_rtx_LSHIFTRT (SImode, op1, operands[1]),
1302			     op0));
1303    }
1304  else
1305    {
1306      rtx op0 = GEN_INT (mask);
1307      rtx op1 = gen_reg_rtx (SImode);
1308      rtx op2 = gen_reg_rtx (SImode);
1309
1310      if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1311	{
1312	  rtx tmp = gen_reg_rtx (SImode);
1313
1314	  emit_insn (gen_movsi (tmp, op0));
1315	  op0 = tmp;
1316	}
1317
1318      /* Mask out any bits in operand[3] that are not needed.  */
1319      emit_insn (gen_andsi3 (op1, operands[3], op0));
1320
1321      if (GET_CODE (op0) == CONST_INT
1322	  && (const_ok_for_arm (mask << start_bit)
1323	      || const_ok_for_arm (~ (mask << start_bit))))
1324	{
1325	  op0 = GEN_INT (~(mask << start_bit));
1326	  emit_insn (gen_andsi3 (op2, operands[0], op0));
1327	}
1328      else
1329	{
1330	  if (GET_CODE (op0) == CONST_INT)
1331	    {
1332	      rtx tmp = gen_reg_rtx (SImode);
1333
1334	      emit_insn (gen_movsi (tmp, op0));
1335	      op0 = tmp;
1336	    }
1337
1338	  if (start_bit != 0)
1339	    op0 = gen_rtx_ASHIFT (SImode, op0, operands[2]);
1340	    
1341	  emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1342	}
1343
1344      if (start_bit != 0)
1345	op1 = gen_rtx_ASHIFT (SImode, op1, operands[2]);
1346
1347      emit_insn (gen_iorsi3 (subtarget, op1, op2));
1348    }
1349
1350  if (subtarget != target)
1351    {
1352      /* If TARGET is still a SUBREG, then it must be wider than a word,
1353	 so we must be careful only to set the subword we were asked to. */
1354      if (GET_CODE (target) == SUBREG)
1355	emit_move_insn (target, subtarget);
1356      else
1357	emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1358    }
1359
1360  DONE;
1361}
1362")
1363
1364;; constants for op 2 will never be given to these patterns.
1365(define_insn "*anddi_notdi_di"
1366  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1367	(and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1368		(match_operand:DI 1 "s_register_operand" "0,r")))]
1369  ""
1370  "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2"
1371[(set_attr "length" "8")])
1372  
1373(define_insn "*anddi_notzesidi_di"
1374  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1375	(and:DI (not:DI (zero_extend:DI
1376			 (match_operand:SI 2 "s_register_operand" "r,r")))
1377		(match_operand:DI 1 "s_register_operand" "0,?r")))]
1378  ""
1379  "@
1380   bic%?\\t%Q0, %Q1, %2
1381   bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1382[(set_attr "length" "4,8")])
1383  
1384(define_insn "*anddi_notsesidi_di"
1385  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1386	(and:DI (not:DI (sign_extend:DI
1387			 (match_operand:SI 2 "s_register_operand" "r,r")))
1388		(match_operand:DI 1 "s_register_operand" "?r,0")))]
1389  ""
1390  "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
1391[(set_attr "length" "8")])
1392  
1393(define_insn "andsi_notsi_si"
1394  [(set (match_operand:SI 0 "s_register_operand" "=r")
1395	(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1396		(match_operand:SI 1 "s_register_operand" "r")))]
1397  ""
1398  "bic%?\\t%0, %1, %2")
1399
1400(define_insn "andsi_not_shiftsi_si"
1401  [(set (match_operand:SI 0 "s_register_operand" "=r")
1402	(and:SI (not:SI (match_operator:SI 4 "shift_operator"
1403			 [(match_operand:SI 2 "s_register_operand" "r")
1404			  (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1405		(match_operand:SI 1 "s_register_operand" "r")))]
1406  ""
1407  "bic%?\\t%0, %1, %2%S4")
1408
1409(define_insn "*andsi_notsi_si_compare0"
1410  [(set (reg:CC_NOOV 24)
1411	(compare:CC_NOOV
1412	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1413		 (match_operand:SI 1 "s_register_operand" "r"))
1414	 (const_int 0)))
1415   (set (match_operand:SI 0 "s_register_operand" "=r")
1416	(and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1417  ""
1418  "bic%?s\\t%0, %1, %2"
1419[(set_attr "conds" "set")])
1420
1421(define_insn "*andsi_notsi_si_compare0_scratch"
1422  [(set (reg:CC_NOOV 24)
1423	(compare:CC_NOOV
1424	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1425		 (match_operand:SI 1 "s_register_operand" "r"))
1426	 (const_int 0)))
1427   (clobber (match_scratch:SI 0 "=r"))]
1428  ""
1429  "bic%?s\\t%0, %1, %2"
1430[(set_attr "conds" "set")])
1431
1432(define_insn "iordi3"
1433  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1434	(ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1435		(match_operand:DI 2 "s_register_operand" "r")))]
1436  ""
1437  "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2"
1438[(set_attr "length" "8")])
1439
1440(define_insn "*iordi_zesidi_di"
1441  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1442	(ior:DI (zero_extend:DI
1443		 (match_operand:SI 2 "s_register_operand" "r,r"))
1444		(match_operand:DI 1 "s_register_operand" "0,?r")))]
1445  ""
1446  "@
1447   orr%?\\t%Q0, %Q1, %2
1448   orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1449[(set_attr "length" "4,8")])
1450
1451(define_insn "*iordi_sesidi_di"
1452  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1453	(ior:DI (sign_extend:DI
1454		 (match_operand:SI 2 "s_register_operand" "r,r"))
1455		(match_operand:DI 1 "s_register_operand" "?r,0")))]
1456  ""
1457  "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1458[(set_attr "length" "8")])
1459
1460(define_expand "iorsi3"
1461  [(set (match_operand:SI 0 "s_register_operand" "")
1462	(ior:SI (match_operand:SI 1 "s_register_operand" "")
1463		(match_operand:SI 2 "reg_or_int_operand" "")))]
1464  ""
1465  "
1466  if (GET_CODE (operands[2]) == CONST_INT)
1467    {
1468      arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1469			  operands[1],
1470			  (reload_in_progress || reload_completed
1471			   ? 0 : preserve_subexpressions_p ()));
1472      DONE;
1473    }
1474")
1475
1476(define_insn "*iorsi3_insn"
1477  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1478	(ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1479		(match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1480  ""
1481  "@
1482   orr%?\\t%0, %1, %2
1483   #"
1484[(set_attr "length" "4,16")])
1485
1486(define_split
1487  [(set (match_operand:SI 0 "s_register_operand" "")
1488	(ior:SI (match_operand:SI 1 "s_register_operand" "")
1489		(match_operand:SI 2 "const_int_operand" "")))]
1490  "! const_ok_for_arm (INTVAL (operands[2]))"
1491  [(clobber (const_int 0))]
1492  "
1493  arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1494		      operands[1], 0);
1495  DONE;
1496")
1497  
1498(define_insn "*iorsi3_compare0"
1499  [(set (reg:CC_NOOV 24)
1500	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1501				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1502			 (const_int 0)))
1503   (set (match_operand:SI 0 "s_register_operand" "=r")
1504	(ior:SI (match_dup 1) (match_dup 2)))]
1505  ""
1506  "orr%?s\\t%0, %1, %2"
1507[(set_attr "conds" "set")])
1508
1509(define_insn "*iorsi3_compare0_scratch"
1510  [(set (reg:CC_NOOV 24)
1511	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1512				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1513			 (const_int 0)))
1514   (clobber (match_scratch:SI 0 "=r"))]
1515  ""
1516  "orr%?s\\t%0, %1, %2"
1517[(set_attr "conds" "set")])
1518
1519(define_insn "xordi3"
1520  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1521	(xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1522		(match_operand:DI 2 "s_register_operand" "r,0")))]
1523  ""
1524  "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2"
1525[(set_attr "length" "8")])
1526
1527(define_insn "*xordi_zesidi_di"
1528  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1529	(xor:DI (zero_extend:DI
1530		 (match_operand:SI 2 "s_register_operand" "r,r"))
1531		(match_operand:DI 1 "s_register_operand" "0,?r")))]
1532  ""
1533  "@
1534   eor%?\\t%Q0, %Q1, %2
1535   eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1536[(set_attr "length" "4,8")])
1537
1538(define_insn "*xordi_sesidi_di"
1539  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1540	(xor:DI (sign_extend:DI
1541		 (match_operand:SI 2 "s_register_operand" "r,r"))
1542		(match_operand:DI 1 "s_register_operand" "?r,0")))]
1543  ""
1544  "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1545[(set_attr "length" "8")])
1546
1547(define_insn "xorsi3"
1548  [(set (match_operand:SI 0 "s_register_operand" "=r")
1549	(xor:SI (match_operand:SI 1 "s_register_operand" "r")
1550		(match_operand:SI 2 "arm_rhs_operand" "rI")))]
1551  ""
1552  "eor%?\\t%0, %1, %2")
1553
1554(define_insn "*xorsi3_compare0"
1555  [(set (reg:CC_NOOV 24)
1556	(compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1557				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1558			 (const_int 0)))
1559   (set (match_operand:SI 0 "s_register_operand" "=r")
1560	(xor:SI (match_dup 1) (match_dup 2)))]
1561  ""
1562  "eor%?s\\t%0, %1, %2"
1563[(set_attr "conds" "set")])
1564
1565(define_insn "*xorsi3_compare0_scratch"
1566  [(set (reg:CC_NOOV 24)
1567	(compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1568				 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1569			 (const_int 0)))]
1570  ""
1571  "teq%?\\t%0, %1"
1572[(set_attr "conds" "set")])
1573
1574;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
1575;; (NOT D) we can sometimes merge the final NOT into one of the following
1576;; insns
1577
1578(define_split
1579  [(set (match_operand:SI 0 "s_register_operand" "=r")
1580	(ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1581			(not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1582		(match_operand:SI 3 "arm_rhs_operand" "rI")))
1583   (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1584  ""
1585  [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1586			      (not:SI (match_dup 3))))
1587   (set (match_dup 0) (not:SI (match_dup 4)))]
1588  ""
1589)
1590
1591(define_insn "*andsi_iorsi3_notsi"
1592  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1593	(and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1594			(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1595		(not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1596  ""
1597  "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1598[(set_attr "length" "8")])
1599
1600
1601
1602;; Minimum and maximum insns
1603
1604(define_insn "smaxsi3"
1605  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1606	(smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1607		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1608   (clobber (reg:CC 24))]
1609  ""
1610  "@
1611   cmp\\t%1, %2\;movlt\\t%0, %2
1612   cmp\\t%1, %2\;movge\\t%0, %1
1613   cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1614[(set_attr "conds" "clob")
1615 (set_attr "length" "8,8,12")])
1616
1617(define_insn "sminsi3"
1618  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1619	(smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1620		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1621   (clobber (reg:CC 24))]
1622  ""
1623  "@
1624   cmp\\t%1, %2\;movge\\t%0, %2
1625   cmp\\t%1, %2\;movlt\\t%0, %1
1626   cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1627[(set_attr "conds" "clob")
1628 (set_attr "length" "8,8,12")])
1629
1630(define_insn "umaxsi3"
1631  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1632	(umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1633		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1634   (clobber (reg:CC 24))]
1635  ""
1636  "@
1637   cmp\\t%1, %2\;movcc\\t%0, %2
1638   cmp\\t%1, %2\;movcs\\t%0, %1
1639   cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1640[(set_attr "conds" "clob")
1641 (set_attr "length" "8,8,12")])
1642
1643(define_insn "uminsi3"
1644  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1645	(umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1646		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1647   (clobber (reg:CC 24))]
1648  ""
1649  "@
1650   cmp\\t%1, %2\;movcs\\t%0, %2
1651   cmp\\t%1, %2\;movcc\\t%0, %1
1652   cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1653[(set_attr "conds" "clob")
1654 (set_attr "length" "8,8,12")])
1655
1656(define_insn "*store_minmaxsi"
1657  [(set (match_operand:SI 0 "memory_operand" "=m")
1658	(match_operator:SI 3 "minmax_operator"
1659	 [(match_operand:SI 1 "s_register_operand" "r")
1660	  (match_operand:SI 2 "s_register_operand" "r")]))
1661   (clobber (reg:CC 24))]
1662  ""
1663  "*
1664  operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1665			 operands[2]);
1666  output_asm_insn (\"cmp\\t%1, %2\", operands);
1667  output_asm_insn (\"str%d3\\t%1, %0\", operands);
1668  output_asm_insn (\"str%D3\\t%2, %0\", operands);
1669  return \"\";
1670"
1671[(set_attr "conds" "clob")
1672 (set_attr "length" "12")
1673 (set_attr "type" "store1")])
1674
1675; Reject the frame pointer in operand[1], since reloading this after
1676; it has been eliminated can cause carnage.
1677(define_insn "*minmax_arithsi"
1678  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1679	(match_operator:SI 4 "shiftable_operator"
1680	 [(match_operator:SI 5 "minmax_operator"
1681	   [(match_operand:SI 2 "s_register_operand" "r,r")
1682	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1683	  (match_operand:SI 1 "s_register_operand" "0,?r")]))
1684   (clobber (reg:CC 24))]
1685  "GET_CODE (operands[1]) != REG
1686   || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
1687       && REGNO(operands[1]) != ARG_POINTER_REGNUM)"
1688  "*
1689{
1690  enum rtx_code code = GET_CODE (operands[4]);
1691
1692  operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1693			 operands[3]);
1694  output_asm_insn (\"cmp\\t%2, %3\", operands);
1695  output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1696  if (which_alternative != 0 || operands[3] != const0_rtx
1697      || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1698    output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1699  return \"\";
1700}
1701"
1702[(set_attr "conds" "clob")
1703 (set_attr "length" "12")])
1704
1705
1706;; Shift and rotation insns
1707
1708(define_expand "ashlsi3"
1709  [(set (match_operand:SI 0 "s_register_operand" "")
1710	(ashift:SI (match_operand:SI 1 "s_register_operand" "")
1711		   (match_operand:SI 2 "arm_rhs_operand" "")))]
1712  ""
1713  "
1714  if (GET_CODE (operands[2]) == CONST_INT
1715      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1716    {
1717      emit_insn (gen_movsi (operands[0], const0_rtx));
1718      DONE;
1719    }
1720")
1721
1722(define_expand "ashrsi3"
1723  [(set (match_operand:SI 0 "s_register_operand" "")
1724	(ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1725		     (match_operand:SI 2 "arm_rhs_operand" "")))]
1726  ""
1727  "
1728  if (GET_CODE (operands[2]) == CONST_INT
1729      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1730    operands[2] = GEN_INT (31);
1731")
1732
1733(define_expand "lshrsi3"
1734  [(set (match_operand:SI 0 "s_register_operand" "")
1735	(lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1736		     (match_operand:SI 2 "arm_rhs_operand" "")))]
1737  ""
1738  "
1739  if (GET_CODE (operands[2]) == CONST_INT
1740      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1741    {
1742      emit_insn (gen_movsi (operands[0], const0_rtx));
1743      DONE;
1744    }
1745")
1746
1747(define_expand "rotlsi3"
1748  [(set (match_operand:SI 0 "s_register_operand" "")
1749	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1750		     (match_operand:SI 2 "reg_or_int_operand" "")))]
1751  ""
1752  "
1753  if (GET_CODE (operands[2]) == CONST_INT)
1754    operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1755  else
1756    {
1757      rtx reg = gen_reg_rtx (SImode);
1758      emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1759      operands[2] = reg;
1760    }
1761")
1762
1763(define_expand "rotrsi3"
1764  [(set (match_operand:SI 0 "s_register_operand" "")
1765	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1766		     (match_operand:SI 2 "arm_rhs_operand" "")))]
1767  ""
1768  "
1769  if (GET_CODE (operands[2]) == CONST_INT
1770      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1771    operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1772")
1773
1774(define_insn "*shiftsi3"
1775  [(set (match_operand:SI 0 "s_register_operand" "=r")
1776	(match_operator:SI 3 "shift_operator"
1777	 [(match_operand:SI 1 "s_register_operand" "r")
1778	  (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1779  ""
1780  "mov%?\\t%0, %1%S3")
1781
1782(define_insn "*shiftsi3_compare0"
1783  [(set (reg:CC_NOOV 24)
1784	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1785			  [(match_operand:SI 1 "s_register_operand" "r")
1786			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
1787			 (const_int 0)))
1788   (set (match_operand:SI 0 "s_register_operand" "=r")
1789	(match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1790  ""
1791  "mov%?s\\t%0, %1%S3"
1792[(set_attr "conds" "set")])
1793
1794(define_insn "*shiftsi3_compare0_scratch"
1795  [(set (reg:CC_NOOV 24)
1796	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1797			  [(match_operand:SI 1 "s_register_operand" "r")
1798			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
1799			 (const_int 0)))
1800   (clobber (match_scratch:SI 0 "=r"))]
1801  ""
1802  "mov%?s\\t%0, %1%S3"
1803[(set_attr "conds" "set")])
1804
1805(define_insn "*notsi_shiftsi"
1806  [(set (match_operand:SI 0 "s_register_operand" "=r")
1807	(not:SI (match_operator:SI 3 "shift_operator"
1808		 [(match_operand:SI 1 "s_register_operand" "r")
1809		  (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1810  ""
1811  "mvn%?\\t%0, %1%S3")
1812
1813(define_insn "*notsi_shiftsi_compare0"
1814  [(set (reg:CC_NOOV 24)
1815	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1816			  [(match_operand:SI 1 "s_register_operand" "r")
1817			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1818			 (const_int 0)))
1819   (set (match_operand:SI 0 "s_register_operand" "=r")
1820	(not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1821  ""
1822  "mvn%?s\\t%0, %1%S3"
1823[(set_attr "conds" "set")])
1824
1825(define_insn "*not_shiftsi_compare0_scratch"
1826  [(set (reg:CC_NOOV 24)
1827	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1828			  [(match_operand:SI 1 "s_register_operand" "r")
1829			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1830			 (const_int 0)))
1831   (clobber (match_scratch:SI 0 "=r"))]
1832  ""
1833  "mvn%?s\\t%0, %1%S3"
1834[(set_attr "conds" "set")])
1835
1836
1837;; Unary arithmetic insns
1838
1839(define_insn "negdi2"
1840  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1841	(neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
1842   (clobber (reg:CC 24))]
1843  ""
1844  "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
1845[(set_attr "conds" "clob")
1846 (set_attr "length" "8")])
1847
1848(define_insn "negsi2"
1849  [(set (match_operand:SI 0 "s_register_operand" "=r")
1850	(neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1851  ""
1852  "rsb%?\\t%0, %1, #0")
1853
1854(define_insn "negsf2"
1855  [(set (match_operand:SF 0 "s_register_operand" "=f")
1856	(neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1857  "TARGET_HARD_FLOAT"
1858  "mnf%?s\\t%0, %1"
1859[(set_attr "type" "ffarith")])
1860
1861(define_insn "negdf2"
1862  [(set (match_operand:DF 0 "s_register_operand" "=f")
1863	(neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1864  "TARGET_HARD_FLOAT"
1865  "mnf%?d\\t%0, %1"
1866[(set_attr "type" "ffarith")])
1867
1868(define_insn "*negdf_esfdf"
1869  [(set (match_operand:DF 0 "s_register_operand" "=f")
1870	(neg:DF (float_extend:DF
1871		 (match_operand:SF 1 "s_register_operand" "f"))))]
1872  "TARGET_HARD_FLOAT"
1873  "mnf%?d\\t%0, %1"
1874[(set_attr "type" "ffarith")])
1875
1876(define_insn "negxf2"
1877  [(set (match_operand:XF 0 "s_register_operand" "=f")
1878	(neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1879  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1880  "mnf%?e\\t%0, %1"
1881[(set_attr "type" "ffarith")])
1882
1883;; abssi2 doesn't really clobber the condition codes if a different register
1884;; is being set.  To keep things simple, assume during rtl manipulations that
1885;; it does, but tell the final scan operator the truth.  Similarly for
1886;; (neg (abs...))
1887
1888(define_insn "abssi2"
1889  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1890	(abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1891   (clobber (reg:CC 24))]
1892  ""
1893  "@
1894   cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1895   eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1896[(set_attr "conds" "clob,*")
1897 (set_attr "length" "8")])
1898
1899(define_insn "*neg_abssi2"
1900  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1901	(neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1902   (clobber (reg:CC 24))]
1903  ""
1904  "@
1905   cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1906   eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1907[(set_attr "conds" "clob,*")
1908 (set_attr "length" "8")])
1909
1910(define_insn "abssf2"
1911  [(set (match_operand:SF 0 "s_register_operand" "=f")
1912	 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1913  "TARGET_HARD_FLOAT"
1914  "abs%?s\\t%0, %1"
1915[(set_attr "type" "ffarith")])
1916
1917(define_insn "absdf2"
1918  [(set (match_operand:DF 0 "s_register_operand" "=f")
1919	(abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1920  "TARGET_HARD_FLOAT"
1921  "abs%?d\\t%0, %1"
1922[(set_attr "type" "ffarith")])
1923
1924(define_insn "*absdf_esfdf"
1925  [(set (match_operand:DF 0 "s_register_operand" "=f")
1926	(abs:DF (float_extend:DF
1927		 (match_operand:SF 1 "s_register_operand" "f"))))]
1928  "TARGET_HARD_FLOAT"
1929  "abs%?d\\t%0, %1"
1930[(set_attr "type" "ffarith")])
1931
1932(define_insn "absxf2"
1933  [(set (match_operand:XF 0 "s_register_operand" "=f")
1934	(abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1935  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1936  "abs%?e\\t%0, %1"
1937[(set_attr "type" "ffarith")])
1938
1939(define_insn "sqrtsf2"
1940  [(set (match_operand:SF 0 "s_register_operand" "=f")
1941	(sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1942  "TARGET_HARD_FLOAT"
1943  "sqt%?s\\t%0, %1"
1944[(set_attr "type" "float_em")])
1945
1946(define_insn "sqrtdf2"
1947  [(set (match_operand:DF 0 "s_register_operand" "=f")
1948	(sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1949  "TARGET_HARD_FLOAT"
1950  "sqt%?d\\t%0, %1"
1951[(set_attr "type" "float_em")])
1952
1953(define_insn "*sqrtdf_esfdf"
1954  [(set (match_operand:DF 0 "s_register_operand" "=f")
1955	(sqrt:DF (float_extend:DF
1956		  (match_operand:SF 1 "s_register_operand" "f"))))]
1957  "TARGET_HARD_FLOAT"
1958  "sqt%?d\\t%0, %1"
1959[(set_attr "type" "float_em")])
1960
1961(define_insn "sqrtxf2"
1962  [(set (match_operand:XF 0 "s_register_operand" "=f")
1963	(sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1964  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1965  "sqt%?e\\t%0, %1"
1966[(set_attr "type" "float_em")])
1967
1968;; SIN COS TAN and family are always emulated, so it's probably better
1969;; to always call a library function.
1970;(define_insn "sinsf2"
1971;  [(set (match_operand:SF 0 "s_register_operand" "=f")
1972;	(unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1973;  "TARGET_HARD_FLOAT"
1974;  "sin%?s\\t%0, %1"
1975;[(set_attr "type" "float_em")])
1976;
1977;(define_insn "sindf2"
1978;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1979;	(unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1980;  "TARGET_HARD_FLOAT"
1981;  "sin%?d\\t%0, %1"
1982;[(set_attr "type" "float_em")])
1983;
1984;(define_insn "*sindf_esfdf"
1985;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1986;	(unspec:DF [(float_extend:DF
1987;		     (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1988;  "TARGET_HARD_FLOAT"
1989;  "sin%?d\\t%0, %1"
1990;[(set_attr "type" "float_em")])
1991;
1992;(define_insn "sinxf2"
1993;  [(set (match_operand:XF 0 "s_register_operand" "=f")
1994;	(unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1995;  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1996;  "sin%?e\\t%0, %1"
1997;[(set_attr "type" "float_em")])
1998;
1999;(define_insn "cossf2"
2000;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2001;	(unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
2002;  "TARGET_HARD_FLOAT"
2003;  "cos%?s\\t%0, %1"
2004;[(set_attr "type" "float_em")])
2005;
2006;(define_insn "cosdf2"
2007;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2008;	(unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
2009;  "TARGET_HARD_FLOAT"
2010;  "cos%?d\\t%0, %1"
2011;[(set_attr "type" "float_em")])
2012;
2013;(define_insn "*cosdf_esfdf"
2014;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2015;	(unspec:DF [(float_extend:DF
2016;		     (match_operand:SF 1 "s_register_operand" "f"))] 1))]
2017;  "TARGET_HARD_FLOAT"
2018;  "cos%?d\\t%0, %1"
2019;[(set_attr "type" "float_em")])
2020;
2021;(define_insn "cosxf2"
2022;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2023;	(unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
2024;  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2025;  "cos%?e\\t%0, %1"
2026;[(set_attr "type" "float_em")])
2027
2028(define_insn "one_cmpldi2"
2029  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2030	(not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2031  ""
2032  "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1"
2033[(set_attr "length" "8")])
2034
2035(define_insn "one_cmplsi2"
2036  [(set (match_operand:SI 0 "s_register_operand" "=r")
2037	(not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2038  ""
2039  "mvn%?\\t%0, %1")
2040
2041(define_insn "*notsi_compare0"
2042  [(set (reg:CC_NOOV 24)
2043	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2044			 (const_int 0)))
2045   (set (match_operand:SI 0 "s_register_operand" "=r")
2046	(not:SI (match_dup 1)))]
2047  ""
2048  "mvn%?s\\t%0, %1"
2049[(set_attr "conds" "set")])
2050
2051(define_insn "*notsi_compare0_scratch"
2052  [(set (reg:CC_NOOV 24)
2053	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2054			 (const_int 0)))
2055   (clobber (match_scratch:SI 0 "=r"))]
2056  ""
2057  "mvn%?s\\t%0, %1"
2058[(set_attr "conds" "set")])
2059
2060;; Fixed <--> Floating conversion insns
2061
2062(define_insn "floatsisf2"
2063  [(set (match_operand:SF 0 "s_register_operand" "=f")
2064	(float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2065  "TARGET_HARD_FLOAT"
2066  "flt%?s\\t%0, %1"
2067[(set_attr "type" "r_2_f")])
2068
2069(define_insn "floatsidf2"
2070  [(set (match_operand:DF 0 "s_register_operand" "=f")
2071	(float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2072  "TARGET_HARD_FLOAT"
2073  "flt%?d\\t%0, %1"
2074[(set_attr "type" "r_2_f")])
2075
2076(define_insn "floatsixf2"
2077  [(set (match_operand:XF 0 "s_register_operand" "=f")
2078	(float:XF (match_operand:SI 1 "s_register_operand" "r")))]
2079  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2080  "flt%?e\\t%0, %1"
2081[(set_attr "type" "r_2_f")])
2082
2083(define_insn "fix_truncsfsi2"
2084  [(set (match_operand:SI 0 "s_register_operand" "=r")
2085	(fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2086  "TARGET_HARD_FLOAT"
2087  "fix%?z\\t%0, %1"
2088[(set_attr "type" "f_2_r")])
2089
2090(define_insn "fix_truncdfsi2"
2091  [(set (match_operand:SI 0 "s_register_operand" "=r")
2092	(fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2093  "TARGET_HARD_FLOAT"
2094  "fix%?z\\t%0, %1"
2095[(set_attr "type" "f_2_r")])
2096
2097(define_insn "fix_truncxfsi2"
2098  [(set (match_operand:SI 0 "s_register_operand" "=r")
2099	(fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
2100  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2101  "fix%?z\\t%0, %1"
2102[(set_attr "type" "f_2_r")])
2103
2104;; Truncation insns
2105
2106(define_insn "truncdfsf2"
2107  [(set (match_operand:SF 0 "s_register_operand" "=f")
2108	(float_truncate:SF
2109	 (match_operand:DF 1 "s_register_operand" "f")))]
2110  "TARGET_HARD_FLOAT"
2111  "mvf%?s\\t%0, %1"
2112[(set_attr "type" "ffarith")])
2113
2114(define_insn "truncxfsf2"
2115  [(set (match_operand:SF 0 "s_register_operand" "=f")
2116	(float_truncate:SF
2117	 (match_operand:XF 1 "s_register_operand" "f")))]
2118  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2119  "mvf%?s\\t%0, %1"
2120[(set_attr "type" "ffarith")])
2121
2122(define_insn "truncxfdf2"
2123  [(set (match_operand:DF 0 "s_register_operand" "=f")
2124	(float_truncate:DF
2125	 (match_operand:XF 1 "s_register_operand" "f")))]
2126  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2127  "mvf%?d\\t%0, %1"
2128[(set_attr "type" "ffarith")])
2129
2130;; Zero and sign extension instructions.
2131
2132(define_insn "zero_extendsidi2"
2133  [(set (match_operand:DI 0 "s_register_operand" "=r")
2134        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2135  ""
2136  "*
2137  if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2138    output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2139  return \"mov%?\\t%R0, #0\";
2140"
2141[(set_attr "length" "8")])
2142
2143(define_insn "zero_extendqidi2"
2144  [(set (match_operand:DI 0 "s_register_operand" "=r")
2145	(zero_extend:DI (match_operand:QI 1 "s_register_operand" "r")))]
2146  ""
2147  "and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0"
2148[(set_attr "length" "8")
2149 (set_attr "type" "*")])
2150
2151(define_insn "extendsidi2"
2152  [(set (match_operand:DI 0 "s_register_operand" "=r")
2153        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2154  ""
2155  "*
2156  if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2157    output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2158  return \"mov%?\\t%R0, %Q0, asr #31\";
2159"
2160[(set_attr "length" "8")])
2161
2162(define_expand "zero_extendhisi2"
2163  [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2164				 (const_int 16)))
2165   (set (match_operand:SI 0 "s_register_operand" "")
2166	(lshiftrt:SI (match_dup 2) (const_int 16)))]
2167  ""
2168  "
2169{
2170  if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2171    {
2172     /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES
2173	here because the insn below will generate an LDRH instruction
2174	rather than an LDR instruction, so we cannot get an unaligned
2175	word access.  */
2176      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2177			      gen_rtx_ZERO_EXTEND (SImode, operands[1])));
2178      DONE;
2179    }
2180  if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2181    {
2182      emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2183      DONE;
2184    }
2185  if (! s_register_operand (operands[1], HImode))
2186    operands[1] = copy_to_mode_reg (HImode, operands[1]);
2187  operands[1] = gen_lowpart (SImode, operands[1]);
2188  operands[2] = gen_reg_rtx (SImode); 
2189}")
2190
2191(define_insn "*zero_extendhisi_insn"
2192  [(set (match_operand:SI 0 "s_register_operand" "=r")
2193	(zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2194  "arm_arch4"
2195  "ldr%?h\\t%0, %1"
2196[(set_attr "type" "load")])
2197
2198(define_split
2199  [(set (match_operand:SI 0 "s_register_operand" "")
2200	(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2201   (clobber (match_operand:SI 2 "s_register_operand" ""))]
2202  "! arm_arch4"
2203  [(set (match_dup 2) (match_dup 1))
2204   (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2205  "
2206{
2207  if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2208    FAIL;
2209}")
2210
2211(define_split
2212  [(set (match_operand:SI 0 "s_register_operand" "")
2213	(match_operator:SI 3 "shiftable_operator"
2214	 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2215	  (match_operand:SI 4 "s_register_operand" "")]))
2216   (clobber (match_operand:SI 2 "s_register_operand" ""))]
2217  "! arm_arch4"
2218  [(set (match_dup 2) (match_dup 1))
2219   (set (match_dup 0)
2220	(match_op_dup 3
2221	 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2222  "
2223{
2224  if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2225    FAIL;
2226}")
2227
2228(define_expand "zero_extendqisi2"
2229  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2230	(zero_extend:SI
2231	 (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2232  ""
2233  "
2234  if (GET_CODE (operands[1]) != MEM)
2235    {
2236      emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
2237			     GEN_INT (255)));
2238      DONE;
2239    }
2240")
2241
2242(define_insn "*load_extendqisi"
2243  [(set (match_operand:SI 0 "s_register_operand" "=r")
2244	(zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2245  ""
2246  "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
2247[(set_attr "type" "load")])
2248
2249(define_split
2250  [(set (match_operand:SI 0 "s_register_operand" "")
2251	(zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
2252   (clobber (match_operand:SI 2 "s_register_operand" ""))]
2253  "GET_CODE (operands[1]) != MEM"
2254  [(set (match_dup 2) (match_dup 1))
2255   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
2256  "")
2257
2258(define_insn "*compareqi_eq0"
2259  [(set (reg:CC_Z 24)
2260	(compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
2261			 (const_int 0)))]
2262  ""
2263  "tst\\t%0, #255"
2264[(set_attr "conds" "set")])
2265
2266(define_expand "extendhisi2"
2267  [(set (match_dup 2)
2268	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2269		   (const_int 16)))
2270   (set (match_operand:SI 0 "s_register_operand" "")
2271	(ashiftrt:SI (match_dup 2)
2272		     (const_int 16)))]
2273  ""
2274  "
2275{
2276  if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2277    {
2278     /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES
2279	here because the insn below will generate an LDRH instruction
2280	rather than an LDR instruction, so we cannot get an unaligned
2281	word access.  */
2282      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2283		 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2284      DONE;
2285    }
2286
2287  if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2288    {
2289      emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
2290      DONE;
2291    }
2292  if (! s_register_operand (operands[1], HImode))
2293    operands[1] = copy_to_mode_reg (HImode, operands[1]);
2294  operands[1] = gen_lowpart (SImode, operands[1]);
2295  operands[2] = gen_reg_rtx (SImode);
2296}")
2297
2298(define_expand "extendhisi2_mem"
2299  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
2300   (set (match_dup 3)
2301	(zero_extend:SI (match_dup 7)))
2302   (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
2303   (set (match_operand:SI 0 "" "")
2304	(ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
2305  ""
2306  "
2307{
2308  rtx mem1, mem2;
2309  rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2310
2311  mem1 = gen_rtx_MEM (QImode, addr);
2312  MEM_COPY_ATTRIBUTES (mem1, operands[1]);
2313  RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
2314  mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
2315  MEM_COPY_ATTRIBUTES (mem2, operands[1]);
2316  RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
2317  operands[0] = gen_lowpart (SImode, operands[0]);
2318  operands[1] = mem1;
2319  operands[2] = gen_reg_rtx (SImode);
2320  operands[3] = gen_reg_rtx (SImode);
2321  operands[6] = gen_reg_rtx (SImode);
2322  operands[7] = mem2;
2323
2324  if (BYTES_BIG_ENDIAN)
2325    {
2326      operands[4] = operands[2];
2327      operands[5] = operands[3];
2328    }
2329  else
2330    {
2331      operands[4] = operands[3];
2332      operands[5] = operands[2];
2333    }
2334}
2335")
2336
2337(define_insn "*extendhisi_insn"
2338  [(set (match_operand:SI 0 "s_register_operand" "=r")
2339	(sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2340  "arm_arch4"
2341  "ldr%?sh\\t%0, %1"
2342[(set_attr "type" "load")])
2343
2344(define_split
2345  [(set (match_operand:SI 0 "s_register_operand" "")
2346	(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2347   (clobber (match_operand:SI 2 "s_register_operand" ""))]
2348  "! arm_arch4"
2349  [(set (match_dup 2) (match_dup 1))
2350   (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2351  "
2352{
2353  if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2354    FAIL;
2355}")
2356
2357(define_split
2358  [(set (match_operand:SI 0 "s_register_operand" "")
2359	(match_operator:SI 3 "shiftable_operator"
2360	 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2361	  (match_operand:SI 4 "s_register_operand" "")]))
2362   (clobber (match_operand:SI 2 "s_register_operand" ""))]
2363  "! arm_arch4"
2364  [(set (match_dup 2) (match_dup 1))
2365   (set (match_dup 0)
2366	(match_op_dup 3
2367	 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2368  "
2369{
2370  if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2371    FAIL;
2372}")
2373
2374(define_expand "extendqihi2"
2375  [(set (match_dup 2)
2376	(ashift:SI (match_operand:QI 1 "general_operand" "")
2377		   (const_int 24)))
2378   (set (match_operand:HI 0 "s_register_operand" "")
2379	(ashiftrt:SI (match_dup 2)
2380		     (const_int 24)))]
2381  ""
2382  "
2383{
2384  if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2385    {
2386      emit_insn (gen_rtx_SET (VOIDmode,
2387			      operands[0],
2388			      gen_rtx_SIGN_EXTEND (HImode, operands[1])));
2389      DONE;
2390    }
2391  if (! s_register_operand (operands[1], QImode))
2392    operands[1] = copy_to_mode_reg (QImode, operands[1]);
2393  operands[0] = gen_lowpart (SImode, operands[0]);
2394  operands[1] = gen_lowpart (SImode, operands[1]);
2395  operands[2] = gen_reg_rtx (SImode);
2396}")
2397
2398; Rather than restricting all byte accesses to memory addresses that ldrsb
2399; can handle, we fix up the ones that ldrsb can't grok with a split.
2400(define_insn "*extendqihi_insn"
2401  [(set (match_operand:HI 0 "s_register_operand" "=r")
2402	(sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
2403  "arm_arch4"
2404  "*
2405  /* If the address is invalid, this will split the instruction into two. */
2406  if (bad_signed_byte_operand (operands[1], QImode))
2407    return \"#\";
2408  return \"ldr%?sb\\t%0, %1\";
2409"
2410[(set_attr "type" "load")
2411 (set_attr "length" "8")])
2412
2413(define_split
2414  [(set (match_operand:HI 0 "s_register_operand" "")
2415	(sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2416  "arm_arch4 && reload_completed"
2417  [(set (match_dup 3) (match_dup 1))
2418   (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
2419  "
2420  {
2421    HOST_WIDE_INT offset;
2422
2423    operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
2424    operands[2] = gen_rtx_MEM (QImode, operands[3]);
2425    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2426    RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2427    operands[1] = XEXP (operands[1], 0);
2428    if (GET_CODE (operands[1]) == PLUS
2429	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2430	&& ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2431	      || const_ok_for_arm (-offset)))
2432      {
2433	HOST_WIDE_INT low = (offset > 0
2434			     ? (offset & 0xff) : -((-offset) & 0xff));
2435	XEXP (operands[2], 0) = plus_constant (operands[3], low);
2436	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2437      }
2438    /* Ensure the sum is in correct canonical form */
2439    else if (GET_CODE (operands[1]) == PLUS
2440	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2441	     && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2442      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2443					   XEXP (operands[1], 1),
2444					   XEXP (operands[1], 0));
2445  }
2446")
2447
2448(define_expand "extendqisi2"
2449  [(set (match_dup 2)
2450	(ashift:SI (match_operand:QI 1 "general_operand" "")
2451		   (const_int 24)))
2452   (set (match_operand:SI 0 "s_register_operand" "")
2453	(ashiftrt:SI (match_dup 2)
2454		     (const_int 24)))]
2455  ""
2456  "
2457{
2458  if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2459    {
2460      emit_insn (gen_rtx_SET (VOIDmode,
2461			      operands[0],
2462			      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2463      DONE;
2464    }
2465  if (! s_register_operand (operands[1], QImode))
2466    operands[1] = copy_to_mode_reg (QImode, operands[1]);
2467  operands[1] = gen_lowpart (SImode, operands[1]);
2468  operands[2] = gen_reg_rtx (SImode);
2469}")
2470
2471; Rather than restricting all byte accesses to memory addresses that ldrsb
2472; can handle, we fix up the ones that ldrsb can't grok with a split.
2473(define_insn "*extendqisi_insn"
2474  [(set (match_operand:SI 0 "s_register_operand" "=r")
2475	(sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2476  "arm_arch4"
2477  "*
2478  /* If the address is invalid, this will split the instruction into two. */
2479  if (bad_signed_byte_operand (operands[1], QImode))
2480    return \"#\";
2481  return \"ldr%?sb\\t%0, %1\";
2482"
2483[(set_attr "type" "load")
2484 (set_attr "length" "8")])
2485
2486(define_split
2487  [(set (match_operand:SI 0 "s_register_operand" "")
2488	(sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2489  "arm_arch4 && reload_completed"
2490  [(set (match_dup 0) (match_dup 1))
2491   (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2492  "
2493  {
2494    HOST_WIDE_INT offset;
2495
2496    operands[2] = gen_rtx_MEM (QImode, operands[0]);
2497    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2498    RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2499    operands[1] = XEXP (operands[1], 0);
2500    if (GET_CODE (operands[1]) == PLUS
2501	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2502	&& ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2503	      || const_ok_for_arm (-offset)))
2504      {
2505	HOST_WIDE_INT low = (offset > 0
2506			     ? (offset & 0xff) : -((-offset) & 0xff));
2507	XEXP (operands[2], 0) = plus_constant (operands[0], low);
2508	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2509      }
2510    /* Ensure the sum is in correct canonical form */
2511    else if (GET_CODE (operands[1]) == PLUS
2512	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2513	     && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2514      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2515					   XEXP (operands[1], 1),
2516					   XEXP (operands[1], 0));
2517  }
2518")
2519
2520(define_insn "extendsfdf2"
2521  [(set (match_operand:DF 0 "s_register_operand" "=f")
2522	(float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2523  "TARGET_HARD_FLOAT"
2524  "mvf%?d\\t%0, %1"
2525[(set_attr "type" "ffarith")])
2526
2527(define_insn "extendsfxf2"
2528  [(set (match_operand:XF 0 "s_register_operand" "=f")
2529	(float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2530  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2531  "mvf%?e\\t%0, %1"
2532[(set_attr "type" "ffarith")])
2533
2534(define_insn "extenddfxf2"
2535  [(set (match_operand:XF 0 "s_register_operand" "=f")
2536	(float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2537  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2538  "mvf%?e\\t%0, %1"
2539[(set_attr "type" "ffarith")])
2540
2541
2542;; Move insns (including loads and stores)
2543
2544;; XXX Just some ideas about movti.
2545;; I don't think these are a good idea on the arm, there just aren't enough
2546;; registers
2547;;(define_expand "loadti"
2548;;  [(set (match_operand:TI 0 "s_register_operand" "")
2549;;	(mem:TI (match_operand:SI 1 "address_operand" "")))]
2550;;  "" "")
2551
2552;;(define_expand "storeti"
2553;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2554;;	(match_operand:TI 1 "s_register_operand" ""))]
2555;;  "" "")
2556
2557;;(define_expand "movti"
2558;;  [(set (match_operand:TI 0 "general_operand" "")
2559;;	(match_operand:TI 1 "general_operand" ""))]
2560;;  ""
2561;;  "
2562;;{
2563;;  rtx insn;
2564;;
2565;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2566;;    operands[1] = copy_to_reg (operands[1]);
2567;;  if (GET_CODE (operands[0]) == MEM)
2568;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2569;;  else if (GET_CODE (operands[1]) == MEM)
2570;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2571;;  else
2572;;    FAIL;
2573;;
2574;;  emit_insn (insn);
2575;;  DONE;
2576;;}")
2577
2578;; Recognise garbage generated above.
2579
2580;;(define_insn ""
2581;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2582;;	(match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2583;;  ""
2584;;  "*
2585;;  {
2586;;    register mem = (which_alternative < 3);
2587;;    register char *template;
2588;;
2589;;    operands[mem] = XEXP (operands[mem], 0);
2590;;    switch (which_alternative)
2591;;      {
2592;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2593;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
2594;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
2595;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
2596;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
2597;;      case 5: template = \"stmia\\t%0, %M1\"; break;
2598;;      }
2599;;    output_asm_insn (template, operands);
2600;;    return \"\";
2601;;  }")
2602
2603
2604(define_insn "movdi"
2605  [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2606	(match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2607  ""
2608  "*
2609  return (output_move_double (operands));
2610"
2611[(set_attr "length" "8,8,8")
2612 (set_attr "type" "*,load,store2")])
2613
2614(define_expand "movsi"
2615  [(set (match_operand:SI 0 "general_operand" "")
2616        (match_operand:SI 1 "general_operand" ""))]
2617  ""
2618  "
2619  /* Everything except mem = const or mem = mem can be done easily */
2620  if (GET_CODE (operands[0]) == MEM)
2621    operands[1] = force_reg (SImode, operands[1]);
2622  if (GET_CODE (operands[1]) == CONST_INT
2623      && !(const_ok_for_arm (INTVAL (operands[1]))
2624           || const_ok_for_arm (~INTVAL (operands[1]))))
2625    {
2626      arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2627			  NULL_RTX,
2628			  (reload_in_progress || reload_completed ? 0
2629			   : preserve_subexpressions_p ()));
2630      DONE;
2631    }
2632  if (CONSTANT_P (operands[1]) && flag_pic)
2633    operands[1] = legitimize_pic_address (operands[1], SImode,
2634					  ((reload_in_progress
2635					    || reload_completed)
2636					   ? operands[0] : 0));
2637")
2638
2639(define_insn "*movsi_insn"
2640  [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2641	(match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
2642  "register_operand (operands[0], SImode)
2643   || register_operand (operands[1], SImode)"
2644  "@
2645   mov%?\\t%0, %1
2646   mvn%?\\t%0, #%B1
2647   ldr%?\\t%0, %1
2648   str%?\\t%1, %0"
2649[(set_attr "type" "*,*,load,store1")])
2650
2651(define_split
2652  [(set (match_operand:SI 0 "s_register_operand" "")
2653	(match_operand:SI 1 "const_int_operand" ""))]
2654  "! (const_ok_for_arm (INTVAL (operands[1]))
2655      || const_ok_for_arm (~INTVAL (operands[1])))"
2656  [(clobber (const_int 0))]
2657  "
2658  arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2659		      NULL_RTX, 0);
2660  DONE;
2661")
2662
2663(define_expand "movaddr"
2664  [(set (match_operand:SI 0 "s_register_operand" "")
2665	(match_operand:DI 1 "address_operand" ""))]
2666  ""
2667  "")
2668
2669(define_insn "*movaddr_insn"
2670  [(set (match_operand:SI 0 "s_register_operand" "=r")
2671	(match_operand:DI 1 "address_operand" "p"))]
2672  "reload_completed
2673   && (GET_CODE (operands[1]) == LABEL_REF
2674       || (GET_CODE (operands[1]) == CONST
2675	   && GET_CODE (XEXP (operands[1], 0)) == PLUS
2676	   && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2677	   && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2678  "adr%?\\t%0, %a1")
2679
2680/* When generating pic, we need to load the symbol offset into a register.
2681   So that the optimizer does not confuse this with a normal symbol load
2682   we use an unspec.  The offset will be loaded from a constant pool entry,
2683   since that is the only type of relocation we can use.  */
2684
2685(define_insn "pic_load_addr"
2686  [(set (match_operand:SI 0 "s_register_operand" "=r")
2687	(unspec:SI [(match_operand 1 "" "")] 3))]
2688  "flag_pic"
2689  "ldr%?\\t%0, %a1"
2690 [(set_attr "type" "load")])
2691
2692;; This variant is used for AOF assembly, since it needs to mention the
2693;; pic register in the rtl.
2694(define_expand "pic_load_addr_based"
2695  [(set (match_operand:SI 0 "s_register_operand" "=r")
2696	(unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
2697  "flag_pic"
2698  "operands[2] = pic_offset_table_rtx;")
2699
2700(define_insn "*pic_load_addr_based_insn"
2701  [(set (match_operand:SI 0 "s_register_operand" "=r")
2702	(unspec:SI [(match_operand 1 "" "")
2703		    (match_operand 2 "s_register_operand" "r")] 3))]
2704  "flag_pic && operands[2] == pic_offset_table_rtx"
2705  "*
2706#ifdef AOF_ASSEMBLER
2707  operands[1] = aof_pic_entry (operands[1]);
2708#endif
2709  output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
2710  return \"\";
2711" [(set_attr "type" "load")])
2712
2713(define_insn "pic_add_dot_plus_eight"
2714  [(set (match_operand 0 "register_operand" "+r")
2715	(plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
2716   (use (label_ref (match_operand 1 "" "")))]
2717  "flag_pic"
2718  "*
2719  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
2720			     CODE_LABEL_NUMBER (operands[1]));
2721  return \"add%?\\t%0, %|pc, %0\";
2722")
2723
2724;; If copying one reg to another we can set the condition codes according to
2725;; its value.  Such a move is common after a return from subroutine and the
2726;; result is being tested against zero.
2727
2728(define_insn "*movsi_compare0"
2729  [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
2730			        (const_int 0)))
2731   (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2732  ""
2733  "@
2734   cmp%?\\t%0, #0
2735   sub%?s\\t%0, %1, #0"
2736[(set_attr "conds" "set")])
2737
2738;; Subroutine to store a half word from a register into memory.
2739;; Operand 0 is the source register (HImode)
2740;; Operand 1 is the destination address in a register (SImode)
2741
2742;; In both this routine and the next, we must be careful not to spill
2743;; a memory address of reg+large_const into a separate PLUS insn, since this
2744;; can generate unrecognizable rtl.
2745
2746(define_expand "storehi"
2747  [;; store the low byte
2748   (set (match_operand 1 "" "") (match_dup 3))
2749   ;; extract the high byte
2750   (set (match_dup 2)
2751	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2752   ;; store the high byte
2753   (set (match_dup 4) (subreg:QI (match_dup 2) 0))]	;explicit subreg safe
2754  ""
2755  "
2756{
2757  rtx addr = XEXP (operands[1], 0);
2758  enum rtx_code code = GET_CODE (addr);
2759
2760  if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2761      || code == MINUS)
2762    addr = force_reg (SImode, addr);
2763
2764  operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2765  operands[1] = change_address (operands[1], QImode, NULL_RTX);
2766  operands[3] = gen_lowpart (QImode, operands[0]);
2767  operands[0] = gen_lowpart (SImode, operands[0]);
2768  operands[2] = gen_reg_rtx (SImode); 
2769}
2770")
2771
2772(define_expand "storehi_bigend"
2773  [(set (match_dup 4) (match_dup 3))
2774   (set (match_dup 2)
2775	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2776   (set (match_operand 1 "" "")	(subreg:QI (match_dup 2) 0))]
2777  ""
2778  "
2779{
2780  rtx addr = XEXP (operands[1], 0);
2781  enum rtx_code code = GET_CODE (addr);
2782
2783  if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2784      || code == MINUS)
2785    addr = force_reg (SImode, addr);
2786
2787  operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2788  operands[1] = change_address (operands[1], QImode, NULL_RTX);
2789  operands[3] = gen_lowpart (QImode, operands[0]);
2790  operands[0] = gen_lowpart (SImode, operands[0]);
2791  operands[2] = gen_reg_rtx (SImode);
2792}
2793")
2794
2795;; Subroutine to store a half word integer constant into memory.
2796(define_expand "storeinthi"
2797  [(set (match_operand 0 "" "")
2798	(subreg:QI (match_operand 1 "" "") 0))
2799   (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
2800  ""
2801  "
2802{
2803  HOST_WIDE_INT value = INTVAL (operands[1]);
2804  rtx addr = XEXP (operands[0], 0);
2805  enum rtx_code code = GET_CODE (addr);
2806
2807  if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2808      || code == MINUS)
2809    addr = force_reg (SImode, addr);
2810
2811  operands[1] = gen_reg_rtx (SImode);
2812  if (BYTES_BIG_ENDIAN)
2813    {
2814      emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2815      if ((value & 255) == ((value >> 8) & 255))
2816	operands[2] = operands[1];
2817      else
2818	{
2819	  operands[2] = gen_reg_rtx (SImode);
2820	  emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2821	}
2822    }
2823  else
2824    {
2825      emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2826      if ((value & 255) == ((value >> 8) & 255))
2827	operands[2] = operands[1];
2828      else
2829	{
2830	  operands[2] = gen_reg_rtx (SImode);
2831	  emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2832	}
2833    }
2834
2835  operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
2836  operands[0] = change_address (operands[0], QImode, NULL_RTX);
2837}
2838")
2839
2840(define_expand "storehi_single_op"
2841  [(set (match_operand:HI 0 "memory_operand" "")
2842	(match_operand:HI 1 "general_operand" ""))]
2843  "arm_arch4"
2844  "
2845  if (! s_register_operand (operands[1], HImode))
2846    operands[1] = copy_to_mode_reg (HImode, operands[1]);
2847")
2848
2849(define_expand "movhi"
2850  [(set (match_operand:HI 0 "general_operand" "")
2851	(match_operand:HI 1 "general_operand" ""))]
2852  ""
2853  "
2854{
2855  if (! (reload_in_progress || reload_completed))
2856    {
2857      if (GET_CODE (operands[0]) == MEM)
2858	{
2859	  if (arm_arch4)
2860	    {
2861	      emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2862	      DONE;
2863	    }
2864	  if (GET_CODE (operands[1]) == CONST_INT)
2865	    emit_insn (gen_storeinthi (operands[0], operands[1]));
2866	  else
2867	    {
2868	      if (GET_CODE (operands[1]) == MEM)
2869		operands[1] = force_reg (HImode, operands[1]);
2870	      if (BYTES_BIG_ENDIAN)
2871		emit_insn (gen_storehi_bigend (operands[1], operands[0]));
2872	      else
2873		emit_insn (gen_storehi (operands[1], operands[0]));
2874	    }
2875	  DONE;
2876	}
2877      /* Sign extend a constant, and keep it in an SImode reg.  */
2878      else if (GET_CODE (operands[1]) == CONST_INT)
2879	{
2880	  rtx reg = gen_reg_rtx (SImode);
2881	  HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2882
2883	  /* If the constant is already valid, leave it alone.  */
2884	  if (! const_ok_for_arm (val))
2885	    {
2886	      /* If setting all the top bits will make the constant 
2887		 loadable in a single instruction, then set them.  
2888		 Otherwise, sign extend the number.  */
2889
2890	      if (const_ok_for_arm (~ (val | ~0xffff)))
2891		val |= ~0xffff;
2892	      else if (val & 0x8000)
2893		val |= ~0xffff;
2894	    }
2895
2896	  emit_insn (gen_movsi (reg, GEN_INT (val)));
2897	  operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
2898	}
2899      else if (! arm_arch4)
2900	{
2901	 /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES
2902	    for v4 and up architectures because LDRH instructions will
2903	    be used to access the HI values, and these cannot generate
2904	    unaligned word access faults in the MMU.  */
2905	  if (GET_CODE (operands[1]) == MEM)
2906	    {
2907	      if (TARGET_SHORT_BY_BYTES)
2908		{
2909		  rtx base;
2910		  rtx offset = const0_rtx;
2911		  rtx reg = gen_reg_rtx (SImode);
2912
2913		  if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2914		       || (GET_CODE (base) == PLUS
2915			   && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2916                           && ((INTVAL(offset) & 1) != 1)
2917			   && GET_CODE (base = XEXP (base, 0)) == REG))
2918		      && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2919		    {
2920		      HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
2921		      rtx new;
2922
2923		      new = gen_rtx_MEM (SImode,
2924					 plus_constant (base, new_offset));
2925	              MEM_COPY_ATTRIBUTES (new, operands[1]);
2926		      RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2927		      emit_insn (gen_movsi (reg, new));
2928		      if (((INTVAL (offset) & 2) != 0)
2929			  ^ (BYTES_BIG_ENDIAN ? 1 : 0))
2930			{
2931			  rtx reg2 = gen_reg_rtx (SImode);
2932
2933			  emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
2934			  reg = reg2;
2935			}
2936		    }
2937		  else
2938		    emit_insn (gen_movhi_bytes (reg, operands[1]));
2939
2940		  operands[1] = gen_lowpart (HImode, reg);
2941		}
2942	      else if (BYTES_BIG_ENDIAN)
2943		{
2944		  rtx base;
2945		  rtx offset = const0_rtx;
2946
2947		  if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2948		       || (GET_CODE (base) == PLUS
2949			   && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2950			   && GET_CODE (base = XEXP (base, 0)) == REG))
2951		      && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2952		    {
2953		      rtx reg = gen_reg_rtx (SImode);
2954		      rtx new;
2955
2956		      if ((INTVAL (offset) & 2) == 2)
2957			{
2958			  HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
2959			  new = gen_rtx_MEM (SImode,
2960					     plus_constant (base, new_offset));
2961                          MEM_COPY_ATTRIBUTES (new, operands[1]);
2962			  RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2963			  emit_insn (gen_movsi (reg, new));
2964			}
2965		      else
2966			{
2967			  new = gen_rtx_MEM (SImode, XEXP (operands[1], 0));
2968	                  MEM_COPY_ATTRIBUTES (new, operands[1]);
2969			  RTX_UNCHANGING_P (new)
2970			    = RTX_UNCHANGING_P (operands[1]);
2971			  emit_insn (gen_rotated_loadsi (reg, new));
2972			}
2973
2974		      operands[1] = gen_lowpart (HImode, reg);
2975		    }
2976		  else
2977		    {
2978		      emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2979		      DONE;
2980		    }
2981		}
2982	    }
2983	}
2984    }
2985  /* Handle loading a large integer during reload */
2986  else if (GET_CODE (operands[1]) == CONST_INT
2987	   && ! const_ok_for_arm (INTVAL (operands[1]))
2988	   && ! const_ok_for_arm (~INTVAL (operands[1])))
2989    {
2990      /* Writing a constant to memory needs a scratch, which should
2991	 be handled with SECONDARY_RELOADs.  */
2992      if (GET_CODE (operands[0]) != REG)
2993	abort ();
2994
2995      operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
2996      emit_insn (gen_movsi (operands[0], operands[1]));
2997      DONE;
2998    }
2999}
3000")
3001
3002(define_insn "rotated_loadsi"
3003  [(set (match_operand:SI 0 "s_register_operand" "=r")
3004	(rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
3005		   (const_int 16)))]
3006  "! TARGET_SHORT_BY_BYTES"
3007  "*
3008{
3009  rtx ops[2];
3010
3011  ops[0] = operands[0];
3012  ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
3013  output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
3014  return \"\";
3015}"
3016[(set_attr "type" "load")])
3017
3018(define_expand "movhi_bytes"
3019  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3020   (set (match_dup 3)
3021	(zero_extend:SI (match_dup 6)))
3022   (set (match_operand:SI 0 "" "")
3023	 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
3024  ""
3025  "
3026{
3027  rtx mem1, mem2;
3028  rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3029
3030  mem1 = gen_rtx_MEM (QImode, addr);
3031  MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3032  RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
3033  mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3034  MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3035  RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
3036  operands[0] = gen_lowpart (SImode, operands[0]);
3037  operands[1] = mem1;
3038  operands[2] = gen_reg_rtx (SImode);
3039  operands[3] = gen_reg_rtx (SImode);
3040  operands[6] = mem2;
3041
3042  if (BYTES_BIG_ENDIAN)
3043    {
3044      operands[4] = operands[2];
3045      operands[5] = operands[3];
3046    }
3047  else
3048    {
3049      operands[4] = operands[3];
3050      operands[5] = operands[2];
3051    }
3052}
3053")
3054
3055(define_expand "movhi_bigend"
3056  [(set (match_dup 2)
3057	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
3058		   (const_int 16)))
3059   (set (match_dup 3)
3060	(ashiftrt:SI (match_dup 2) (const_int 16)))
3061   (set (match_operand:HI 0 "s_register_operand" "")
3062	(subreg:HI (match_dup 3) 0))]
3063  ""
3064  "
3065  operands[2] = gen_reg_rtx (SImode);
3066  operands[3] = gen_reg_rtx (SImode);
3067")
3068
3069;; Pattern to recognise insn generated default case above
3070(define_insn "*movhi_insn_arch4"
3071  [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
3072	(match_operand:HI 1 "general_operand"  "rI,K,m,r"))]
3073  "arm_arch4
3074   && (GET_CODE (operands[1]) != CONST_INT
3075       || const_ok_for_arm (INTVAL (operands[1]))
3076       || const_ok_for_arm (~INTVAL (operands[1])))"
3077  "@
3078   mov%?\\t%0, %1\\t%@ movhi
3079   mvn%?\\t%0, #%B1\\t%@ movhi
3080   ldr%?h\\t%0, %1\\t%@ movhi
3081   str%?h\\t%1, %0\\t%@ movhi"
3082[(set_attr "type" "*,*,load,store1")])
3083
3084(define_insn "*movhi_insn_littleend"
3085  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3086	(match_operand:HI 1 "general_operand"  "rI,K,m"))]
3087  "! arm_arch4
3088   && ! BYTES_BIG_ENDIAN
3089   && ! TARGET_SHORT_BY_BYTES
3090   && (GET_CODE (operands[1]) != CONST_INT
3091       || const_ok_for_arm (INTVAL (operands[1]))
3092       || const_ok_for_arm (~INTVAL (operands[1])))"
3093  "@
3094   mov%?\\t%0, %1\\t%@ movhi
3095   mvn%?\\t%0, #%B1\\t%@ movhi
3096   ldr%?\\t%0, %1\\t%@ movhi"
3097[(set_attr "type" "*,*,load")])
3098
3099(define_insn "*movhi_insn_bigend"
3100  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3101	(match_operand:HI 1 "general_operand"  "rI,K,m"))]
3102  "! arm_arch4
3103   && BYTES_BIG_ENDIAN
3104   && ! TARGET_SHORT_BY_BYTES
3105   && (GET_CODE (operands[1]) != CONST_INT
3106       || const_ok_for_arm (INTVAL (operands[1]))
3107       || const_ok_for_arm (~INTVAL (operands[1])))"
3108  "@
3109   mov%?\\t%0, %1\\t%@ movhi
3110   mvn%?\\t%0, #%B1\\t%@ movhi
3111   ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
3112[(set_attr "type" "*,*,load")
3113 (set_attr "length" "4,4,8")])
3114
3115(define_insn "*loadhi_si_bigend"
3116  [(set (match_operand:SI 0 "s_register_operand" "=r")
3117	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
3118		   (const_int 16)))]
3119  "BYTES_BIG_ENDIAN
3120   && ! TARGET_SHORT_BY_BYTES"
3121  "ldr%?\\t%0, %1\\t%@ movhi_bigend"
3122[(set_attr "type" "load")])
3123
3124(define_insn "*movhi_bytes"
3125  [(set (match_operand:HI 0 "s_register_operand" "=r,r")
3126	(match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
3127  "TARGET_SHORT_BY_BYTES"
3128  "@
3129   mov%?\\t%0, %1\\t%@ movhi
3130   mvn%?\\t%0, #%B1\\t%@ movhi")
3131
3132;; We use a DImode scratch because we may occasionally need an additional
3133;; temporary if the address isn't offsettable -- push_reload doesn't seem
3134;; to take any notice of the "o" constraints on reload_memory_operand operand.
3135(define_expand "reload_outhi"
3136  [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
3137	      (match_operand:HI 1 "s_register_operand" "r")
3138	      (match_operand:DI 2 "s_register_operand" "=&r")])]
3139  ""
3140  "
3141  arm_reload_out_hi (operands);
3142  DONE;
3143")
3144
3145(define_expand "reload_inhi"
3146  [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
3147	      (match_operand:HI 1 "reload_memory_operand" "o")
3148	      (match_operand:DI 2 "s_register_operand" "=&r")])]
3149  "TARGET_SHORT_BY_BYTES"
3150  "
3151  arm_reload_in_hi (operands);
3152  DONE;
3153")
3154
3155(define_expand "movqi"
3156  [(set (match_operand:QI 0 "general_operand" "")
3157        (match_operand:QI 1 "general_operand" ""))]
3158  ""
3159  "
3160  /* Everything except mem = const or mem = mem can be done easily */
3161
3162  if (!(reload_in_progress || reload_completed))
3163    {
3164      if (GET_CODE (operands[1]) == CONST_INT)
3165	{
3166	  rtx reg = gen_reg_rtx (SImode);
3167
3168	  emit_insn (gen_movsi (reg, operands[1]));
3169	  operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
3170	}
3171      if (GET_CODE (operands[0]) == MEM)
3172	operands[1] = force_reg (QImode, operands[1]);
3173    }
3174")
3175
3176
3177(define_insn "*movqi_insn"
3178  [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
3179	(match_operand:QI 1 "general_operand" "rI,K,m,r"))]
3180  "register_operand (operands[0], QImode)
3181   || register_operand (operands[1], QImode)"
3182  "@
3183   mov%?\\t%0, %1
3184   mvn%?\\t%0, #%B1
3185   ldr%?b\\t%0, %1
3186   str%?b\\t%1, %0"
3187[(set_attr "type" "*,*,load,store1")])
3188
3189(define_expand "movsf"
3190  [(set (match_operand:SF 0 "general_operand" "")
3191	(match_operand:SF 1 "general_operand" ""))]
3192  ""
3193  "
3194  if (GET_CODE (operands[0]) == MEM)
3195    operands[1] = force_reg (SFmode, operands[1]);
3196")
3197
3198(define_insn "*movsf_hard_insn"
3199  [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
3200	(match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
3201  "TARGET_HARD_FLOAT
3202   && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3203  "@
3204   mvf%?s\\t%0, %1
3205   mnf%?s\\t%0, #%N1
3206   ldf%?s\\t%0, %1
3207   stf%?s\\t%1, %0
3208   str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
3209   stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
3210   mov%?\\t%0, %1
3211   ldr%?\\t%0, %1\\t%@ float
3212   str%?\\t%1, %0\\t%@ float"
3213[(set_attr "length" "4,4,4,4,8,8,4,4,4")
3214 (set_attr "type"
3215	 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
3216
3217;; Exactly the same as above, except that all `f' cases are deleted.
3218;; This is necessary to prevent reload from ever trying to use a `f' reg
3219;; when -msoft-float.
3220
3221(define_insn "*movsf_soft_insn"
3222  [(set (match_operand:SF 0 "general_operand" "=r,r,m")
3223	(match_operand:SF 1 "general_operand" "r,mE,r"))]
3224  "TARGET_SOFT_FLOAT
3225   && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3226  "@
3227   mov%?\\t%0, %1
3228   ldr%?\\t%0, %1\\t%@ float
3229   str%?\\t%1, %0\\t%@ float"
3230[(set_attr "length" "4,4,4")
3231 (set_attr "type" "*,load,store1")])
3232
3233(define_expand "movdf"
3234  [(set (match_operand:DF 0 "general_operand" "")
3235	(match_operand:DF 1 "general_operand" ""))]
3236  ""
3237  "
3238  if (GET_CODE (operands[0]) == MEM)
3239    operands[1] = force_reg (DFmode, operands[1]);
3240")
3241
3242;; Reloading a df mode value stored in integer regs to memory can require a
3243;; scratch reg.
3244(define_expand "reload_outdf"
3245  [(match_operand:DF 0 "reload_memory_operand" "=o")
3246   (match_operand:DF 1 "s_register_operand" "r")
3247   (match_operand:SI 2 "s_register_operand" "=&r")]
3248  ""
3249  "
3250{
3251  enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
3252
3253  if (code == REG)
3254    operands[2] = XEXP (operands[0], 0);
3255  else if (code == POST_INC || code == PRE_DEC)
3256    {
3257      operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
3258      operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
3259      emit_insn (gen_movdi (operands[0], operands[1]));
3260      DONE;
3261    }
3262  else if (code == PRE_INC)
3263    {
3264      rtx reg = XEXP (XEXP (operands[0], 0), 0);
3265      emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
3266      operands[2] = reg;
3267    }
3268  else if (code == POST_DEC)
3269    operands[2] = XEXP (XEXP (operands[0], 0), 0);
3270  else
3271    emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
3272			   XEXP (XEXP (operands[0], 0), 1)));
3273
3274  emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
3275				    operands[1]));
3276
3277  if (code == POST_DEC)
3278    emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
3279
3280  DONE;
3281}
3282")
3283
3284(define_insn "*movdf_hard_insn"
3285  [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
3286	(match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
3287  "TARGET_HARD_FLOAT
3288   && (GET_CODE (operands[0]) != MEM
3289       || register_operand (operands[1], DFmode))"
3290  "*
3291{
3292  switch (which_alternative)
3293    {
3294    default:
3295    case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3296    case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3297    case 2: case 3: case 4: return output_move_double (operands);
3298    case 5: return \"mvf%?d\\t%0, %1\";
3299    case 6: return \"mnf%?d\\t%0, #%N1\";
3300    case 7: return \"ldf%?d\\t%0, %1\";
3301    case 8: return \"stf%?d\\t%1, %0\";
3302    case 9: return output_mov_double_fpu_from_arm (operands);
3303    case 10: return output_mov_double_arm_from_fpu (operands);
3304    }
3305}
3306"
3307[(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3308 (set_attr "type"
3309"load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
3310
3311;; Software floating point version.  This is essentially the same as movdi.
3312;; Do not use `f' as a constraint to prevent reload from ever trying to use
3313;; an `f' reg.
3314
3315(define_insn "*movdf_soft_insn"
3316  [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3317	(match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3318  "TARGET_SOFT_FLOAT"
3319  "* return output_move_double (operands);"
3320[(set_attr "length" "8,8,8")
3321 (set_attr "type" "*,load,store2")])
3322
3323(define_expand "movxf"
3324  [(set (match_operand:XF 0 "general_operand" "")
3325	(match_operand:XF 1 "general_operand" ""))]
3326  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3327  "")
3328
3329;; Even when the XFmode patterns aren't enabled, we enable this after
3330;; reloading so that we can push floating point registers in the prologue.
3331
3332(define_insn "*movxf_hard_insn"
3333  [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3334	(match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3335  "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3336  "*
3337  switch (which_alternative)
3338    {
3339    default:
3340    case 0: return \"mvf%?e\\t%0, %1\";
3341    case 1: return \"mnf%?e\\t%0, #%N1\";
3342    case 2: return \"ldf%?e\\t%0, %1\";
3343    case 3: return \"stf%?e\\t%1, %0\";
3344    case 4: return output_mov_long_double_fpu_from_arm (operands);
3345    case 5: return output_mov_long_double_arm_from_fpu (operands);
3346    case 6: return output_mov_long_double_arm_from_arm (operands);
3347    }
3348"
3349[(set_attr "length" "4,4,4,4,8,8,12")
3350 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
3351
3352
3353;; load- and store-multiple insns
3354;; The arm can load/store any set of registers, provided that they are in
3355;; ascending order; but that is beyond GCC so stick with what it knows.
3356
3357(define_expand "load_multiple"
3358  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3359                          (match_operand:SI 1 "" ""))
3360                     (use (match_operand:SI 2 "" ""))])]
3361  ""
3362  "
3363  /* Support only fixed point registers */
3364  if (GET_CODE (operands[2]) != CONST_INT
3365      || INTVAL (operands[2]) > 14
3366      || INTVAL (operands[2]) < 2
3367      || GET_CODE (operands[1]) != MEM
3368      || GET_CODE (operands[0]) != REG
3369      || REGNO (operands[0]) > 14
3370      || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
3371    FAIL;
3372
3373  operands[3]
3374    = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
3375			     force_reg (SImode, XEXP (operands[1], 0)),
3376			     TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
3377			     MEM_IN_STRUCT_P(operands[1]),
3378	                     MEM_SCALAR_P (operands[1]));
3379")
3380
3381;; Load multiple with write-back
3382
3383(define_insn "*ldmsi_postinc"
3384  [(match_parallel 0 "load_multiple_operation"
3385    [(set (match_operand:SI 1 "s_register_operand" "+r")
3386	  (plus:SI (match_dup 1)
3387		   (match_operand:SI 2 "const_int_operand" "n")))
3388     (set (match_operand:SI 3 "s_register_operand" "=r")
3389	  (mem:SI (match_dup 1)))])]
3390  "(INTVAL (operands[2])  == 4 * (XVECLEN (operands[0], 0) - 2))"
3391  "*
3392{
3393  rtx ops[3];
3394  int count = XVECLEN (operands[0], 0);
3395
3396  ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3397  ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
3398  ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
3399
3400  output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
3401  return \"\";
3402}
3403"
3404[(set_attr "type" "load")])
3405
3406;; Ordinary load multiple
3407
3408(define_insn "*ldmsi"
3409  [(match_parallel 0 "load_multiple_operation"
3410    [(set (match_operand:SI 1 "s_register_operand" "=r")
3411	  (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3412  ""
3413  "*
3414{
3415  rtx ops[3];
3416  int count = XVECLEN (operands[0], 0);
3417
3418  ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3419  ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3420  ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3421
3422  output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3423  return \"\";
3424}
3425"
3426[(set_attr "type" "load")])
3427
3428(define_expand "store_multiple"
3429  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3430                          (match_operand:SI 1 "" ""))
3431                     (use (match_operand:SI 2 "" ""))])]
3432  ""
3433  "
3434  /* Support only fixed point registers */
3435  if (GET_CODE (operands[2]) != CONST_INT
3436      || INTVAL (operands[2]) > 14
3437      || INTVAL (operands[2]) < 2
3438      || GET_CODE (operands[1]) != REG
3439      || GET_CODE (operands[0]) != MEM
3440      || REGNO (operands[1]) > 14
3441      || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3442    FAIL;
3443
3444  operands[3]
3445    = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3446			      force_reg (SImode, XEXP (operands[0], 0)),
3447			      TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
3448			      MEM_IN_STRUCT_P(operands[0]), 
3449	                      MEM_SCALAR_P (operands[0]));
3450")
3451
3452;; Store multiple with write-back
3453
3454(define_insn "*stmsi_postinc"
3455  [(match_parallel 0 "store_multiple_operation"
3456    [(set (match_operand:SI 1 "s_register_operand" "+r")
3457	  (plus:SI (match_dup 1)
3458		   (match_operand:SI 2 "const_int_operand" "n")))
3459     (set (mem:SI (match_dup 1))
3460	  (match_operand:SI 3 "s_register_operand" "r"))])]
3461  "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3462  "*
3463{
3464  rtx ops[3];
3465  int count = XVECLEN (operands[0], 0);
3466
3467  ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3468  ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3469  ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3470
3471  output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3472  return \"\";
3473}
3474"
3475[(set (attr "type")
3476      (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3477		(const_string "store2")
3478	     (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3479		(const_string "store3")]
3480	  (const_string "store4")))])
3481
3482;; Ordinary store multiple
3483
3484(define_insn "*stmsi"
3485  [(match_parallel 0 "store_multiple_operation"
3486    [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3487	  (match_operand:SI 1 "s_register_operand" "r"))])]
3488  ""
3489  "*
3490{
3491  rtx ops[3];
3492  int count = XVECLEN (operands[0], 0);
3493
3494  ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3495  ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3496  ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3497
3498  output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3499  return \"\";
3500}
3501"
3502[(set (attr "type")
3503      (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3504		(const_string "store2")
3505	     (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3506		(const_string "store3")]
3507	  (const_string "store4")))])
3508
3509;; Move a block of memory if it is word aligned and MORE than 2 words long.
3510;; We could let this apply for blocks of less than this, but it clobbers so
3511;; many registers that there is then probably a better way.
3512
3513(define_expand "movstrqi"
3514  [(match_operand:BLK 0 "general_operand" "")
3515   (match_operand:BLK 1 "general_operand" "")
3516   (match_operand:SI 2 "const_int_operand" "")
3517   (match_operand:SI 3 "const_int_operand" "")]
3518  ""
3519  "
3520  if (arm_gen_movstrqi (operands))
3521    DONE;
3522  FAIL;
3523")
3524
3525
3526;; Comparison and test insns
3527
3528(define_expand "cmpsi"
3529  [(match_operand:SI 0 "s_register_operand" "")
3530   (match_operand:SI 1 "arm_add_operand" "")]
3531  ""
3532  "
3533{
3534  arm_compare_op0 = operands[0];
3535  arm_compare_op1 = operands[1];
3536  DONE;
3537}
3538")
3539
3540(define_expand "cmpsf"
3541  [(match_operand:SF 0 "s_register_operand" "")
3542   (match_operand:SF 1 "fpu_rhs_operand" "")]
3543  "TARGET_HARD_FLOAT"
3544  "
3545{
3546  arm_compare_op0 = operands[0];
3547  arm_compare_op1 = operands[1];
3548  DONE;
3549}
3550")
3551
3552(define_expand "cmpdf"
3553  [(match_operand:DF 0 "s_register_operand" "")
3554   (match_operand:DF 1 "fpu_rhs_operand" "")]
3555  "TARGET_HARD_FLOAT"
3556  "
3557{
3558  arm_compare_op0 = operands[0];
3559  arm_compare_op1 = operands[1];
3560  DONE;
3561}
3562")
3563
3564(define_expand "cmpxf"
3565  [(match_operand:XF 0 "s_register_operand" "")
3566   (match_operand:XF 1 "fpu_rhs_operand" "")]
3567  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3568  "
3569{
3570  arm_compare_op0 = operands[0];
3571  arm_compare_op1 = operands[1];
3572  DONE;
3573}
3574")
3575
3576(define_insn "*cmpsi_insn"
3577  [(set (reg:CC 24)
3578	(compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3579		    (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3580  ""
3581  "@
3582   cmp%?\\t%0, %1
3583   cmn%?\\t%0, #%n1"
3584[(set_attr "conds" "set")])
3585
3586(define_insn "*cmpsi_shiftsi"
3587  [(set (reg:CC 24)
3588	(compare:CC (match_operand:SI 0 "s_register_operand" "r")
3589		    (match_operator:SI 3 "shift_operator"
3590		     [(match_operand:SI 1 "s_register_operand" "r")
3591		      (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3592  ""
3593  "cmp%?\\t%0, %1%S3"
3594[(set_attr "conds" "set")])
3595
3596(define_insn "*cmpsi_shiftsi_swp"
3597  [(set (reg:CC_SWP 24)
3598	(compare:CC_SWP (match_operator:SI 3 "shift_operator"
3599			 [(match_operand:SI 1 "s_register_operand" "r")
3600			  (match_operand:SI 2 "reg_or_int_operand" "rM")])
3601			(match_operand:SI 0 "s_register_operand" "r")))]
3602  ""
3603  "cmp%?\\t%0, %1%S3"
3604[(set_attr "conds" "set")])
3605
3606(define_insn "*cmpsi_neg_shiftsi"
3607  [(set (reg:CC 24)
3608	(compare:CC (match_operand:SI 0 "s_register_operand" "r")
3609		    (neg:SI (match_operator:SI 3 "shift_operator"
3610			     [(match_operand:SI 1 "s_register_operand" "r")
3611			      (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3612  ""
3613  "cmn%?\\t%0, %1%S3"
3614[(set_attr "conds" "set")])
3615
3616(define_insn "*cmpsf_insn"
3617  [(set (reg:CCFP 24)
3618	(compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3619		      (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3620  "TARGET_HARD_FLOAT"
3621  "@
3622   cmf%?\\t%0, %1
3623   cnf%?\\t%0, #%N1"
3624[(set_attr "conds" "set")
3625 (set_attr "type" "f_2_r")])
3626
3627(define_insn "*cmpdf_insn"
3628  [(set (reg:CCFP 24)
3629	(compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3630		      (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3631  "TARGET_HARD_FLOAT"
3632  "@
3633   cmf%?\\t%0, %1
3634   cnf%?\\t%0, #%N1"
3635[(set_attr "conds" "set")
3636 (set_attr "type" "f_2_r")])
3637
3638(define_insn "*cmpesfdf_df"
3639  [(set (reg:CCFP 24)
3640	(compare:CCFP (float_extend:DF
3641		       (match_operand:SF 0 "s_register_operand" "f,f"))
3642		      (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3643  "TARGET_HARD_FLOAT"
3644  "@
3645   cmf%?\\t%0, %1
3646   cnf%?\\t%0, #%N1"
3647[(set_attr "conds" "set")
3648 (set_attr "type" "f_2_r")])
3649
3650(define_insn "*cmpdf_esfdf"
3651  [(set (reg:CCFP 24)
3652	(compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3653		      (float_extend:DF
3654		       (match_operand:SF 1 "s_register_operand" "f"))))]
3655  "TARGET_HARD_FLOAT"
3656  "cmf%?\\t%0, %1"
3657[(set_attr "conds" "set")
3658 (set_attr "type" "f_2_r")])
3659
3660(define_insn "*cmpxf_insn"
3661  [(set (reg:CCFP 24)
3662	(compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3663		      (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3664  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3665  "@
3666   cmf%?\\t%0, %1
3667   cnf%?\\t%0, #%N1"
3668[(set_attr "conds" "set")
3669 (set_attr "type" "f_2_r")])
3670
3671(define_insn "*cmpsf_trap"
3672  [(set (reg:CCFPE 24)
3673	(compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3674		       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3675  "TARGET_HARD_FLOAT"
3676  "@
3677   cmf%?e\\t%0, %1
3678   cnf%?e\\t%0, #%N1"
3679[(set_attr "conds" "set")
3680 (set_attr "type" "f_2_r")])
3681
3682(define_insn "*cmpdf_trap"
3683  [(set (reg:CCFPE 24)
3684	(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3685		       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3686  "TARGET_HARD_FLOAT"
3687  "@
3688   cmf%?e\\t%0, %1
3689   cnf%?e\\t%0, #%N1"
3690[(set_attr "conds" "set")
3691 (set_attr "type" "f_2_r")])
3692
3693(define_insn "*cmp_esfdf_df_trap"
3694  [(set (reg:CCFPE 24)
3695	(compare:CCFPE (float_extend:DF
3696			(match_operand:SF 0 "s_register_operand" "f,f"))
3697		       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3698  "TARGET_HARD_FLOAT"
3699  "@
3700   cmf%?e\\t%0, %1
3701   cnf%?e\\t%0, #%N1"
3702[(set_attr "conds" "set")
3703 (set_attr "type" "f_2_r")])
3704
3705(define_insn "*cmp_df_esfdf_trap"
3706  [(set (reg:CCFPE 24)
3707	(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3708		       (float_extend:DF
3709			(match_operand:SF 1 "s_register_operand" "f"))))]
3710  "TARGET_HARD_FLOAT"
3711  "cmf%?e\\t%0, %1"
3712[(set_attr "conds" "set")
3713 (set_attr "type" "f_2_r")])
3714
3715(define_insn "*cmpxf_trap"
3716  [(set (reg:CCFPE 24)
3717	(compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3718		       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3719  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3720  "@
3721   cmf%?e\\t%0, %1
3722   cnf%?e\\t%0, #%N1"
3723[(set_attr "conds" "set")
3724 (set_attr "type" "f_2_r")])
3725
3726; This insn allows redundant compares to be removed by cse, nothing should
3727; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3728; is deleted later on. The match_dup will match the mode here, so that
3729; mode changes of the condition codes aren't lost by this even though we don't
3730; specify what they are.
3731
3732(define_insn "*deleted_compare"
3733  [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3734  ""
3735  "\\t%@ deleted compare"
3736[(set_attr "conds" "set")
3737 (set_attr "length" "0")])
3738
3739
3740;; Conditional branch insns
3741
3742(define_expand "beq"
3743  [(set (pc)
3744	(if_then_else (eq (match_dup 1) (const_int 0))
3745		      (label_ref (match_operand 0 "" ""))
3746		      (pc)))]
3747  ""
3748  "
3749{
3750  operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);
3751}
3752")
3753
3754(define_expand "bne"
3755  [(set (pc)
3756	(if_then_else (ne (match_dup 1) (const_int 0))
3757		      (label_ref (match_operand 0 "" ""))
3758		      (pc)))]
3759  ""
3760  "
3761{
3762  operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);
3763}
3764")
3765
3766(define_expand "bgt"
3767  [(set (pc)
3768	(if_then_else (gt (match_dup 1) (const_int 0))
3769		      (label_ref (match_operand 0 "" ""))
3770		      (pc)))]
3771  ""
3772  "
3773{
3774  operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);
3775}
3776")
3777
3778(define_expand "ble"
3779  [(set (pc)
3780	(if_then_else (le (match_dup 1) (const_int 0))
3781		      (label_ref (match_operand 0 "" ""))
3782		      (pc)))]
3783  ""
3784  "
3785{
3786  operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);
3787}
3788")
3789
3790(define_expand "bge"
3791  [(set (pc)
3792	(if_then_else (ge (match_dup 1) (const_int 0))
3793		      (label_ref (match_operand 0 "" ""))
3794		      (pc)))]
3795  ""
3796  "
3797{
3798  operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);
3799}
3800")
3801
3802(define_expand "blt"
3803  [(set (pc)
3804	(if_then_else (lt (match_dup 1) (const_int 0))
3805		      (label_ref (match_operand 0 "" ""))
3806		      (pc)))]
3807  ""
3808  "
3809{
3810  operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);
3811}
3812")
3813
3814(define_expand "bgtu"
3815  [(set (pc)
3816	(if_then_else (gtu (match_dup 1) (const_int 0))
3817		      (label_ref (match_operand 0 "" ""))
3818		      (pc)))]
3819  ""
3820  "
3821{
3822  operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);
3823}
3824")
3825
3826(define_expand "bleu"
3827  [(set (pc)
3828	(if_then_else (leu (match_dup 1) (const_int 0))
3829		      (label_ref (match_operand 0 "" ""))
3830		      (pc)))]
3831  ""
3832  "
3833{
3834  operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);
3835}
3836")
3837
3838(define_expand "bgeu"
3839  [(set (pc)
3840	(if_then_else (geu (match_dup 1) (const_int 0))
3841		      (label_ref (match_operand 0 "" ""))
3842		      (pc)))]
3843  ""
3844  "
3845{
3846  operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);
3847}
3848")
3849
3850(define_expand "bltu"
3851  [(set (pc)
3852	(if_then_else (ltu (match_dup 1) (const_int 0))
3853		      (label_ref (match_operand 0 "" ""))
3854		      (pc)))]
3855  ""
3856  "
3857{
3858  operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);
3859}
3860")
3861
3862;; patterns to match conditional branch insns
3863
3864(define_insn "*condbranch"
3865  [(set (pc)
3866	(if_then_else (match_operator 1 "comparison_operator"
3867		       [(match_operand 2 "cc_register" "") (const_int 0)])
3868		      (label_ref (match_operand 0 "" ""))
3869		      (pc)))]
3870  ""
3871  "*
3872{
3873  extern int arm_ccfsm_state;
3874
3875  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3876  {
3877    arm_ccfsm_state += 2;
3878    return \"\";
3879  }
3880  return \"b%d1\\t%l0\";
3881}"
3882[(set_attr "conds" "use")])
3883
3884(define_insn "*condbranch_reversed"
3885  [(set (pc)
3886	(if_then_else (match_operator 1 "comparison_operator"
3887		       [(match_operand 2 "cc_register" "") (const_int 0)])
3888		      (pc)
3889		      (label_ref (match_operand 0 "" ""))))]
3890  ""
3891  "*
3892{
3893  extern int arm_ccfsm_state;
3894
3895  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3896  {
3897    arm_ccfsm_state += 2;
3898    return \"\";
3899  }
3900  return \"b%D1\\t%l0\";
3901}"
3902[(set_attr "conds" "use")])
3903
3904
3905; scc insns
3906
3907(define_expand "seq"
3908  [(set (match_operand:SI 0 "s_register_operand" "=r")
3909	(eq:SI (match_dup 1) (const_int 0)))]
3910  ""
3911  "
3912{
3913  operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);
3914}
3915")
3916
3917(define_expand "sne"
3918  [(set (match_operand:SI 0 "s_register_operand" "=r")
3919	(ne:SI (match_dup 1) (const_int 0)))]
3920  ""
3921  "
3922{
3923  operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);
3924}
3925")
3926
3927(define_expand "sgt"
3928  [(set (match_operand:SI 0 "s_register_operand" "=r")
3929	(gt:SI (match_dup 1) (const_int 0)))]
3930  ""
3931  "
3932{
3933  operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);
3934}
3935")
3936
3937(define_expand "sle"
3938  [(set (match_operand:SI 0 "s_register_operand" "=r")
3939	(le:SI (match_dup 1) (const_int 0)))]
3940  ""
3941  "
3942{
3943  operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);
3944}
3945")
3946
3947(define_expand "sge"
3948  [(set (match_operand:SI 0 "s_register_operand" "=r")
3949	(ge:SI (match_dup 1) (const_int 0)))]
3950  ""
3951  "
3952{
3953  operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);
3954}
3955")
3956
3957(define_expand "slt"
3958  [(set (match_operand:SI 0 "s_register_operand" "=r")
3959	(lt:SI (match_dup 1) (const_int 0)))]
3960  ""
3961  "
3962{
3963  operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);
3964}
3965")
3966
3967(define_expand "sgtu"
3968  [(set (match_operand:SI 0 "s_register_operand" "=r")
3969	(gtu:SI (match_dup 1) (const_int 0)))]
3970  ""
3971  "
3972{
3973  operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);
3974}
3975")
3976
3977(define_expand "sleu"
3978  [(set (match_operand:SI 0 "s_register_operand" "=r")
3979	(leu:SI (match_dup 1) (const_int 0)))]
3980  ""
3981  "
3982{
3983  operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);
3984}
3985")
3986
3987(define_expand "sgeu"
3988  [(set (match_operand:SI 0 "s_register_operand" "=r")
3989	(geu:SI (match_dup 1) (const_int 0)))]
3990  ""
3991  "
3992{
3993  operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);
3994}
3995")
3996
3997(define_expand "sltu"
3998  [(set (match_operand:SI 0 "s_register_operand" "=r")
3999	(ltu:SI (match_dup 1) (const_int 0)))]
4000  ""
4001  "
4002{
4003  operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);
4004}
4005")
4006
4007(define_insn "*mov_scc"
4008  [(set (match_operand:SI 0 "s_register_operand" "=r")
4009	(match_operator:SI 1 "comparison_operator"
4010	 [(match_operand 2 "cc_register" "") (const_int 0)]))]
4011  ""
4012  "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
4013[(set_attr "conds" "use")
4014 (set_attr "length" "8")])
4015
4016(define_insn "*mov_negscc"
4017  [(set (match_operand:SI 0 "s_register_operand" "=r")
4018	(neg:SI (match_operator:SI 1 "comparison_operator"
4019		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4020  ""
4021  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
4022[(set_attr "conds" "use")
4023 (set_attr "length" "8")])
4024
4025(define_insn "*mov_notscc"
4026  [(set (match_operand:SI 0 "s_register_operand" "=r")
4027	(not:SI (match_operator:SI 1 "comparison_operator"
4028		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4029  ""
4030  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
4031[(set_attr "conds" "use")
4032 (set_attr "length" "8")])
4033
4034
4035;; Conditional move insns
4036
4037(define_expand "movsicc"
4038  [(set (match_operand:SI 0 "s_register_operand" "")
4039	(if_then_else:SI (match_operand 1 "comparison_operator" "")
4040			 (match_operand:SI 2 "arm_not_operand" "")
4041			 (match_operand:SI 3 "arm_not_operand" "")))]
4042  ""
4043  "
4044{
4045  enum rtx_code code = GET_CODE (operands[1]);
4046  rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4047
4048  operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4049}")
4050
4051(define_expand "movsfcc"
4052  [(set (match_operand:SF 0 "s_register_operand" "")
4053	(if_then_else:SF (match_operand 1 "comparison_operator" "")
4054			 (match_operand:SF 2 "s_register_operand" "")
4055			 (match_operand:SF 3 "nonmemory_operand" "")))]
4056  ""
4057  "
4058{
4059  enum rtx_code code = GET_CODE (operands[1]);
4060  rtx ccreg;
4061
4062  /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
4063     Otherwise, ensure it is a valid FP add operand */
4064  if ((! TARGET_HARD_FLOAT)
4065      || (! fpu_add_operand (operands[3], SFmode)))
4066    operands[3] = force_reg (SFmode, operands[3]);
4067
4068  ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4069
4070  operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4071}")
4072
4073(define_expand "movdfcc"
4074  [(set (match_operand:DF 0 "s_register_operand" "")
4075	(if_then_else:DF (match_operand 1 "comparison_operator" "")
4076			 (match_operand:DF 2 "s_register_operand" "")
4077			 (match_operand:DF 3 "fpu_add_operand" "")))]
4078  "TARGET_HARD_FLOAT"
4079  "
4080{
4081  enum rtx_code code = GET_CODE (operands[1]);
4082  rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4083
4084  operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4085}")
4086
4087(define_insn "*movsicc_insn"
4088  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
4089	(if_then_else:SI
4090	 (match_operator 3 "comparison_operator"
4091	  [(match_operand 4 "cc_register" "") (const_int 0)])
4092	 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
4093	 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
4094  ""
4095  "@
4096   mov%D3\\t%0, %2
4097   mvn%D3\\t%0, #%B2
4098   mov%d3\\t%0, %1
4099   mvn%d3\\t%0, #%B1
4100   mov%d3\\t%0, %1\;mov%D3\\t%0, %2
4101   mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
4102   mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
4103   mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
4104  [(set_attr "length" "4,4,4,4,8,8,8,8")
4105   (set_attr "conds" "use")])
4106
4107(define_insn "*movsfcc_hard_insn"
4108  [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4109	(if_then_else:SF
4110	 (match_operator 3 "comparison_operator" 
4111	  [(match_operand 4 "cc_register" "") (const_int 0)])
4112	 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4113	 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4114  "TARGET_HARD_FLOAT"
4115  "@
4116   mvf%D3s\\t%0, %2
4117   mnf%D3s\\t%0, #%N2
4118   mvf%d3s\\t%0, %1
4119   mnf%d3s\\t%0, #%N1
4120   mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
4121   mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
4122   mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
4123   mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
4124  [(set_attr "length" "4,4,4,4,8,8,8,8")
4125   (set_attr "type" "ffarith")
4126   (set_attr "conds" "use")])
4127
4128(define_insn "*movsfcc_soft_insn"
4129  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
4130	(if_then_else:SF (match_operator 3 "comparison_operator"
4131			  [(match_operand 4 "cc_register" "") (const_int 0)])
4132			 (match_operand:SF 1 "s_register_operand" "0,r")
4133			 (match_operand:SF 2 "s_register_operand" "r,0")))]
4134  "TARGET_SOFT_FLOAT"
4135  "@
4136   mov%D3\\t%0, %2
4137   mov%d3\\t%0, %1"
4138  [(set_attr "conds" "use")])
4139
4140(define_insn "*movdfcc_insn"
4141  [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4142	(if_then_else:DF
4143	 (match_operator 3 "comparison_operator"
4144	  [(match_operand 4 "cc_register" "") (const_int 0)])
4145	 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4146	 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4147  "TARGET_HARD_FLOAT"
4148  "@
4149   mvf%D3d\\t%0, %2
4150   mnf%D3d\\t%0, #%N2
4151   mvf%d3d\\t%0, %1
4152   mnf%d3d\\t%0, #%N1
4153   mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
4154   mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
4155   mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
4156   mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
4157  [(set_attr "length" "4,4,4,4,8,8,8,8")
4158   (set_attr "type" "ffarith")
4159   (set_attr "conds" "use")])
4160
4161;; Jump and linkage insns
4162
4163(define_insn "jump"
4164  [(set (pc)
4165	(label_ref (match_operand 0 "" "")))]
4166  ""
4167  "*
4168{
4169  extern int arm_ccfsm_state;
4170
4171  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4172    {
4173      arm_ccfsm_state += 2;
4174      return \"\";
4175    }
4176  return \"b%?\\t%l0\";
4177}")
4178
4179(define_expand "call"
4180  [(parallel [(call (match_operand 0 "memory_operand" "")
4181	            (match_operand 1 "general_operand" ""))
4182	      (clobber (reg:SI 14))])]
4183  ""
4184  "")
4185
4186(define_insn "*call_reg"
4187  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
4188         (match_operand 1 "" "g"))
4189   (clobber (reg:SI 14))]
4190  ""
4191  "*
4192  return output_call (operands);
4193"
4194;; length is worst case, normally it is only two
4195[(set_attr "length" "12")
4196 (set_attr "type" "call")])
4197
4198(define_insn "*call_mem"
4199  [(call (mem:SI (match_operand 0 "memory_operand" "m"))
4200	 (match_operand 1 "general_operand" "g"))
4201   (clobber (reg:SI 14))]
4202  ""
4203  "*
4204  return output_call_mem (operands);
4205"
4206[(set_attr "length" "12")
4207 (set_attr "type" "call")])
4208
4209(define_expand "call_value"
4210  [(parallel [(set (match_operand 0 "" "=rf")
4211	           (call (match_operand 1 "memory_operand" "m")
4212		         (match_operand 2 "general_operand" "g")))
4213	      (clobber (reg:SI 14))])]
4214  ""
4215  "")
4216
4217(define_insn "*call_value_reg"
4218  [(set (match_operand 0 "" "=rf")
4219        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4220	      (match_operand 2 "general_operand" "g")))
4221   (clobber (reg:SI 14))]
4222  ""
4223  "*
4224  return output_call (&operands[1]);
4225"
4226[(set_attr "length" "12")
4227 (set_attr "type" "call")])
4228
4229(define_insn "*call_value_mem"
4230  [(set (match_operand 0 "" "=rf")
4231	(call (mem:SI (match_operand 1 "memory_operand" "m"))
4232	(match_operand 2 "general_operand" "g")))
4233   (clobber (reg:SI 14))]
4234  "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4235  "*
4236  return output_call_mem (&operands[1]);
4237"
4238[(set_attr "length" "12")
4239 (set_attr "type" "call")])
4240
4241;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4242;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4243
4244(define_insn "*call_symbol"
4245  [(call (mem:SI (match_operand:SI 0 "" "X"))
4246	 (match_operand:SI 1 "general_operand" "g"))
4247   (clobber (reg:SI 14))]
4248  "GET_CODE (operands[0]) == SYMBOL_REF"
4249  "*
4250  {
4251    return NEED_PLT_GOT ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
4252  }"
4253[(set_attr "type" "call")])
4254
4255(define_insn "*call_value_symbol"
4256  [(set (match_operand 0 "s_register_operand" "=rf")
4257	(call (mem:SI (match_operand:SI 1 "" "X"))
4258	(match_operand:SI 2 "general_operand" "g")))
4259   (clobber (reg:SI 14))]
4260  "GET_CODE(operands[1]) == SYMBOL_REF"
4261  "*
4262  {
4263    return NEED_PLT_GOT ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
4264  }"
4265[(set_attr "type" "call")])
4266
4267;; Often the return insn will be the same as loading from memory, so set attr
4268(define_insn "return"
4269  [(return)]
4270  "USE_RETURN_INSN(FALSE)"
4271  "*
4272{
4273  extern int arm_ccfsm_state;
4274
4275  if (arm_ccfsm_state == 2)
4276  {
4277    arm_ccfsm_state += 2;
4278    return \"\";
4279  }
4280  return output_return_instruction (NULL, TRUE, FALSE);
4281}"
4282[(set_attr "type" "load")])
4283
4284(define_insn "*cond_return"
4285  [(set (pc)
4286        (if_then_else (match_operator 0 "comparison_operator"
4287		       [(match_operand 1 "cc_register" "") (const_int 0)])
4288                      (return)
4289                      (pc)))]
4290  "USE_RETURN_INSN(TRUE)"
4291  "*
4292{
4293  extern int arm_ccfsm_state;
4294
4295  if (arm_ccfsm_state == 2)
4296  {
4297    arm_ccfsm_state += 2;
4298    return \"\";
4299  }
4300  return output_return_instruction (operands[0], TRUE, FALSE);
4301}"
4302[(set_attr "conds" "use")
4303 (set_attr "type" "load")])
4304
4305(define_insn "*cond_return_inverted"
4306  [(set (pc)
4307        (if_then_else (match_operator 0 "comparison_operator"
4308		       [(match_operand 1 "cc_register" "") (const_int 0)])
4309                      (pc)
4310		      (return)))]
4311  "USE_RETURN_INSN(TRUE)"
4312  "*
4313{
4314  extern int arm_ccfsm_state;
4315
4316  if (arm_ccfsm_state == 2)
4317  {
4318    arm_ccfsm_state += 2;
4319    return \"\";
4320  }
4321  return output_return_instruction (operands[0], TRUE, TRUE);
4322}"
4323[(set_attr "conds" "use")
4324 (set_attr "type" "load")])
4325
4326;; Call subroutine returning any type.
4327
4328(define_expand "untyped_call"
4329  [(parallel [(call (match_operand 0 "" "")
4330		    (const_int 0))
4331	      (match_operand 1 "" "")
4332	      (match_operand 2 "" "")])]
4333  ""
4334  "
4335{
4336  int i;
4337
4338  emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4339
4340  for (i = 0; i < XVECLEN (operands[2], 0); i++)
4341    {
4342      rtx set = XVECEXP (operands[2], 0, i);
4343      emit_move_insn (SET_DEST (set), SET_SRC (set));
4344    }
4345
4346  /* The optimizer does not know that the call sets the function value
4347     registers we stored in the result block.  We avoid problems by
4348     claiming that all hard registers are used and clobbered at this
4349     point.  */
4350  emit_insn (gen_blockage ());
4351
4352  DONE;
4353}")
4354
4355;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4356;; all of memory.  This blocks insns from being moved across this point.
4357
4358(define_insn "blockage"
4359  [(unspec_volatile [(const_int 0)] 0)]
4360  ""
4361  ""
4362[(set_attr "length" "0")
4363 (set_attr "type" "block")])
4364
4365(define_expand "casesi"
4366  [(match_operand:SI 0 "s_register_operand" "")	; index to jump on
4367   (match_operand:SI 1 "const_int_operand" "")	; lower bound
4368   (match_operand:SI 2 "const_int_operand" "")	; total range
4369   (match_operand:SI 3 "" "")			; table label
4370   (match_operand:SI 4 "" "")]			; Out of range label
4371  ""
4372  "
4373{
4374  rtx reg;
4375  if (operands[1] != const0_rtx)
4376    {
4377      reg = gen_reg_rtx (SImode);
4378      emit_insn (gen_addsi3 (reg, operands[0],
4379			     GEN_INT (-INTVAL (operands[1]))));
4380      operands[0] = reg;
4381    }
4382
4383  if (! const_ok_for_arm (INTVAL (operands[2])))
4384    operands[2] = force_reg (SImode, operands[2]);
4385
4386  emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4387				       operands[4]));
4388  DONE;
4389}")
4390
4391;; The USE in this pattern is needed to tell flow analysis that this is
4392;; a CASESI insn.  It has no other purpose.
4393(define_insn "casesi_internal"
4394  [(parallel [(set (pc)
4395	       (if_then_else
4396		(leu (match_operand:SI 0 "s_register_operand" "r")
4397		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
4398		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4399				 (label_ref (match_operand 2 "" ""))))
4400		(label_ref (match_operand 3 "" ""))))
4401	      (use (label_ref (match_dup 2)))])]
4402  ""
4403  "*
4404  if (flag_pic)
4405    return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4406  return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4407"
4408[(set_attr "conds" "clob")
4409 (set_attr "length" "12")])
4410
4411(define_insn "indirect_jump"
4412  [(set (pc)
4413	(match_operand:SI 0 "s_register_operand" "r"))]
4414  ""
4415  "mov%?\\t%|pc, %0\\t%@ indirect jump")
4416
4417(define_insn "*load_indirect_jump"
4418  [(set (pc)
4419	(match_operand:SI 0 "memory_operand" "m"))]
4420  ""
4421  "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4422[(set_attr "type" "load")])
4423
4424;; Misc insns
4425
4426(define_insn "nop"
4427  [(const_int 0)]
4428  ""
4429  "mov%?\\t%|r0, %|r0\\t%@ nop")
4430
4431;; Patterns to allow combination of arithmetic, cond code and shifts
4432
4433(define_insn "*arith_shiftsi"
4434  [(set (match_operand:SI 0 "s_register_operand" "=r")
4435        (match_operator:SI 1 "shiftable_operator"
4436          [(match_operator:SI 3 "shift_operator"
4437             [(match_operand:SI 4 "s_register_operand" "r")
4438              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4439           (match_operand:SI 2 "s_register_operand" "r")]))]
4440  ""
4441  "%i1%?\\t%0, %2, %4%S3")
4442
4443(define_insn "*arith_shiftsi_compare0"
4444  [(set (reg:CC_NOOV 24)
4445        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4446		          [(match_operator:SI 3 "shift_operator"
4447		            [(match_operand:SI 4 "s_register_operand" "r")
4448		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
4449		           (match_operand:SI 2 "s_register_operand" "r")])
4450			 (const_int 0)))
4451   (set (match_operand:SI 0 "s_register_operand" "=r")
4452	(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4453			 (match_dup 2)]))]
4454  ""
4455  "%i1%?s\\t%0, %2, %4%S3"
4456[(set_attr "conds" "set")])
4457
4458(define_insn "*arith_shiftsi_compare0_scratch"
4459  [(set (reg:CC_NOOV 24)
4460        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4461		          [(match_operator:SI 3 "shift_operator"
4462		            [(match_operand:SI 4 "s_register_operand" "r")
4463		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
4464		           (match_operand:SI 2 "s_register_operand" "r")])
4465			 (const_int 0)))
4466   (clobber (match_scratch:SI 0 "=r"))]
4467  ""
4468  "%i1%?s\\t%0, %2, %4%S3"
4469[(set_attr "conds" "set")])
4470
4471(define_insn "*sub_shiftsi"
4472  [(set (match_operand:SI 0 "s_register_operand" "=r")
4473	(minus:SI (match_operand:SI 1 "s_register_operand" "r")
4474		  (match_operator:SI 2 "shift_operator"
4475		   [(match_operand:SI 3 "s_register_operand" "r")
4476		    (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4477  ""
4478  "sub%?\\t%0, %1, %3%S2")
4479
4480(define_insn "*sub_shiftsi_compare0"
4481  [(set (reg:CC_NOOV 24)
4482	(compare:CC_NOOV
4483	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4484		   (match_operator:SI 2 "shift_operator"
4485		    [(match_operand:SI 3 "s_register_operand" "r")
4486		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4487	 (const_int 0)))
4488   (set (match_operand:SI 0 "s_register_operand" "=r")
4489	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4490						 (match_dup 4)])))]
4491  ""
4492  "sub%?s\\t%0, %1, %3%S2"
4493[(set_attr "conds" "set")])
4494
4495(define_insn "*sub_shiftsi_compare0_scratch"
4496  [(set (reg:CC_NOOV 24)
4497	(compare:CC_NOOV
4498	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4499		   (match_operator:SI 2 "shift_operator"
4500		    [(match_operand:SI 3 "s_register_operand" "r")
4501		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4502	 (const_int 0)))
4503   (clobber (match_scratch:SI 0 "=r"))]
4504  ""
4505  "sub%?s\\t%0, %1, %3%S2"
4506[(set_attr "conds" "set")])
4507
4508;; These variants of the above insns can occur if the first operand is the
4509;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
4510;; seem to be a way around it.  Most of the predicates have to be null
4511;; because the format can be generated part way through reload, so
4512;; if we don't match it as soon as it becomes available, reload doesn't know
4513;; how to reload pseudos that haven't got hard registers; the constraints will
4514;; sort everything out.
4515
4516(define_insn "*reload_mulsi3"
4517  [(set (match_operand:SI 0 "" "=&r")
4518	(plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4519			   [(match_operand:SI 3 "" "r")
4520			    (match_operand:SI 4 "" "rM")])
4521			  (match_operand:SI 2 "" "r"))
4522		 (match_operand:SI 1 "const_int_operand" "n")))]
4523  "reload_in_progress"
4524  "*
4525  output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4526  operands[2] = operands[1];
4527  operands[1] = operands[0];
4528  return output_add_immediate (operands);
4529"
4530; we have no idea how long the add_immediate is, it could be up to 4.
4531[(set_attr "length" "20")])
4532
4533(define_insn "*reload_mulsi_compare0"
4534  [(set (reg:CC_NOOV 24)
4535	(compare:CC_NOOV (plus:SI
4536			  (plus:SI 
4537			   (match_operator:SI 5 "shift_operator"
4538			    [(match_operand:SI 3 "" "r")
4539			     (match_operand:SI 4 "" "rM")])
4540			   (match_operand:SI 1 "" "r"))
4541			  (match_operand:SI 2 "const_int_operand" "n"))
4542			 (const_int 0)))
4543   (set (match_operand:SI 0 "" "=&r")
4544	(plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4545			  (match_dup 1))
4546		 (match_dup 2)))]
4547  "reload_in_progress"
4548  "*
4549  output_add_immediate (operands);
4550  return \"add%?s\\t%0, %0, %3%S5\";
4551"
4552[(set_attr "conds" "set")
4553 (set_attr "length" "20")])
4554
4555(define_insn "*reload_mulsi_compare0_scratch"
4556  [(set (reg:CC_NOOV 24)
4557	(compare:CC_NOOV (plus:SI
4558			  (plus:SI 
4559			   (match_operator:SI 5 "shift_operator"
4560			    [(match_operand:SI 3 "" "r")
4561			     (match_operand:SI 4 "" "rM")])
4562			   (match_operand:SI 1 "" "r"))
4563			  (match_operand:SI 2 "const_int_operand" "n"))
4564			 (const_int 0)))
4565   (clobber (match_scratch:SI 0 "=&r"))]
4566  "reload_in_progress"
4567  "*
4568  output_add_immediate (operands);
4569  return \"add%?s\\t%0, %0, %3%S5\";
4570"
4571[(set_attr "conds" "set")
4572 (set_attr "length" "20")])
4573
4574;; These are similar, but are needed when the mla pattern contains the
4575;; eliminated register as operand 3.
4576
4577(define_insn "*reload_muladdsi"
4578  [(set (match_operand:SI 0 "" "=&r,&r")
4579	(plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4580				   (match_operand:SI 2 "" "r,r"))
4581			  (match_operand:SI 3 "" "r,r"))
4582		 (match_operand:SI 4 "const_int_operand" "n,n")))]
4583  "reload_in_progress"
4584  "*
4585  output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4586  operands[2] = operands[4];
4587  operands[1] = operands[0];
4588  return output_add_immediate (operands);
4589"
4590[(set_attr "length" "20")
4591 (set_attr "type" "mult")])
4592
4593(define_insn "*reload_muladdsi_compare0"
4594  [(set (reg:CC_NOOV 24)
4595	(compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4596					    (match_operand:SI 3 "" "r")
4597					    (match_operand:SI 4 "" "r"))
4598					   (match_operand:SI 1 "" "r"))
4599				  (match_operand:SI 2 "const_int_operand" "n"))
4600			 (const_int 0)))
4601   (set (match_operand:SI 0 "" "=&r")
4602	(plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4603		 (match_dup 2)))]
4604  "reload_in_progress"
4605  "*
4606  output_add_immediate (operands);
4607  output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4608  return \"\";
4609"
4610[(set_attr "length" "20")
4611 (set_attr "conds" "set")
4612 (set_attr "type" "mult")])
4613
4614(define_insn "*reload_muladdsi_compare0_scratch"
4615  [(set (reg:CC_NOOV 24)
4616	(compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4617					    (match_operand:SI 3 "" "r")
4618					    (match_operand:SI 4 "" "r"))
4619					   (match_operand:SI 1 "" "r"))
4620				  (match_operand:SI 2 "const_int_operand" "n"))
4621			 (const_int 0)))
4622   (clobber (match_scratch:SI 0 "=&r"))]
4623  "reload_in_progress"
4624  "*
4625  output_add_immediate (operands);
4626  return \"mla%?s\\t%0, %3, %4, %0\";
4627"
4628[(set_attr "length" "20")
4629 (set_attr "conds" "set")
4630 (set_attr "type" "mult")])
4631
4632
4633
4634(define_insn "*and_scc"
4635  [(set (match_operand:SI 0 "s_register_operand" "=r")
4636	(and:SI (match_operator 1 "comparison_operator"
4637		 [(match_operand 3 "cc_register" "") (const_int 0)])
4638		(match_operand:SI 2 "s_register_operand" "r")))]
4639  ""
4640  "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
4641[(set_attr "conds" "use")
4642 (set_attr "length" "8")])
4643
4644(define_insn "*ior_scc"
4645  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4646	(ior:SI (match_operator 2 "comparison_operator"
4647		 [(match_operand 3 "cc_register" "") (const_int 0)])
4648		(match_operand:SI 1 "s_register_operand" "0,?r")))]
4649  ""
4650  "@
4651   orr%d2\\t%0, %1, #1
4652   mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
4653[(set_attr "conds" "use")
4654 (set_attr "length" "4,8")])
4655
4656(define_insn "*compare_scc"
4657  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4658	(match_operator 1 "comparison_operator"
4659	 [(match_operand:SI 2 "s_register_operand" "r,r")
4660	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4661   (clobber (reg:CC 24))]
4662  ""
4663  "*
4664  if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4665    return \"mov\\t%0, %2, lsr #31\";
4666
4667  if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4668    return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4669
4670  if (GET_CODE (operands[1]) == NE)
4671    {
4672      if (which_alternative == 1)
4673	return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4674      return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4675    }
4676  if (which_alternative == 1)
4677    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4678  else
4679    output_asm_insn (\"cmp\\t%2, %3\", operands);
4680  return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4681"
4682[(set_attr "conds" "clob")
4683 (set_attr "length" "12")])
4684
4685(define_insn "*cond_move"
4686  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4687	(if_then_else:SI (match_operator 3 "equality_operator"
4688			  [(match_operator 4 "comparison_operator"
4689			    [(match_operand 5 "cc_register" "") (const_int 0)])
4690			   (const_int 0)])
4691			 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4692			 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4693  ""
4694  "*
4695  if (GET_CODE (operands[3]) == NE)
4696    {
4697      if (which_alternative != 1)
4698	output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4699      if (which_alternative != 0)
4700	output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4701      return \"\";
4702    }
4703  if (which_alternative != 0)
4704    output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4705  if (which_alternative != 1)
4706    output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4707  return \"\";
4708"
4709[(set_attr "conds" "use")
4710 (set_attr "length" "4,4,8")])
4711
4712(define_insn "*cond_arith"
4713  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4714        (match_operator:SI 5 "shiftable_operator" 
4715	 [(match_operator:SI 4 "comparison_operator"
4716           [(match_operand:SI 2 "s_register_operand" "r,r")
4717	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4718          (match_operand:SI 1 "s_register_operand" "0,?r")]))
4719   (clobber (reg:CC 24))]
4720  ""
4721  "*
4722  if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4723    return \"%i5\\t%0, %1, %2, lsr #31\";
4724
4725  output_asm_insn (\"cmp\\t%2, %3\", operands);
4726  if (GET_CODE (operands[5]) == AND)
4727    output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4728  else if (GET_CODE (operands[5]) == MINUS)
4729    output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4730  else if (which_alternative != 0)
4731    output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4732  return \"%i5%d4\\t%0, %1, #1\";
4733"
4734[(set_attr "conds" "clob")
4735 (set_attr "length" "12")])
4736
4737(define_insn "*cond_sub"
4738  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4739        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4740		  (match_operator:SI 4 "comparison_operator"
4741                   [(match_operand:SI 2 "s_register_operand" "r,r")
4742		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4743   (clobber (reg:CC 24))]
4744  ""
4745  "*
4746  output_asm_insn (\"cmp\\t%2, %3\", operands);
4747  if (which_alternative != 0)
4748    output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4749  return \"sub%d4\\t%0, %1, #1\";
4750"
4751[(set_attr "conds" "clob")
4752 (set_attr "length" "8,12")])
4753
4754(define_insn "*cmp_ite0"
4755  [(set (match_operand 6 "dominant_cc_register" "")
4756	(compare
4757	 (if_then_else:SI
4758	  (match_operator 4 "comparison_operator"
4759	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4760	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4761	  (match_operator:SI 5 "comparison_operator"
4762	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4763	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4764	  (const_int 0))
4765	 (const_int 0)))]
4766  ""
4767  "*
4768{
4769  char* opcodes[4][2] =
4770  {
4771    {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
4772    {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
4773    {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
4774    {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
4775     \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
4776  };
4777  int swap =
4778    comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
4779
4780  return opcodes[which_alternative][swap];
4781}
4782"
4783[(set_attr "conds" "set")
4784 (set_attr "length" "8")])
4785
4786(define_insn "*cmp_ite1"
4787  [(set (match_operand 6 "dominant_cc_register" "")
4788	(compare
4789	 (if_then_else:SI
4790	  (match_operator 4 "comparison_operator"
4791	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4792	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4793	  (match_operator:SI 5 "comparison_operator"
4794	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4795	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4796	  (const_int 1))
4797	 (const_int 0)))]
4798  ""
4799  "*
4800{
4801  char* opcodes[4][2] =
4802  {
4803    {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
4804    {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
4805    {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
4806    {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
4807     \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
4808  };
4809  int swap =
4810    comparison_dominates_p (GET_CODE (operands[5]),
4811			    reverse_condition (GET_CODE (operands[4])));
4812
4813  return opcodes[which_alternative][swap];
4814}
4815"
4816[(set_attr "conds" "set")
4817 (set_attr "length" "8")])
4818
4819(define_insn "*negscc"
4820  [(set (match_operand:SI 0 "s_register_operand" "=r")
4821	(neg:SI (match_operator 3 "comparison_operator"
4822		 [(match_operand:SI 1 "s_register_operand" "r")
4823		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4824   (clobber (reg:CC 24))]
4825  ""
4826  "*
4827  if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4828    return \"mov\\t%0, %1, asr #31\";
4829
4830  if (GET_CODE (operands[3]) == NE)
4831    return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4832
4833  if (GET_CODE (operands[3]) == GT)
4834    return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4835
4836  output_asm_insn (\"cmp\\t%1, %2\", operands);
4837  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4838  return \"mvn%d3\\t%0, #0\";
4839"
4840[(set_attr "conds" "clob")
4841 (set_attr "length" "12")])
4842
4843(define_insn "movcond"
4844  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4845	(if_then_else:SI
4846	 (match_operator 5 "comparison_operator"
4847	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
4848	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4849	 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4850	 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4851   (clobber (reg:CC 24))]
4852  ""
4853  "*
4854  if (GET_CODE (operands[5]) == LT
4855      && (operands[4] == const0_rtx))
4856    {
4857      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4858	{
4859	  if (operands[2] == const0_rtx)
4860	    return \"and\\t%0, %1, %3, asr #31\";
4861	  return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4862	}
4863      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4864	{
4865	  if (operands[1] == const0_rtx)
4866	    return \"bic\\t%0, %2, %3, asr #31\";
4867	  return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4868	}
4869      /* The only case that falls through to here is when both ops 1 & 2
4870	 are constants */
4871    }
4872
4873  if (GET_CODE (operands[5]) == GE
4874      && (operands[4] == const0_rtx))
4875    {
4876      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4877	{
4878	  if (operands[2] == const0_rtx)
4879	    return \"bic\\t%0, %1, %3, asr #31\";
4880	  return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4881	}
4882      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4883	{
4884	  if (operands[1] == const0_rtx)
4885	    return \"and\\t%0, %2, %3, asr #31\";
4886	  return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4887	}
4888      /* The only case that falls through to here is when both ops 1 & 2
4889	 are constants */
4890    }
4891  if (GET_CODE (operands[4]) == CONST_INT
4892      && !const_ok_for_arm (INTVAL (operands[4])))
4893    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4894  else
4895    output_asm_insn (\"cmp\\t%3, %4\", operands);
4896  if (which_alternative != 0)
4897    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4898  if (which_alternative != 1)
4899    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4900  return \"\";
4901"
4902[(set_attr "conds" "clob")
4903 (set_attr "length" "8,8,12")])
4904
4905(define_insn "*ifcompare_plus_move"
4906  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4907	(if_then_else:SI (match_operator 6 "comparison_operator"
4908			  [(match_operand:SI 4 "s_register_operand" "r,r")
4909			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4910			 (plus:SI
4911			  (match_operand:SI 2 "s_register_operand" "r,r")
4912			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
4913			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
4914   (clobber (reg:CC 24))]
4915  ""
4916  "#"
4917[(set_attr "conds" "clob")
4918 (set_attr "length" "8,12")])
4919
4920(define_insn "*if_plus_move"
4921  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4922	(if_then_else:SI
4923	 (match_operator 4 "comparison_operator"
4924	  [(match_operand 5 "cc_register" "") (const_int 0)])
4925	 (plus:SI
4926	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4927	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
4928	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
4929  ""
4930  "@
4931   add%d4\\t%0, %2, %3
4932   sub%d4\\t%0, %2, #%n3
4933   add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4934   sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
4935[(set_attr "conds" "use")
4936 (set_attr "length" "4,4,8,8")
4937 (set_attr "type" "*,*,*,*")])
4938
4939(define_insn "*ifcompare_move_plus"
4940  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4941	(if_then_else:SI (match_operator 6 "comparison_operator"
4942			  [(match_operand:SI 4 "s_register_operand" "r,r")
4943			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4944			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4945			 (plus:SI
4946			  (match_operand:SI 2 "s_register_operand" "r,r")
4947			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4948   (clobber (reg:CC 24))]
4949  ""
4950  "#"
4951[(set_attr "conds" "clob")
4952 (set_attr "length" "8,12")])
4953
4954(define_insn "*if_move_plus"
4955  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4956	(if_then_else:SI
4957	 (match_operator 4 "comparison_operator"
4958	  [(match_operand 5 "cc_register" "") (const_int 0)])
4959	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4960	 (plus:SI
4961	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4962	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
4963  ""
4964  "@
4965   add%D4\\t%0, %2, %3
4966   sub%D4\\t%0, %2, #%n3
4967   add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4968   sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
4969[(set_attr "conds" "use")
4970 (set_attr "length" "4,4,8,8")
4971 (set_attr "type" "*,*,*,*")])
4972
4973(define_insn "*ifcompare_arith_arith"
4974  [(set (match_operand:SI 0 "s_register_operand" "=r")
4975	(if_then_else:SI (match_operator 9 "comparison_operator"
4976			  [(match_operand:SI 5 "s_register_operand" "r")
4977			   (match_operand:SI 6 "arm_add_operand" "rIL")])
4978			 (match_operator:SI 8 "shiftable_operator"
4979			  [(match_operand:SI 1 "s_register_operand" "r")
4980			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
4981			 (match_operator:SI 7 "shiftable_operator"
4982			  [(match_operand:SI 3 "s_register_operand" "r")
4983			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))
4984   (clobber (reg:CC 24))]
4985  ""
4986  "#"
4987[(set_attr "conds" "clob")
4988 (set_attr "length" "12")])
4989
4990(define_insn "*if_arith_arith"
4991  [(set (match_operand:SI 0 "s_register_operand" "=r")
4992	(if_then_else:SI (match_operator 5 "comparison_operator"
4993			  [(match_operand 8 "cc_register" "") (const_int 0)])
4994			 (match_operator:SI 6 "shiftable_operator"
4995			  [(match_operand:SI 1 "s_register_operand" "r")
4996			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
4997			 (match_operator:SI 7 "shiftable_operator"
4998			  [(match_operand:SI 3 "s_register_operand" "r")
4999			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
5000  ""
5001  "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
5002[(set_attr "conds" "use")
5003 (set_attr "length" "8")])
5004
5005(define_insn "*ifcompare_arith_move"
5006  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5007	(if_then_else:SI (match_operator 6 "comparison_operator"
5008			  [(match_operand:SI 2 "s_register_operand" "r,r")
5009			   (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
5010			 (match_operator:SI 7 "shiftable_operator"
5011			  [(match_operand:SI 4 "s_register_operand" "r,r")
5012			   (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
5013			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5014   (clobber (reg:CC 24))]
5015  ""
5016  "*
5017  /* If we have an operation where (op x 0) is the identity operation and
5018     the conditional operator is LT or GE and we are comparing against zero and
5019     everything is in registers then we can do this in two instructions */
5020  if (operands[3] == const0_rtx
5021      && GET_CODE (operands[7]) != AND
5022      && GET_CODE (operands[5]) == REG
5023      && GET_CODE (operands[1]) == REG 
5024      && REGNO (operands[1]) == REGNO (operands[4])
5025      && REGNO (operands[4]) != REGNO (operands[0]))
5026    {
5027      if (GET_CODE (operands[6]) == LT)
5028	return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5029      else if (GET_CODE (operands[6]) == GE)
5030	return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5031    }
5032  if (GET_CODE (operands[3]) == CONST_INT
5033      && !const_ok_for_arm (INTVAL (operands[3])))
5034    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
5035  else
5036    output_asm_insn (\"cmp\\t%2, %3\", operands);
5037  output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
5038  if (which_alternative != 0)
5039    return \"mov%D6\\t%0, %1\";
5040  return \"\";
5041"
5042[(set_attr "conds" "clob")
5043 (set_attr "length" "8,12")])
5044
5045(define_insn "*if_arith_move"
5046  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5047	(if_then_else:SI (match_operator 4 "comparison_operator"
5048			  [(match_operand 6 "cc_register" "") (const_int 0)])
5049			 (match_operator:SI 5 "shiftable_operator"
5050			  [(match_operand:SI 2 "s_register_operand" "r,r")
5051			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
5052			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
5053  ""
5054  "@
5055   %I5%d4\\t%0, %2, %3
5056   %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
5057[(set_attr "conds" "use")
5058 (set_attr "length" "4,8")
5059 (set_attr "type" "*,*")])
5060
5061(define_insn "*ifcompare_move_arith"
5062  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5063	(if_then_else:SI (match_operator 6 "comparison_operator"
5064			  [(match_operand:SI 4 "s_register_operand" "r,r")
5065			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5066			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5067			 (match_operator:SI 7 "shiftable_operator"
5068			  [(match_operand:SI 2 "s_register_operand" "r,r")
5069			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
5070   (clobber (reg:CC 24))]
5071  ""
5072  "*
5073  /* If we have an operation where (op x 0) is the identity operation and
5074     the conditional operator is LT or GE and we are comparing against zero and
5075     everything is in registers then we can do this in two instructions */
5076  if (operands[5] == const0_rtx
5077      && GET_CODE (operands[7]) != AND
5078      && GET_CODE (operands[3]) == REG
5079      && GET_CODE (operands[1]) == REG 
5080      && REGNO (operands[1]) == REGNO (operands[2])
5081      && REGNO (operands[2]) != REGNO (operands[0]))
5082    {
5083      if (GET_CODE (operands[6]) == GE)
5084	return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5085      else if (GET_CODE (operands[6]) == LT)
5086	return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5087    }
5088
5089  if (GET_CODE (operands[5]) == CONST_INT
5090      && !const_ok_for_arm (INTVAL (operands[5])))
5091    output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5092  else
5093    output_asm_insn (\"cmp\\t%4, %5\", operands);
5094
5095  if (which_alternative != 0)
5096    output_asm_insn (\"mov%d6\\t%0, %1\", operands);
5097  return \"%I7%D6\\t%0, %2, %3\";
5098"
5099[(set_attr "conds" "clob")
5100 (set_attr "length" "8,12")])
5101
5102(define_insn "*if_move_arith"
5103  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5104	(if_then_else:SI
5105	 (match_operator 4 "comparison_operator"
5106	  [(match_operand 6 "cc_register" "") (const_int 0)])
5107	 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5108	 (match_operator:SI 5 "shiftable_operator"
5109	  [(match_operand:SI 2 "s_register_operand" "r,r")
5110	   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
5111  ""
5112  "@
5113   %I5%D4\\t%0, %2, %3
5114   %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
5115[(set_attr "conds" "use")
5116 (set_attr "length" "4,8")
5117 (set_attr "type" "*,*")])
5118
5119(define_insn "*ifcompare_move_not"
5120  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5121	(if_then_else:SI
5122	 (match_operator 5 "comparison_operator"
5123	  [(match_operand:SI 3 "s_register_operand" "r,r")
5124	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5125	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5126	 (not:SI
5127	  (match_operand:SI 2 "s_register_operand" "r,r"))))
5128   (clobber (reg:CC 24))]
5129  ""
5130  "#"
5131[(set_attr "conds" "clob")
5132 (set_attr "length" "8,12")])
5133
5134(define_insn "*if_move_not"
5135  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5136	(if_then_else:SI
5137	 (match_operator 4 "comparison_operator"
5138	  [(match_operand 3 "cc_register" "") (const_int 0)])
5139	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5140	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5141  ""
5142  "@
5143   mvn%D4\\t%0, %2
5144   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
5145   mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
5146[(set_attr "conds" "use")
5147 (set_attr "length" "4,8,8")])
5148
5149(define_insn "*ifcompare_not_move"
5150  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5151	(if_then_else:SI 
5152	 (match_operator 5 "comparison_operator"
5153	  [(match_operand:SI 3 "s_register_operand" "r,r")
5154	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5155	 (not:SI
5156	  (match_operand:SI 2 "s_register_operand" "r,r"))
5157	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5158   (clobber (reg:CC 24))]
5159  ""
5160  "#"
5161[(set_attr "conds" "clob")
5162 (set_attr "length" "8,12")])
5163
5164(define_insn "*if_not_move"
5165  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5166	(if_then_else:SI
5167	 (match_operator 4 "comparison_operator"
5168	  [(match_operand 3 "cc_register" "") (const_int 0)])
5169	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5170	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5171  ""
5172  "@
5173   mvn%d4\\t%0, %2
5174   mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
5175   mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
5176[(set_attr "conds" "use")
5177 (set_attr "length" "4,8,8")])
5178
5179(define_insn "*ifcompare_shift_move"
5180  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5181	(if_then_else:SI
5182	 (match_operator 6 "comparison_operator"
5183	  [(match_operand:SI 4 "s_register_operand" "r,r")
5184	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5185	 (match_operator:SI 7 "shift_operator"
5186	  [(match_operand:SI 2 "s_register_operand" "r,r")
5187	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
5188	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5189   (clobber (reg:CC 24))]
5190  ""
5191  "#"
5192[(set_attr "conds" "clob")
5193 (set_attr "length" "8,12")])
5194
5195(define_insn "*if_shift_move"
5196  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5197	(if_then_else:SI
5198	 (match_operator 5 "comparison_operator"
5199	  [(match_operand 6 "cc_register" "") (const_int 0)])
5200	 (match_operator:SI 4 "shift_operator"
5201	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
5202	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
5203	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5204  ""
5205  "@
5206   mov%d5\\t%0, %2%S4
5207   mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
5208   mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
5209[(set_attr "conds" "use")
5210 (set_attr "length" "4,8,8")])
5211
5212(define_insn "*ifcompare_move_shift"
5213  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5214	(if_then_else:SI
5215	 (match_operator 6 "comparison_operator"
5216	  [(match_operand:SI 4 "s_register_operand" "r,r")
5217	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5218	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5219	 (match_operator:SI 7 "shift_operator"
5220	  [(match_operand:SI 2 "s_register_operand" "r,r")
5221	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5222   (clobber (reg:CC 24))]
5223  ""
5224  "#"
5225[(set_attr "conds" "clob")
5226 (set_attr "length" "8,12")])
5227
5228(define_insn "*if_move_shift"
5229  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5230	(if_then_else:SI
5231	 (match_operator 5 "comparison_operator"
5232	  [(match_operand 6 "cc_register" "") (const_int 0)])
5233	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5234	 (match_operator:SI 4 "shift_operator"
5235	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
5236	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5237  ""
5238  "@
5239   mov%D5\\t%0, %2%S4
5240   mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5241   mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5242[(set_attr "conds" "use")
5243 (set_attr "length" "4,8,8")])
5244
5245(define_insn "*ifcompare_shift_shift"
5246  [(set (match_operand:SI 0 "s_register_operand" "=r")
5247	(if_then_else:SI
5248	 (match_operator 7 "comparison_operator"
5249	  [(match_operand:SI 5 "s_register_operand" "r")
5250	   (match_operand:SI 6 "arm_add_operand" "rIL")])
5251	 (match_operator:SI 8 "shift_operator"
5252	  [(match_operand:SI 1 "s_register_operand" "r")
5253	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
5254	 (match_operator:SI 9 "shift_operator"
5255	  [(match_operand:SI 3 "s_register_operand" "r")
5256	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5257   (clobber (reg:CC 24))]
5258  ""
5259  "#"
5260[(set_attr "conds" "clob")
5261 (set_attr "length" "12")])
5262
5263(define_insn "*if_shift_shift"
5264  [(set (match_operand:SI 0 "s_register_operand" "=r")
5265	(if_then_else:SI
5266	 (match_operator 5 "comparison_operator"
5267	  [(match_operand 8 "cc_register" "") (const_int 0)])
5268	 (match_operator:SI 6 "shift_operator"
5269	  [(match_operand:SI 1 "s_register_operand" "r")
5270	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
5271	 (match_operator:SI 7 "shift_operator"
5272	  [(match_operand:SI 3 "s_register_operand" "r")
5273	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5274  ""
5275  "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5276[(set_attr "conds" "use")
5277 (set_attr "length" "8")])
5278
5279(define_insn "*ifcompare_not_arith"
5280  [(set (match_operand:SI 0 "s_register_operand" "=r")
5281	(if_then_else:SI
5282	 (match_operator 6 "comparison_operator"
5283	  [(match_operand:SI 4 "s_register_operand" "r")
5284	   (match_operand:SI 5 "arm_add_operand" "rIL")])
5285	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5286	 (match_operator:SI 7 "shiftable_operator"
5287	  [(match_operand:SI 2 "s_register_operand" "r")
5288	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5289   (clobber (reg:CC 24))]
5290  ""
5291  "#"
5292[(set_attr "conds" "clob")
5293 (set_attr "length" "12")])
5294
5295(define_insn "*if_not_arith"
5296  [(set (match_operand:SI 0 "s_register_operand" "=r")
5297	(if_then_else:SI
5298	 (match_operator 5 "comparison_operator"
5299	  [(match_operand 4 "cc_register" "") (const_int 0)])
5300	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5301	 (match_operator:SI 6 "shiftable_operator"
5302	  [(match_operand:SI 2 "s_register_operand" "r")
5303	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5304  ""
5305  "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5306[(set_attr "conds" "use")
5307 (set_attr "length" "8")])
5308
5309(define_insn "*ifcompare_arith_not"
5310  [(set (match_operand:SI 0 "s_register_operand" "=r")
5311	(if_then_else:SI
5312	 (match_operator 6 "comparison_operator"
5313	  [(match_operand:SI 4 "s_register_operand" "r")
5314	   (match_operand:SI 5 "arm_add_operand" "rIL")])
5315	 (match_operator:SI 7 "shiftable_operator"
5316	  [(match_operand:SI 2 "s_register_operand" "r")
5317	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
5318	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5319   (clobber (reg:CC 24))]
5320  ""
5321  "#"
5322[(set_attr "conds" "clob")
5323 (set_attr "length" "12")])
5324
5325(define_insn "*if_arith_not"
5326  [(set (match_operand:SI 0 "s_register_operand" "=r")
5327	(if_then_else:SI
5328	 (match_operator 5 "comparison_operator"
5329	  [(match_operand 4 "cc_register" "") (const_int 0)])
5330	 (match_operator:SI 6 "shiftable_operator"
5331	  [(match_operand:SI 2 "s_register_operand" "r")
5332	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
5333	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5334  ""
5335  "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5336[(set_attr "conds" "use")
5337 (set_attr "length" "8")])
5338
5339(define_insn "*ifcompare_neg_move"
5340  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5341	(if_then_else:SI
5342	 (match_operator 5 "comparison_operator"
5343	  [(match_operand:SI 3 "s_register_operand" "r,r")
5344	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5345	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5346	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5347   (clobber (reg:CC 24))]
5348  ""
5349  "#"
5350[(set_attr "conds" "clob")
5351 (set_attr "length" "8,12")])
5352
5353(define_insn "*if_neg_move"
5354  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5355	(if_then_else:SI
5356	 (match_operator 4 "comparison_operator"
5357	  [(match_operand 3 "cc_register" "") (const_int 0)])
5358	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5359	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5360  ""
5361  "@
5362   rsb%d4\\t%0, %2, #0
5363   mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5364   mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5365[(set_attr "conds" "use")
5366 (set_attr "length" "4,8,8")])
5367
5368(define_insn "*ifcompare_move_neg"
5369  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5370	(if_then_else:SI
5371	 (match_operator 5 "comparison_operator"
5372	  [(match_operand:SI 3 "s_register_operand" "r,r")
5373	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5374	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5375	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5376   (clobber (reg:CC 24))]
5377  ""
5378  "#"
5379[(set_attr "conds" "clob")
5380 (set_attr "length" "8,12")])
5381
5382(define_insn "*if_move_neg"
5383  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5384	(if_then_else:SI
5385	 (match_operator 4 "comparison_operator"
5386	  [(match_operand 3 "cc_register" "") (const_int 0)])
5387	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5388	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5389  ""
5390  "@
5391   rsb%D4\\t%0, %2, #0
5392   mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5393   mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5394[(set_attr "conds" "use")
5395 (set_attr "length" "4,8,8")])
5396
5397(define_insn "*arith_adjacentmem"
5398  [(set (match_operand:SI 0 "s_register_operand" "=r")
5399	(match_operator:SI 1 "shiftable_operator"
5400	 [(match_operand:SI 2 "memory_operand" "m")
5401	  (match_operand:SI 3 "memory_operand" "m")]))
5402   (clobber (match_scratch:SI 4 "=r"))]
5403  "adjacent_mem_locations (operands[2], operands[3])"
5404  "*
5405{
5406  rtx ldm[3];
5407  rtx arith[4];
5408  int val1 = 0, val2 = 0;
5409
5410  if (REGNO (operands[0]) > REGNO (operands[4]))
5411    {
5412      ldm[1] = operands[4];
5413      ldm[2] = operands[0];
5414    }
5415  else
5416    {
5417      ldm[1] = operands[0];
5418      ldm[2] = operands[4];
5419    }
5420  if (GET_CODE (XEXP (operands[2], 0)) != REG)
5421    val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5422  if (GET_CODE (XEXP (operands[3], 0)) != REG)
5423    val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5424  arith[0] = operands[0];
5425  arith[3] = operands[1];
5426  if (val1 < val2)
5427    {
5428      arith[1] = ldm[1];
5429      arith[2] = ldm[2];
5430    }
5431  else
5432    {
5433      arith[1] = ldm[2];
5434      arith[2] = ldm[1];
5435    }
5436  if (val1 && val2)
5437    {
5438      rtx ops[3];
5439      ldm[0] = ops[0] = operands[4];
5440      ops[1] = XEXP (XEXP (operands[2], 0), 0);
5441      ops[2] = XEXP (XEXP (operands[2], 0), 1);
5442      output_add_immediate (ops);
5443      if (val1 < val2)
5444	output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5445      else
5446	output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5447    }
5448  else if (val1)
5449    {
5450      ldm[0] = XEXP (operands[3], 0);
5451      if (val1 < val2)
5452	output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5453      else
5454	output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5455    }
5456  else
5457    {
5458      ldm[0] = XEXP (operands[2], 0);
5459      if (val1 < val2)
5460	output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5461      else
5462	output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5463    }
5464  output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5465  return \"\";
5466}
5467"
5468[(set_attr "length" "12")
5469 (set_attr "type" "load")])
5470
5471;; the arm can support extended pre-inc instructions
5472
5473;; In all these cases, we use operands 0 and 1 for the register being
5474;; incremented because those are the operands that local-alloc will
5475;; tie and these are the pair most likely to be tieable (and the ones
5476;; that will benefit the most).
5477
5478;; We reject the frame pointer if it occurs anywhere in these patterns since
5479;; elimination will cause too many headaches.
5480
5481(define_insn "*strqi_preinc"
5482  [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5483			 (match_operand:SI 2 "index_operand" "rJ")))
5484	(match_operand:QI 3 "s_register_operand" "r"))
5485   (set (match_operand:SI 0 "s_register_operand" "=r")
5486	(plus:SI (match_dup 1) (match_dup 2)))]
5487  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5488   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5489   && (GET_CODE (operands[2]) != REG
5490       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5491  "str%?b\\t%3, [%0, %2]!"
5492[(set_attr "type" "store1")])
5493
5494(define_insn "*strqi_predec"
5495  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5496			  (match_operand:SI 2 "s_register_operand" "r")))
5497	(match_operand:QI 3 "s_register_operand" "r"))
5498   (set (match_operand:SI 0 "s_register_operand" "=r")
5499	(minus:SI (match_dup 1) (match_dup 2)))]
5500  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5501   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5502   && (GET_CODE (operands[2]) != REG
5503       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5504  "str%?b\\t%3, [%0, -%2]!"
5505[(set_attr "type" "store1")])
5506
5507(define_insn "*loadqi_preinc"
5508  [(set (match_operand:QI 3 "s_register_operand" "=r")
5509	(mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5510			 (match_operand:SI 2 "index_operand" "rJ"))))
5511   (set (match_operand:SI 0 "s_register_operand" "=r")
5512	(plus:SI (match_dup 1) (match_dup 2)))]
5513  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5514   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5515   && (GET_CODE (operands[2]) != REG
5516       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5517  "ldr%?b\\t%3, [%0, %2]!"
5518[(set_attr "type" "load")])
5519
5520(define_insn "*loadqi_predec"
5521  [(set (match_operand:QI 3 "s_register_operand" "=r")
5522	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5523			  (match_operand:SI 2 "s_register_operand" "r"))))
5524   (set (match_operand:SI 0 "s_register_operand" "=r")
5525	(minus:SI (match_dup 1) (match_dup 2)))]
5526  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5527   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5528   && (GET_CODE (operands[2]) != REG
5529       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5530  "ldr%?b\\t%3, [%0, -%2]!"
5531[(set_attr "type" "load")])
5532
5533(define_insn "*loadqisi_preinc"
5534  [(set (match_operand:SI 3 "s_register_operand" "=r")
5535	(zero_extend:SI
5536	 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5537			  (match_operand:SI 2 "index_operand" "rJ")))))
5538   (set (match_operand:SI 0 "s_register_operand" "=r")
5539	(plus:SI (match_dup 1) (match_dup 2)))]
5540  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5541   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5542   && (GET_CODE (operands[2]) != REG
5543       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5544  "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5545[(set_attr "type" "load")])
5546
5547(define_insn "*loadqisi_predec"
5548  [(set (match_operand:SI 3 "s_register_operand" "=r")
5549	(zero_extend:SI
5550	 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5551			   (match_operand:SI 2 "s_register_operand" "r")))))
5552   (set (match_operand:SI 0 "s_register_operand" "=r")
5553	(minus:SI (match_dup 1) (match_dup 2)))]
5554  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5555   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5556   && (GET_CODE (operands[2]) != REG
5557       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5558  "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5559[(set_attr "type" "load")])
5560
5561(define_insn "*strsi_preinc"
5562  [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5563			 (match_operand:SI 2 "index_operand" "rJ")))
5564	(match_operand:SI 3 "s_register_operand" "r"))
5565   (set (match_operand:SI 0 "s_register_operand" "=r")
5566	(plus:SI (match_dup 1) (match_dup 2)))]
5567  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5568   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5569   && (GET_CODE (operands[2]) != REG
5570       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5571  "str%?\\t%3, [%0, %2]!"
5572[(set_attr "type" "store1")])
5573
5574(define_insn "*strqi_predec"
5575  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5576			  (match_operand:SI 2 "s_register_operand" "r")))
5577	(match_operand:SI 3 "s_register_operand" "r"))
5578   (set (match_operand:SI 0 "s_register_operand" "=r")
5579	(minus:SI (match_dup 1) (match_dup 2)))]
5580  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5581   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5582   && (GET_CODE (operands[2]) != REG
5583       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5584  "str%?\\t%3, [%0, -%2]!"
5585[(set_attr "type" "store1")])
5586
5587(define_insn "*loadsi_preinc"
5588  [(set (match_operand:SI 3 "s_register_operand" "=r")
5589	(mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5590			 (match_operand:SI 2 "index_operand" "rJ"))))
5591   (set (match_operand:SI 0 "s_register_operand" "=r")
5592	(plus:SI (match_dup 1) (match_dup 2)))]
5593  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5594   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5595   && (GET_CODE (operands[2]) != REG
5596       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5597  "ldr%?\\t%3, [%0, %2]!"
5598[(set_attr "type" "load")])
5599
5600(define_insn "*loadsi_predec"
5601  [(set (match_operand:SI 3 "s_register_operand" "=r")
5602	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5603			  (match_operand:SI 2 "s_register_operand" "r"))))
5604   (set (match_operand:SI 0 "s_register_operand" "=r")
5605	(minus:SI (match_dup 1) (match_dup 2)))]
5606  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5607   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5608   && (GET_CODE (operands[2]) != REG
5609       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5610  "ldr%?\\t%3, [%0, -%2]!"
5611[(set_attr "type" "load")])
5612
5613(define_insn "*loadhi_preinc"
5614  [(set (match_operand:HI 3 "s_register_operand" "=r")
5615	(mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5616			 (match_operand:SI 2 "index_operand" "rJ"))))
5617   (set (match_operand:SI 0 "s_register_operand" "=r")
5618	(plus:SI (match_dup 1) (match_dup 2)))]
5619  "(! BYTES_BIG_ENDIAN)
5620   && ! TARGET_SHORT_BY_BYTES
5621   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5622   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5623   && (GET_CODE (operands[2]) != REG
5624       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5625  "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5626[(set_attr "type" "load")])
5627
5628(define_insn "*loadhi_predec"
5629  [(set (match_operand:HI 3 "s_register_operand" "=r")
5630	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5631			  (match_operand:SI 2 "s_register_operand" "r"))))
5632   (set (match_operand:SI 0 "s_register_operand" "=r")
5633	(minus:SI (match_dup 1) (match_dup 2)))]
5634  "(!BYTES_BIG_ENDIAN)
5635   && ! TARGET_SHORT_BY_BYTES
5636   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5637   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5638   && (GET_CODE (operands[2]) != REG
5639       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5640  "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5641[(set_attr "type" "load")])
5642
5643(define_insn "*strqi_shiftpreinc"
5644  [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5645			  [(match_operand:SI 3 "s_register_operand" "r")
5646			   (match_operand:SI 4 "const_shift_operand" "n")])
5647			 (match_operand:SI 1 "s_register_operand" "0")))
5648	(match_operand:QI 5 "s_register_operand" "r"))
5649   (set (match_operand:SI 0 "s_register_operand" "=r")
5650	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
5651		 (match_dup 1)))]
5652  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5653   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5654   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5655  "str%?b\\t%5, [%0, %3%S2]!"
5656[(set_attr "type" "store1")])
5657
5658(define_insn "*strqi_shiftpredec"
5659  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5660			  (match_operator:SI 2 "shift_operator"
5661			   [(match_operand:SI 3 "s_register_operand" "r")
5662			    (match_operand:SI 4 "const_shift_operand" "n")])))
5663	(match_operand:QI 5 "s_register_operand" "r"))
5664   (set (match_operand:SI 0 "s_register_operand" "=r")
5665	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5666						 (match_dup 4)])))]
5667  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5668   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5669   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5670  "str%?b\\t%5, [%0, -%3%S2]!"
5671[(set_attr "type" "store1")])
5672
5673(define_insn "*loadqi_shiftpreinc"
5674  [(set (match_operand:QI 5 "s_register_operand" "=r")
5675	(mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5676			  [(match_operand:SI 3 "s_register_operand" "r")
5677			   (match_operand:SI 4 "const_shift_operand" "n")])
5678			 (match_operand:SI 1 "s_register_operand" "0"))))
5679   (set (match_operand:SI 0 "s_register_operand" "=r")
5680	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
5681		 (match_dup 1)))]
5682  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5683   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5684   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5685  "ldr%?b\\t%5, [%0, %3%S2]!"
5686[(set_attr "type" "load")])
5687
5688(define_insn "*loadqi_shiftpredec"
5689  [(set (match_operand:QI 5 "s_register_operand" "=r")
5690	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5691			  (match_operator:SI 2 "shift_operator"
5692			   [(match_operand:SI 3 "s_register_operand" "r")
5693			    (match_operand:SI 4 "const_shift_operand" "n")]))))
5694   (set (match_operand:SI 0 "s_register_operand" "=r")
5695	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5696						 (match_dup 4)])))]
5697  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5698   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5699   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5700  "ldr%?b\\t%5, [%0, -%3%S2]!"
5701[(set_attr "type" "load")])
5702
5703(define_insn "*strsi_shiftpreinc"
5704  [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5705			  [(match_operand:SI 3 "s_register_operand" "r")
5706			   (match_operand:SI 4 "const_shift_operand" "n")])
5707			 (match_operand:SI 1 "s_register_operand" "0")))
5708	(match_operand:SI 5 "s_register_operand" "r"))
5709   (set (match_operand:SI 0 "s_register_operand" "=r")
5710	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
5711		 (match_dup 1)))]
5712  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5713   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5714   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5715  "str%?\\t%5, [%0, %3%S2]!"
5716[(set_attr "type" "store1")])
5717
5718(define_insn "*strsi_shiftpredec"
5719  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5720			  (match_operator:SI 2 "shift_operator"
5721			   [(match_operand:SI 3 "s_register_operand" "r")
5722			    (match_operand:SI 4 "const_shift_operand" "n")])))
5723	(match_operand:SI 5 "s_register_operand" "r"))
5724   (set (match_operand:SI 0 "s_register_operand" "=r")
5725	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5726						 (match_dup 4)])))]
5727  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5728   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5729   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5730  "str%?\\t%5, [%0, -%3%S2]!"
5731[(set_attr "type" "store1")])
5732
5733(define_insn "*loadqi_shiftpreinc"
5734  [(set (match_operand:SI 5 "s_register_operand" "=r")
5735	(mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5736			  [(match_operand:SI 3 "s_register_operand" "r")
5737			   (match_operand:SI 4 "const_shift_operand" "n")])
5738			 (match_operand:SI 1 "s_register_operand" "0"))))
5739   (set (match_operand:SI 0 "s_register_operand" "=r")
5740	(plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5741		 (match_dup 1)))]
5742  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5743   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5744   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5745  "ldr%?\\t%5, [%0, %3%S2]!"
5746[(set_attr "type" "load")])
5747
5748(define_insn "*loadqi_shiftpredec"
5749  [(set (match_operand:SI 5 "s_register_operand" "=r")
5750	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5751			  (match_operator:SI 2 "shift_operator"
5752			   [(match_operand:SI 3 "s_register_operand" "r")
5753			    (match_operand:SI 4 "const_shift_operand" "n")]))))
5754   (set (match_operand:SI 0 "s_register_operand" "=r")
5755	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5756						 (match_dup 4)])))]
5757  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5758   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5759   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5760  "ldr%?\\t%5, [%0, -%3%S2]!"
5761[(set_attr "type" "load")])
5762
5763(define_insn "*loadhi_shiftpreinc"
5764  [(set (match_operand:HI 5 "s_register_operand" "=r")
5765	(mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5766			  [(match_operand:SI 3 "s_register_operand" "r")
5767			   (match_operand:SI 4 "const_shift_operand" "n")])
5768			 (match_operand:SI 1 "s_register_operand" "0"))))
5769   (set (match_operand:SI 0 "s_register_operand" "=r")
5770	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
5771		 (match_dup 1)))]
5772  "(! BYTES_BIG_ENDIAN)
5773   && ! TARGET_SHORT_BY_BYTES
5774   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5775   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5776   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5777  "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5778[(set_attr "type" "load")])
5779
5780(define_insn "*loadhi_shiftpredec"
5781  [(set (match_operand:HI 5 "s_register_operand" "=r")
5782	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5783			  (match_operator:SI 2 "shift_operator"
5784			   [(match_operand:SI 3 "s_register_operand" "r")
5785			    (match_operand:SI 4 "const_shift_operand" "n")]))))
5786   (set (match_operand:SI 0 "s_register_operand" "=r")
5787	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5788						 (match_dup 4)])))]
5789  "(! BYTES_BIG_ENDIAN)
5790   && ! TARGET_SHORT_BY_BYTES
5791   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5792   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5793   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5794  "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5795[(set_attr "type" "load")])
5796
5797; It can also support extended post-inc expressions, but combine doesn't
5798; try these....
5799; It doesn't seem worth adding peepholes for anything but the most common
5800; cases since, unlike combine, the increment must immediately follow the load
5801; for this pattern to match.
5802; We must watch to see that the source/destination register isn't also the
5803; same as the base address register, and that if the index is a register,
5804; that it is not the same as the base address register.  In such cases the
5805; instruction that we would generate would have UNPREDICTABLE behaviour so 
5806; we cannot use it.
5807
5808(define_peephole
5809  [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5810	(match_operand:QI 2 "s_register_operand" "r"))
5811   (set (match_dup 0)
5812	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5813  "(REGNO (operands[2]) != REGNO (operands[0]))
5814   && (GET_CODE (operands[1]) != REG || (REGNO (operands[1]) != REGNO (operands[0])))"
5815  "str%?b\\t%2, [%0], %1")
5816
5817(define_peephole
5818  [(set (match_operand:QI 0 "s_register_operand" "=r")
5819	(mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5820   (set (match_dup 1)
5821	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5822  "REGNO (operands[0]) != REGNO (operands[1])
5823   && (GET_CODE (operands[2]) != REG || REGNO (operands[0]) != REGNO (operands[2]))"
5824  "ldr%?b\\t%0, [%1], %2")
5825
5826(define_peephole
5827  [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5828	(match_operand:SI 2 "s_register_operand" "r"))
5829   (set (match_dup 0)
5830	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5831  "(REGNO (operands[2]) != REGNO (operands[0]))
5832   && (GET_CODE (operands[1]) != REG || (REGNO (operands[1]) != REGNO (operands[0])))"
5833  "str%?\\t%2, [%0], %1")
5834
5835(define_peephole
5836  [(set (match_operand:HI 0 "s_register_operand" "=r")
5837	(mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5838   (set (match_dup 1)
5839	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5840  "(! BYTES_BIG_ENDIAN)
5841   && ! TARGET_SHORT_BY_BYTES
5842   && REGNO (operands[0]) != REGNO (operands[1])
5843   && (GET_CODE (operands[2]) != REG || REGNO (operands[0]) != REGNO (operands[2]))"
5844  "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5845
5846(define_peephole
5847  [(set (match_operand:SI 0 "s_register_operand" "=r")
5848	(mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5849   (set (match_dup 1)
5850	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5851  "REGNO (operands[0]) != REGNO (operands[1])
5852   && (GET_CODE (operands[2]) != REG || REGNO (operands[0]) != REGNO (operands[2]))"
5853  "ldr%?\\t%0, [%1], %2")
5854
5855(define_peephole
5856  [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5857			 (match_operand:SI 1 "index_operand" "rJ")))
5858	(match_operand:QI 2 "s_register_operand" "r"))
5859   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5860  "(REGNO (operands[2]) != REGNO (operands[0]))
5861   && (GET_CODE (operands[1]) != REG || (REGNO (operands[1]) != REGNO (operands[0])))"
5862  "str%?b\\t%2, [%0, %1]!")
5863
5864(define_peephole
5865  [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5866			  [(match_operand:SI 0 "s_register_operand" "r")
5867			   (match_operand:SI 1 "const_int_operand" "n")])
5868			 (match_operand:SI 2 "s_register_operand" "+r")))
5869	(match_operand:QI 3 "s_register_operand" "r"))
5870   (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5871			       (match_dup 2)))]
5872  "REGNO (operands[0]) != REGNO (operands[2])
5873   && REGNO (operands[3]) != REGNO (operands[2])"
5874  "str%?b\\t%3, [%2, %0%S4]!")
5875
5876; This pattern is never tried by combine, so do it as a peephole
5877
5878(define_peephole
5879  [(set (match_operand:SI 0 "s_register_operand" "=r")
5880	(match_operand:SI 1 "s_register_operand" "r"))
5881   (set (reg:CC 24)
5882	(compare:CC (match_dup 1) (const_int 0)))]
5883  ""
5884  "sub%?s\\t%0, %1, #0"
5885[(set_attr "conds" "set")])
5886
5887; Peepholes to spot possible load- and store-multiples, if the ordering is
5888; reversed, check that the memory references aren't volatile.
5889
5890(define_peephole
5891  [(set (match_operand:SI 0 "s_register_operand" "=r")
5892        (match_operand:SI 4 "memory_operand" "m"))
5893   (set (match_operand:SI 1 "s_register_operand" "=r")
5894        (match_operand:SI 5 "memory_operand" "m"))
5895   (set (match_operand:SI 2 "s_register_operand" "=r")
5896        (match_operand:SI 6 "memory_operand" "m"))
5897   (set (match_operand:SI 3 "s_register_operand" "=r")
5898        (match_operand:SI 7 "memory_operand" "m"))]
5899  "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5900  "*
5901  return emit_ldm_seq (operands, 4);
5902")
5903
5904(define_peephole
5905  [(set (match_operand:SI 0 "s_register_operand" "=r")
5906        (match_operand:SI 3 "memory_operand" "m"))
5907   (set (match_operand:SI 1 "s_register_operand" "=r")
5908        (match_operand:SI 4 "memory_operand" "m"))
5909   (set (match_operand:SI 2 "s_register_operand" "=r")
5910        (match_operand:SI 5 "memory_operand" "m"))]
5911  "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5912  "*
5913  return emit_ldm_seq (operands, 3);
5914")
5915
5916(define_peephole
5917  [(set (match_operand:SI 0 "s_register_operand" "=r")
5918        (match_operand:SI 2 "memory_operand" "m"))
5919   (set (match_operand:SI 1 "s_register_operand" "=r")
5920        (match_operand:SI 3 "memory_operand" "m"))]
5921  "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5922  "*
5923  return emit_ldm_seq (operands, 2);
5924")
5925
5926(define_peephole
5927  [(set (match_operand:SI 4 "memory_operand" "=m")
5928        (match_operand:SI 0 "s_register_operand" "r"))
5929   (set (match_operand:SI 5 "memory_operand" "=m")
5930        (match_operand:SI 1 "s_register_operand" "r"))
5931   (set (match_operand:SI 6 "memory_operand" "=m")
5932        (match_operand:SI 2 "s_register_operand" "r"))
5933   (set (match_operand:SI 7 "memory_operand" "=m")
5934        (match_operand:SI 3 "s_register_operand" "r"))]
5935  "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5936  "*
5937  return emit_stm_seq (operands, 4);
5938")
5939
5940(define_peephole
5941  [(set (match_operand:SI 3 "memory_operand" "=m")
5942        (match_operand:SI 0 "s_register_operand" "r"))
5943   (set (match_operand:SI 4 "memory_operand" "=m")
5944        (match_operand:SI 1 "s_register_operand" "r"))
5945   (set (match_operand:SI 5 "memory_operand" "=m")
5946        (match_operand:SI 2 "s_register_operand" "r"))]
5947  "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5948  "*
5949  return emit_stm_seq (operands, 3);
5950")
5951
5952(define_peephole
5953  [(set (match_operand:SI 2 "memory_operand" "=m")
5954        (match_operand:SI 0 "s_register_operand" "r"))
5955   (set (match_operand:SI 3 "memory_operand" "=m")
5956        (match_operand:SI 1 "s_register_operand" "r"))]
5957  "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5958  "*
5959  return emit_stm_seq (operands, 2);
5960")
5961
5962;; A call followed by return can be replaced by restoring the regs and
5963;; jumping to the subroutine, provided we aren't passing the address of
5964;; any of our local variables.  If we call alloca then this is unsafe
5965;; since restoring the frame frees the memory, which is not what we want.
5966;; Sometimes the return might have been targeted by the final prescan:
5967;; if so then emit a proper return insn as well.
5968;; Unfortunately, if the frame pointer is required, we don't know if the
5969;; current function has any implicit stack pointer adjustments that will 
5970;; be restored by the return: we can't therefore do a tail call.
5971;; Another unfortunate that we can't handle is if current_function_args_size
5972;; is non-zero: in this case elimination of the argument pointer assumed
5973;; that lr was pushed onto the stack, so eliminating upsets the offset
5974;; calculations.
5975
5976(define_peephole
5977  [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5978			  (match_operand:SI 1 "general_operand" "g"))
5979		    (clobber (reg:SI 14))])
5980   (return)]
5981  "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
5982    && !get_frame_size () && !current_function_calls_alloca
5983    && !frame_pointer_needed && !current_function_args_size)"
5984  "*
5985{
5986  extern rtx arm_target_insn;
5987  extern int arm_ccfsm_state;
5988
5989  if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5990  {
5991    arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5992    output_return_instruction (NULL, TRUE, FALSE);
5993    arm_ccfsm_state = 0;
5994    arm_target_insn = NULL;
5995  }
5996
5997  output_return_instruction (NULL, FALSE, FALSE);
5998  return NEED_PLT_GOT ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
5999}"
6000[(set_attr "type" "call")
6001 (set_attr "length" "8")])
6002
6003(define_peephole
6004  [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6005		   (call (mem:SI (match_operand:SI 1 "" "X"))
6006			 (match_operand:SI 2 "general_operand" "g")))
6007	      (clobber (reg:SI 14))])
6008   (return)]
6009  "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6010    && !get_frame_size () && !current_function_calls_alloca
6011    && !frame_pointer_needed && !current_function_args_size)"
6012  "*
6013{
6014  extern rtx arm_target_insn;
6015  extern int arm_ccfsm_state;
6016
6017  if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6018  {
6019    arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6020    output_return_instruction (NULL, TRUE, FALSE);
6021    arm_ccfsm_state = 0;
6022    arm_target_insn = NULL;
6023  }
6024
6025  output_return_instruction (NULL, FALSE, FALSE);
6026  return NEED_PLT_GOT ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6027}"
6028[(set_attr "type" "call")
6029 (set_attr "length" "8")])
6030
6031;; As above but when this function is not void, we must be returning the
6032;; result of the called subroutine.
6033
6034(define_peephole
6035  [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6036		   (call (mem:SI (match_operand:SI 1 "" "X"))
6037			 (match_operand:SI 2 "general_operand" "g")))
6038	      (clobber (reg:SI 14))])
6039   (use (match_dup 0))
6040   (return)]
6041  "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6042    && !get_frame_size () && !current_function_calls_alloca
6043    && !frame_pointer_needed && !current_function_args_size)"
6044  "*
6045{
6046  extern rtx arm_target_insn;
6047  extern int arm_ccfsm_state;
6048
6049  if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6050  {
6051    arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6052    output_return_instruction (NULL, TRUE, FALSE);
6053    arm_ccfsm_state = 0;
6054    arm_target_insn = NULL;
6055  }
6056
6057  output_return_instruction (NULL, FALSE, FALSE);
6058  return \"b%?\\t%a1\";
6059}"
6060[(set_attr "type" "call")
6061 (set_attr "length" "8")])
6062
6063(define_split
6064  [(set (match_operand:SI 0 "s_register_operand" "")
6065	(and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
6066		       (const_int 0))
6067		(neg:SI (match_operator:SI 2 "comparison_operator"
6068			 [(match_operand:SI 3 "s_register_operand" "")
6069			  (match_operand:SI 4 "arm_rhs_operand" "")]))))
6070   (clobber (match_operand:SI 5 "s_register_operand" ""))]
6071  ""
6072  [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
6073   (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6074			      (match_dup 5)))]
6075  "")
6076
6077;; This split can be used because CC_Z mode implies that the following
6078;; branch will be an equality, or an unsigned inequality, so the sign
6079;; extension is not needed.
6080
6081(define_split
6082  [(set (reg:CC_Z 24)
6083	(compare:CC_Z
6084	 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
6085		    (const_int 24))
6086	 (match_operand 1 "const_int_operand" "")))
6087   (clobber (match_scratch:SI 2 ""))]
6088  "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
6089   == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
6090  [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
6091   (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
6092  "
6093  operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
6094")
6095
6096(define_expand "prologue"
6097  [(clobber (const_int 0))]
6098  ""
6099  "
6100  arm_expand_prologue ();
6101  DONE;
6102")
6103
6104;; This split is only used during output to reduce the number of patterns
6105;; that need assembler instructions adding to them.  We allowed the setting
6106;; of the conditions to be implicit during rtl generation so that
6107;; the conditional compare patterns would work.  However this conflicts to
6108;; some extent with the conditional data operations, so we have to split them
6109;; up again here.
6110
6111(define_split
6112  [(set (match_operand:SI 0 "s_register_operand" "")
6113	(if_then_else:SI (match_operator 1 "comparison_operator"
6114			  [(match_operand 2 "" "") (match_operand 3 "" "")])
6115			 (match_operand 4 "" "")
6116			 (match_operand 5 "" "")))
6117   (clobber (reg:CC 24))]
6118  "reload_completed"
6119  [(set (match_dup 6) (match_dup 7))
6120   (set (match_dup 0) 
6121	(if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
6122			 (match_dup 4)
6123			 (match_dup 5)))]
6124  "
6125{
6126  enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
6127					   operands[3]);
6128
6129  operands[6] = gen_rtx_REG (mode, 24);
6130  operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
6131}
6132")
6133
6134;; The next two patterns occur when an AND operation is followed by a
6135;; scc insn sequence 
6136
6137(define_insn "*sign_extract_onebit"
6138  [(set (match_operand:SI 0 "s_register_operand" "=r")
6139	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6140			 (const_int 1)
6141			 (match_operand:SI 2 "const_int_operand" "n")))]
6142  ""
6143  "*
6144  operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6145  output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6146  return \"mvnne\\t%0, #0\";
6147"
6148[(set_attr "conds" "clob")
6149 (set_attr "length" "8")])
6150
6151(define_insn "*not_signextract_onebit"
6152  [(set (match_operand:SI 0 "s_register_operand" "=r")
6153	(not:SI
6154	 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6155			  (const_int 1)
6156			  (match_operand:SI 2 "const_int_operand" "n"))))]
6157  ""
6158  "*
6159  operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6160  output_asm_insn (\"tst\\t%1, %2\", operands);
6161  output_asm_insn (\"mvneq\\t%0, #0\", operands);
6162  return \"movne\\t%0, #0\";
6163"
6164[(set_attr "conds" "clob")
6165 (set_attr "length" "12")])
6166
6167;; Push multiple registers to the stack.  The first register is in the
6168;; unspec part of the insn; subsequent registers are in parallel (use ...)
6169;; expressions.
6170(define_insn "*push_multi"
6171  [(match_parallel 2 "multi_register_push"
6172    [(set (match_operand:BLK 0 "memory_operand" "=m")
6173	  (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
6174  ""
6175  "*
6176{
6177  char pattern[100];
6178  int i;
6179  extern int lr_save_eliminated;
6180
6181  if (lr_save_eliminated)
6182    {
6183      if (XVECLEN (operands[2], 0) > 1)
6184	abort ();
6185      return \"\";
6186    }
6187  strcpy (pattern, \"stmfd\\t%m0!, {%1\");
6188  for (i = 1; i < XVECLEN (operands[2], 0); i++)
6189    {
6190      strcat (pattern, \", %|\");
6191      strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
6192					      0))]);
6193    }
6194  strcat (pattern, \"}\");
6195  output_asm_insn (pattern, operands);
6196  return \"\";
6197}"
6198[(set_attr "type" "store4")])
6199
6200;; Similarly for the floating point registers
6201(define_insn "*push_fp_multi"
6202  [(match_parallel 2 "multi_register_push"
6203    [(set (match_operand:BLK 0 "memory_operand" "=m")
6204	  (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
6205  ""
6206  "*
6207{
6208  char pattern[100];
6209
6210  sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
6211  output_asm_insn (pattern, operands);
6212  return \"\";
6213}"
6214[(set_attr "type" "f_store")])
6215
6216;; Special patterns for dealing with the constant pool
6217
6218(define_insn "consttable_4"
6219  [(unspec_volatile [(match_operand 0 "" "")] 2)]
6220  ""
6221  "*
6222{
6223  making_const_table = TRUE;
6224  switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6225    {
6226    case MODE_FLOAT:
6227    {
6228      union real_extract u;
6229      bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6230      assemble_real (u.d, GET_MODE (operands[0]));
6231      break;
6232    }
6233    default:
6234      assemble_integer (operands[0], 4, 1);
6235      break;
6236    }
6237  return \"\";
6238}"
6239[(set_attr "length" "4")])
6240
6241(define_insn "consttable_8"
6242  [(unspec_volatile [(match_operand 0 "" "")] 3)]
6243  ""
6244  "*
6245{
6246  making_const_table = TRUE;
6247  switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6248    {
6249    case MODE_FLOAT:
6250    {
6251      union real_extract u;
6252      bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6253      assemble_real (u.d, GET_MODE (operands[0]));
6254      break;
6255    }
6256    default:
6257      assemble_integer (operands[0], 8, 1);
6258      break;
6259    }
6260  return \"\";
6261}"
6262[(set_attr "length" "8")])
6263
6264(define_insn "consttable_end"
6265  [(unspec_volatile [(const_int 0)] 4)]
6266  ""
6267  "*
6268  making_const_table = FALSE;
6269  return \"\";
6270")
6271
6272(define_insn "align_4"
6273  [(unspec_volatile [(const_int 0)] 5)]
6274  ""
6275  "*
6276  assemble_align (32);
6277  return \"\";
6278")
6279