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