(addsi3, subsi3, andsi3, iorsi3, ashlsi3, ashrsi3, lshrsi3, rotrsi3):
[official-gcc.git] / gcc / config / arm / arm.md
blob521d765ca5ca4274820416b052a3c93221437a96
1 ;;- Machine description Acorn RISC Machine for GNU compiler
2 ;;  Copyright (C) 1991, 1993, 1994 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)
7 ;; This file is part of GNU CC.
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.
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.
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.
23 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25 ;; There are patterns in this file to support XFmode arithmetic.
26 ;; Unfortunately RISCiX doesn't work well with these so they are disabled.
27 ;; (See arm.h)
29 ;; UNSPEC Usage:
30 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
31 ;;   the mode is MODE_FLOAT
32 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
33 ;;   the mode is MODE_FLOAT
34 ;; 2 `push multiple' operation: operand 0 is the first register.  Subsequent
35 ;;   registers are in parallel (use...) expressions.
37 ;; Attributes
39 ; condition codes: this one is used by final_prescan_insn to speed up
40 ; conditionalizing instructions.  It saves having to scan the rtl to see if
41 ; it uses or alters the condition codes.
43 ; USE means that the condition codes are used by the insn in the process of
44 ; outputting code, this means (at present) that we can't use the insn in
45 ; inlined branches
47 ; SET means that the purpose of the insn is to set the condition codes in a
48 ; well defined manner.
50 ; CLOB means that the condition codes are altered in an undefined manner, if
51 ; they are altered at all
53 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
54 ; but are if the branch wasn't taken; the effect is to limit the branch
55 ; elimination scanning.
57 ; NOCOND means that the condition codes are niether altered nor affect the
58 ; output of this insn
60 (define_attr "conds" "use,set,clob,jump_clob,nocond"
61         (const_string "nocond"))
63 ; CPU attribute is used to determine whether condition codes are clobbered
64 ; by a call insn: on the arm6 they are if in 32-bit addressing mode; on the
65 ; arm2 and arm3 the condition codes are restored by the return.
67 (define_attr "cpu" "arm2,arm3,arm6" (const (symbol_ref "arm_cpu_attr")))
69 ; LENGTH of an instruction (in bytes)
70 (define_attr "length" "" (const_int 4))
72 ; An assembler sequence may clobber the condition codes without us knowing
73 (define_asm_attributes
74  [(set_attr "conds" "clob")
75   (set_attr "length" "4")])
77 ; TYPE attribute is used to detect floating point instructions which, if
78 ; running on a co-processor can run in parallel with other, basic instructions
79 ; If write-buffer scheduling is enabled then it can also be used in the
80 ; scheduling of writes.
82 ; Classification of each insn
83 ; normal        any data instruction that doesn't hit memory or fp regs
84 ; block         blockage insn, this blocks all functional units
85 ; float         a floating point arithmetic operation (subject to expansion)
86 ; float_em      a floating point arithmetic operation that is normally emulated
87 ; f_load        a floating point load from memory
88 ; f_store       a floating point store to memory
89 ; f_mem_r       a transfer of a floating point register to a real reg via mem
90 ; r_mem_f       the reverse of f_mem_r
91 ; f_2_r         fast transfer float to arm (no memory needed)
92 ; r_2_f         fast transfer arm to float
93 ; call          a subroutine call
94 ; load          any load from memory
95 ; store1        store 1 word to memory from arm registers
96 ; store2        store 2 words
97 ; store3        store 3 words
98 ; store4        store 4 words
100 (define_attr "type"
101         "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" 
102         (const_string "normal"))
104 (define_attr "write_conflict" "no,yes"
105   (if_then_else (eq_attr "type"
106                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
107                 (const_string "yes")
108                 (const_string "no")))
110 ; The write buffer on some of the arm6 processors is hard to model exactly.
111 ; There is room in the buffer for up to two addresses and up to eight words
112 ; of memory, but the two needn't be split evenly.  When writing the two
113 ; addresses are fully pipelined.  However, a read from memory that is not
114 ; currently in the cache will block until the writes have completed.
115 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
116 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
117 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
118 ; cycle to add as well.
120 ;; (define_function_unit {name} {num-units} {n-users} {test}
121 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
122 ;; This is not well tuned, but I don't have all the details.
123 (define_function_unit "fpa" 1 1 (eq_attr "type" "float") 5 0)
125 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store1") 3 3
126         [(eq_attr "write_conflict" "yes")])
127 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store2") 5 5
128         [(eq_attr "write_conflict" "yes")])
129 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store3") 7 7
130         [(eq_attr "write_conflict" "yes")])
131 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store4") 9 9
132         [(eq_attr "write_conflict" "yes")])
133 (define_function_unit "write_buf" 1 2 (eq_attr "type" "r_mem_f") 3 3
134         [(eq_attr "write_conflict" "yes")])
136 ;; Note: For DImode insns, there is normally no reason why operands should
137 ;; not be in the same register, what we don't want is for something being
138 ;; written to partially overlap something that is an input.
140 ;; Addition insns.
142 (define_insn "adddi3"
143   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
144         (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
145                  (match_operand:DI 2 "s_register_operand" "r,0")))
146    (clobber (reg:CC 24))]
147   ""
148   "adds\\t%0, %1, %2\;adc\\t%R0, %R1, %R2"
149 [(set_attr "conds" "clob")
150  (set_attr "length" "8")])
152 (define_insn ""
153   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
154         (plus:DI (sign_extend:DI
155                   (match_operand:SI 1 "s_register_operand" "r,r"))
156                  (match_operand:DI 2 "s_register_operand" "r,0")))
157    (clobber (reg:CC 24))]
158   ""
159   "adds\\t%0, %2, %1\;adc\\t%R0, %R2, %1, asr #31"
160 [(set_attr "conds" "clob")
161  (set_attr "length" "8")])
163 (define_insn ""
164   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
165         (plus:DI (zero_extend:DI
166                   (match_operand:SI 1 "s_register_operand" "r,r"))
167                  (match_operand:DI 2 "s_register_operand" "r,0")))
168    (clobber (reg:CC 24))]
169   ""
170   "adds\\t%0, %2, %1\;adc\\t%R0, %R2, #0"
171 [(set_attr "conds" "clob")
172  (set_attr "length" "8")])
174 (define_expand "addsi3"
175   [(set (match_operand:SI 0 "s_register_operand" "")
176         (plus:SI (match_operand:SI 1 "s_register_operand" "")
177                  (match_operand:SI 2 "reg_or_int_operand" "")))]
178   ""
179   "
180   if (GET_CODE (operands[2]) == CONST_INT)
181     {
182       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
183                           operands[1],
184                           (reload_in_progress || reload_completed ? 0
185                            : preserve_subexpressions_p ()));
186       DONE;
187     }
190 (define_split
191   [(set (match_operand:SI 0 "s_register_operand" "")
192         (plus:SI (match_operand:SI 1 "s_register_operand" "")
193                  (match_operand:SI 2 "const_int_operand" "")))]
194   "! (const_ok_for_arm (INTVAL (operands[2]))
195       || const_ok_for_arm (-INTVAL (operands[2])))"
196   [(clobber (const_int 0))]
197   "
198   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
199                       operands[1], 0);
200   DONE;
203 (define_insn ""
204   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
205         (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
206                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
207   ""
208   "@
209    add%?\\t%0, %1, %2
210    sub%?\\t%0, %1, #%n2
211    #"
212 [(set_attr "length" "4,4,16")])
214 (define_insn ""
215   [(set (reg:CC_NOOV 24)
216         (compare:CC_NOOV
217          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
218                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
219          (const_int 0)))
220    (set (match_operand:SI 0 "s_register_operand" "=r,r")
221         (plus:SI (match_dup 1) (match_dup 2)))]
222   ""
223   "@
224    add%?s\\t%0, %1, %2
225    sub%?s\\t%0, %1, #%n2"
226 [(set_attr "conds" "set")])
228 (define_insn ""
229   [(set (reg:CC 24)
230         (compare:CC (match_operand:SI 1 "s_register_operand" "r,r")
231                     (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
232    (set (match_operand:SI 0 "s_register_operand" "=r,r")
233         (plus:SI (match_dup 1) (match_dup 2)))]
234   ""
235   "@
236    add%?s\\t%0, %1, %2
237    sub%?s\\t%0, %1, #%n2"
238 [(set_attr "conds" "set")])
240 (define_insn "incscc"
241   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
242         (plus:SI (match_operator:SI 2 "comparison_operator"
243                     [(reg 24) (const_int 0)])
244                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
245   ""
246   "@
247   add%d2\\t%0, %1, #1
248   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
249 [(set_attr "conds" "use")
250  (set_attr "length" "4,8")])
252 ; If a constant is too big to fit in a single instruction then the constant
253 ; will be pre-loaded into a register taking at least two insns, we might be
254 ; able to merge it with an add, but it depends on the exact value.
256 (define_split
257   [(set (match_operand:SI 0 "s_register_operand" "=r")
258         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
259                  (match_operand:SI 2 "immediate_operand" "n")))]
260   "!(const_ok_for_arm (INTVAL (operands[2]))
261      || const_ok_for_arm (-INTVAL (operands[2])))"
262   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
263    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
264   "
266   unsigned int val = (unsigned) INTVAL (operands[2]);
267   int i;
268   unsigned int temp;
270   /* this code is similar to the approach followed in movsi, but it must
271      generate exactly two insns */
273   for (i = 30; i >= 0; i -= 2)
274     {
275       if (val & (3 << i))
276         {
277           i -= 6;
278           if (i < 0) i = 0;
279           if (const_ok_for_arm (temp = (val & ~(255 << i))))
280             {
281               val &= 255 << i;
282               break;
283             }
284           /* we might be able to do this as (larger number - small number) */
285           temp = ((val >> i) & 255) + 1;
286           if (temp > 255 && i < 24)
287             {
288               i += 2;
289               temp = ((val >> i) & 255) + 1;
290             }
291           if (const_ok_for_arm ((temp << i) - val))
292             {
293               i = temp << i;
294               temp = (unsigned) - (int) (i - val);
295               val = i;
296               break;
297             }
298           FAIL;
299         }
300     }
301   /* if we got here, we have found a way of doing it in two instructions.
302      the two constants are in val and temp */
303   operands[2] = GEN_INT ((int)val);
304   operands[3] = GEN_INT ((int)temp);
308 (define_insn "addsf3"
309   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
310         (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
311                  (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
312   ""
313   "@
314    adf%?s\\t%0, %1, %2
315    suf%?s\\t%0, %1, #%N2"
316 [(set_attr "type" "float")])
318 (define_insn "adddf3"
319   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
320         (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
321                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
322   ""
323   "@
324    adf%?d\\t%0, %1, %2
325    suf%?d\\t%0, %1, #%N2"
326 [(set_attr "type" "float")])
328 (define_insn ""
329   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
330         (plus:DF (float_extend:DF
331                   (match_operand:SF 1 "s_register_operand" "f,f"))
332                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
333   ""
334   "@
335    adf%?d\\t%0, %1, %2
336    suf%?d\\t%0, %1, #%N2"
337 [(set_attr "type" "float")])
339 (define_insn ""
340   [(set (match_operand:DF 0 "s_register_operand" "=f")
341         (plus:DF (match_operand:DF 1 "s_register_operand" "f")
342                  (float_extend:DF
343                   (match_operand:SF 2 "s_register_operand" "f"))))]
344   ""
345   "adf%?d\\t%0, %1, %2"
346 [(set_attr "type" "float")])
348 (define_insn ""
349   [(set (match_operand:DF 0 "s_register_operand" "=f")
350         (plus:DF (float_extend:DF 
351                   (match_operand:SF 1 "s_register_operand" "f"))
352                  (float_extend:DF
353                   (match_operand:SF 2 "s_register_operand" "f"))))]
354   ""
355   "adf%?d\\t%0, %1, %2"
356 [(set_attr "type" "float")])
358 (define_insn "addxf3"
359   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
360         (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
361                  (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
362   "ENABLE_XF_PATTERNS"
363   "@
364    adf%?e\\t%0, %1, %2
365    suf%?e\\t%0, %1, #%N2"
366 [(set_attr "type" "float")])
368 (define_insn "subdi3"
369   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
370         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
371                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
372    (clobber (reg:CC 24))]
373   ""
374   "subs\\t%0, %1, %2\;sbc\\t%R0, %R1, %R2"
375 [(set_attr "conds" "clob")
376  (set_attr "length" "8")])
378 (define_insn ""
379   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
380         (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
381                   (zero_extend:DI
382                    (match_operand:SI 2 "s_register_operand" "r,r"))))
383    (clobber (reg:CC 24))]
384   ""
385   "subs\\t%0, %1, %2\;sbc\\t%R0, %R1, #0"
386 [(set_attr "conds" "clob")
387  (set_attr "length" "8")])
389 (define_insn ""
390   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
391         (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
392                   (sign_extend:DI
393                    (match_operand:SI 2 "s_register_operand" "r,r"))))
394    (clobber (reg:CC 24))]
395   ""
396   "subs\\t%0, %1, %2\;sbc\\t%R0, %R1, %2, asr #31"
397 [(set_attr "conds" "clob")
398  (set_attr "length" "8")])
400 (define_insn ""
401   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
402         (minus:DI (zero_extend:DI
403                    (match_operand:SI 2 "s_register_operand" "r,r"))
404                   (match_operand:DI 1 "s_register_operand" "?r,0")))
405    (clobber (reg:CC 24))]
406   ""
407   "rsbs\\t%0, %1, %2\;rsc\\t%R0, %R1, #0"
408 [(set_attr "conds" "clob")
409  (set_attr "length" "8")])
411 (define_insn ""
412   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
413         (minus:DI (sign_extend:DI
414                    (match_operand:SI 2 "s_register_operand" "r,r"))
415                   (match_operand:DI 1 "s_register_operand" "?r,0")))
416    (clobber (reg:CC 24))]
417   ""
418   "rsbs\\t%0, %1, %2\;rsc\\t%R0, %R1, %2, asr #31"
419 [(set_attr "conds" "clob")
420  (set_attr "length" "8")])
422 (define_insn ""
423   [(set (match_operand:DI 0 "s_register_operand" "=r")
424         (minus:DI (zero_extend:DI
425                    (match_operand:SI 1 "s_register_operand" "r"))
426                   (zero_extend:DI
427                    (match_operand:SI 2 "s_register_operand" "r"))))
428    (clobber (reg:CC 24))]
429   ""
430   "subs\\t%0, %1, %2\;rsc\\t%R0, %1, %1"
431 [(set_attr "conds" "clob")
432  (set_attr "length" "8")])
434 (define_expand "subsi3"
435   [(set (match_operand:SI 0 "s_register_operand" "")
436         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
437                   (match_operand:SI 2 "s_register_operand" "")))]
438   ""
439   "
440   if (GET_CODE (operands[1]) == CONST_INT)
441     {
442       arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
443                           operands[2],
444                           (reload_in_progress || reload_completed ? 0
445                            : preserve_subexpressions_p ()));
446       DONE;
447     }
450 (define_insn ""
451   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
452         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
453                   (match_operand:SI 2 "s_register_operand" "r,r")))]
454   ""
455   "@
456    rsb%?\\t%0, %2, %1
457    #"
458 [(set_attr "length" "4,16")])
460 (define_split
461   [(set (match_operand:SI 0 "s_register_operand" "")
462         (minus:SI (match_operand:SI 1 "const_int_operand" "")
463                   (match_operand:SI 2 "s_register_operand" "")))]
464   "! const_ok_for_arm (INTVAL (operands[1]))"
465   [(clobber (const_int 0))]
466   "
467   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
468                       operands[2], 0);
469   DONE;
472 (define_insn ""
473   [(set (reg:CC_NOOV 24)
474         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
475                                  (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
476                          (const_int 0)))
477    (set (match_operand:SI 0 "s_register_operand" "=r,r")
478         (minus:SI (match_dup 1) (match_dup 2)))]
479   ""
480   "@
481    sub%?s\\t%0, %1, %2
482    rsb%?s\\t%0, %2, %1"
483 [(set_attr "conds" "set")])
485 (define_insn "decscc"
486   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
487         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
488                   (match_operator:SI 2 "comparison_operator"
489                    [(reg 24) (const_int 0)])))]
490   ""
491   "@
492   sub%d2\\t%0, %1, #1
493   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
494 [(set_attr "conds" "use")
495  (set_attr "length" "*,8")])
497 (define_insn "subsf3"
498   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
499         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
500                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
501   ""
502   "@
503    suf%?s\\t%0, %1, %2
504    rsf%?s\\t%0, %2, %1"
505 [(set_attr "type" "float")])
507 (define_insn "subdf3"
508   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
509         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
510                   (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
511   ""
512   "@
513    suf%?d\\t%0, %1, %2
514    rsf%?d\\t%0, %2, %1"
515 [(set_attr "type" "float")])
517 (define_insn ""
518   [(set (match_operand:DF 0 "s_register_operand" "=f")
519         (minus:DF (float_extend:DF
520                    (match_operand:SF 1 "s_register_operand" "f"))
521                   (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
522   ""
523   "suf%?d\\t%0, %1, %2"
524 [(set_attr "type" "float")])
526 (define_insn ""
527   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
528         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
529                   (float_extend:DF
530                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
531   ""
532   "@
533    suf%?d\\t%0, %1, %2
534    rsf%?d\\t%0, %2, %1"
535 [(set_attr "type" "float")])
537 (define_insn ""
538   [(set (match_operand:DF 0 "s_register_operand" "=f")
539         (minus:DF (float_extend:DF
540                    (match_operand:SF 1 "s_register_operand" "f"))
541                   (float_extend:DF
542                    (match_operand:SF 2 "s_register_operand" "f"))))]
543   ""
544   "suf%?d\\t%0, %1, %2"
545 [(set_attr "type" "float")])
547 (define_insn "subxf3"
548   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
549         (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
550                   (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
551   "ENABLE_XF_PATTERNS"
552   "@
553    suf%?e\\t%0, %1, %2
554    rsf%?e\\t%0, %2, %1"
555 [(set_attr "type" "float")])
557 ;; Multiplication insns
559 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
560 (define_insn "mulsi3"
561   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
562         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
563                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
564   ""
565   "mul%?\\t%0, %2, %1")
567 (define_insn ""
568   [(set (reg:CC_NOOV 24)
569         (compare:CC_NOOV (mult:SI
570                           (match_operand:SI 2 "s_register_operand" "r,r")
571                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
572                          (const_int 0)))
573    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
574         (mult:SI (match_dup 2) (match_dup 1)))]
575   ""
576   "mul%?s\\t%0, %2, %1"
577 [(set_attr "conds" "set")])
579 (define_insn ""
580   [(set (reg:CC_NOOV 24)
581         (compare:CC_NOOV (mult:SI
582                           (match_operand:SI 2 "s_register_operand" "r,r")
583                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
584                          (const_int 0)))
585    (clobber (match_scratch:SI 0 "=&r,&r"))]
586   ""
587   "mul%?s\\t%0, %2, %1"
588 [(set_attr "conds" "set")])
590 ;; Unnamed templates to match MLA instruction.
592 (define_insn ""
593   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
594         (plus:SI
595           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
596                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
597           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
598   ""
599   "mla%?\\t%0, %2, %1, %3")
601 (define_insn ""
602   [(set (reg:CC_NOOV 24)
603         (compare:CC_NOOV (plus:SI
604                           (mult:SI
605                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
606                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
607                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
608                          (const_int 0)))
609    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
610         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
611                  (match_dup 3)))]
612   ""
613   "mla%?s\\t%0, %2, %1, %3"
614 [(set_attr "conds" "set")])
616 (define_insn ""
617   [(set (reg:CC_NOOV 24)
618         (compare:CC_NOOV (plus:SI
619                           (mult:SI
620                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
621                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
622                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
623                          (const_int 0)))
624    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
625   ""
626   "mla%?s\\t%0, %2, %1, %3"
627 [(set_attr "conds" "set")])
629 (define_insn "mulsf3"
630   [(set (match_operand:SF 0 "s_register_operand" "=f")
631         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
632                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
633   ""
634   "fml%?s\\t%0, %1, %2"
635 [(set_attr "type" "float")])
637 (define_insn "muldf3"
638   [(set (match_operand:DF 0 "s_register_operand" "=f")
639         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
640                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
641   ""
642   "muf%?d\\t%0, %1, %2"
643 [(set_attr "type" "float")])
645 (define_insn ""
646   [(set (match_operand:DF 0 "s_register_operand" "=f")
647         (mult:DF (float_extend:DF
648                   (match_operand:SF 1 "s_register_operand" "f"))
649                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
650   ""
651   "muf%?d\\t%0, %1, %2"
652 [(set_attr "type" "float")])
654 (define_insn ""
655   [(set (match_operand:DF 0 "s_register_operand" "=f")
656         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
657                  (float_extend:DF
658                   (match_operand:SF 2 "s_register_operand" "f"))))]
659   ""
660   "muf%?d\\t%0, %1, %2"
661 [(set_attr "type" "float")])
663 (define_insn ""
664   [(set (match_operand:DF 0 "s_register_operand" "=f")
665         (mult:DF (float_extend:DF
666                   (match_operand:SF 1 "s_register_operand" "f"))
667                  (float_extend:DF
668                   (match_operand:SF 2 "s_register_operand" "f"))))]
669   ""
670   "muf%?d\\t%0, %1, %2"
671 [(set_attr "type" "float")])
673 (define_insn "mulxf3"
674   [(set (match_operand:XF 0 "s_register_operand" "=f")
675         (mult:XF (match_operand:XF 1 "s_register_operand" "f")
676                  (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
677   "ENABLE_XF_PATTERNS"
678   "muf%?e\\t%0, %1, %2"
679 [(set_attr "type" "float")])
681 ;; Division insns
683 (define_insn "divsf3"
684   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
685         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
686                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
687   ""
688   "@
689    fdv%?s\\t%0, %1, %2
690    frd%?s\\t%0, %2, %1"
691 [(set_attr "type" "float")])
693 (define_insn "divdf3"
694   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
695         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
696                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
697   ""
698   "@
699    dvf%?d\\t%0, %1, %2
700    rdf%?d\\t%0, %2, %1"
701 [(set_attr "type" "float")])
703 (define_insn ""
704   [(set (match_operand:DF 0 "s_register_operand" "=f")
705         (div:DF (float_extend:DF
706                  (match_operand:SF 1 "s_register_operand" "f"))
707                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
708   ""
709   "dvf%?d\\t%0, %1, %2"
710 [(set_attr "type" "float")])
712 (define_insn ""
713   [(set (match_operand:DF 0 "s_register_operand" "=f")
714         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
715                 (float_extend:DF
716                  (match_operand:SF 2 "s_register_operand" "f"))))]
717   ""
718   "rdf%?d\\t%0, %2, %1"
719 [(set_attr "type" "float")])
721 (define_insn ""
722   [(set (match_operand:DF 0 "s_register_operand" "=f")
723         (div:DF (float_extend:DF
724                  (match_operand:SF 1 "s_register_operand" "f"))
725                 (float_extend:DF
726                  (match_operand:SF 2 "s_register_operand" "f"))))]
727   ""
728   "dvf%?d\\t%0, %1, %2"
729 [(set_attr "type" "float")])
731 (define_insn "divxf3"
732   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
733         (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
734                 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
735   "ENABLE_XF_PATTERNS"
736   "@
737    dvf%?e\\t%0, %1, %2
738    rdf%?e\\t%0, %2, %1"
739 [(set_attr "type" "float")])
741 ;; Modulo insns
743 (define_insn "modsf3"
744   [(set (match_operand:SF 0 "s_register_operand" "=f")
745         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
746                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
747   ""
748   "rmf%?s\\t%0, %1, %2"
749 [(set_attr "type" "float")])
751 (define_insn "moddf3"
752   [(set (match_operand:DF 0 "s_register_operand" "=f")
753         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
754                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
755   ""
756   "rmf%?d\\t%0, %1, %2"
757 [(set_attr "type" "float")])
759 (define_insn ""
760   [(set (match_operand:DF 0 "s_register_operand" "=f")
761         (mod:DF (float_extend:DF
762                  (match_operand:SF 1 "s_register_operand" "f"))
763                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
764   ""
765   "rmf%?d\\t%0, %1, %2"
766 [(set_attr "type" "float")])
768 (define_insn ""
769   [(set (match_operand:DF 0 "s_register_operand" "=f")
770         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
771                 (float_extend:DF
772                  (match_operand:SF 2 "s_register_operand" "f"))))]
773   ""
774   "rmf%?d\\t%0, %1, %2"
775 [(set_attr "type" "float")])
777 (define_insn ""
778   [(set (match_operand:DF 0 "s_register_operand" "=f")
779         (mod:DF (float_extend:DF
780                  (match_operand:SF 1 "s_register_operand" "f"))
781                 (float_extend:DF
782                  (match_operand:SF 2 "s_register_operand" "f"))))]
783   ""
784   "rmf%?d\\t%0, %1, %2"
785 [(set_attr "type" "float")])
787 (define_insn "modxf3"
788   [(set (match_operand:XF 0 "s_register_operand" "=f")
789         (mod:XF (match_operand:XF 1 "s_register_operand" "f")
790                 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
791   "ENABLE_XF_PATTERNS"
792   "rmf%?e\\t%0, %1, %2"
793 [(set_attr "type" "float")])
795 ;; Boolean and,ior,xor insns
797 (define_insn "anddi3"
798   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
799         (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
800                 (match_operand:DI 2 "s_register_operand" "r,0")))]
801   ""
802   "and%?\\t%0, %1, %2\;and%?\\t%R0, %R1, %R2"
803 [(set_attr "length" "8")])
805 (define_insn ""
806   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
807         (and:DI (zero_extend:DI
808                  (match_operand:SI 2 "s_register_operand" "r,r"))
809                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
810   ""
811   "and%?\\t%0, %1, %2\;mov%?\\t%R0, #0"
812 [(set_attr "length" "8")])
814 (define_insn ""
815   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
816         (and:DI (sign_extend:DI
817                  (match_operand:SI 2 "s_register_operand" "r,r"))
818                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
819   ""
820   "and%?\\t%0, %1, %2\;and%?\\t%R0, %R1, %2, asr #31"
821 [(set_attr "length" "8")])
823 (define_expand "andsi3"
824   [(set (match_operand:SI 0 "s_register_operand" "")
825         (and:SI (match_operand:SI 1 "s_register_operand" "")
826                 (match_operand:SI 2 "reg_or_int_operand" "")))]
827   ""
828   "
829   if (GET_CODE (operands[2]) == CONST_INT)
830     {
831       arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
832                           operands[1],
833                           (reload_in_progress || reload_completed
834                            ? 0 : preserve_subexpressions_p ()));
835       DONE;
836     }
839 (define_insn ""
840   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
841         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
842                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
843   ""
844   "@
845    and%?\\t%0, %1, %2
846    bic%?\\t%0, %1, #%B2
847    #"
848 [(set_attr "length" "4,4,16")])
850 (define_split
851   [(set (match_operand:SI 0 "s_register_operand" "")
852         (and:SI (match_operand:SI 1 "s_register_operand" "")
853                 (match_operand:SI 2 "const_int_operand" "")))]
854   "! (const_ok_for_arm (INTVAL (operands[2]))
855       || const_ok_for_arm (~ INTVAL (operands[2])))"
856   [(clobber (const_int 0))]
857   "
858   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
859                        operands[1], 0);
860   DONE;
863 (define_insn ""
864   [(set (reg:CC_NOOV 24)
865         (compare:CC_NOOV
866          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
867                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
868          (const_int 0)))
869    (set (match_operand:SI 0 "s_register_operand" "=r,r")
870         (and:SI (match_dup 1) (match_dup 2)))]
871   ""
872   "@
873    and%?s\\t%0, %1, %2
874    bic%?s\\t%0, %1, #%B2"
875 [(set_attr "conds" "set")])
877 (define_insn ""
878   [(set (reg:CC_NOOV 24)
879         (compare:CC_NOOV
880          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
881                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
882          (const_int 0)))
883    (clobber (match_scratch:SI 3 "=X,r"))]
884   ""
885   "@
886    tst%?\\t%0, %1
887    bic%?s\\t%3, %0, #%B1"
888 [(set_attr "conds" "set")])
890 (define_insn ""
891   [(set (reg:CC_NOOV 24)
892         (compare:CC_NOOV (zero_extract:SI
893                           (match_operand:SI 0 "s_register_operand" "r")
894                           (match_operand:SI 1 "immediate_operand" "n")
895                           (match_operand:SI 2 "immediate_operand" "n"))
896                          (const_int 0)))]
897   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
898    && INTVAL (operands[1]) > 0 
899    && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
900    && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
901   "*
903   unsigned int mask = 0;
904   int cnt = INTVAL (operands[1]);
905   
906   while (cnt--)
907     mask = (mask << 1) | 1;
908   operands[1] = GEN_INT (mask << INTVAL (operands[2]));
909   output_asm_insn (\"tst%?\\t%0, %1\", operands);
910   return \"\";
913 [(set_attr "conds" "set")])
915 (define_insn ""
916   [(set (reg:CC_NOOV 24)
917         (compare:CC_NOOV (zero_extract:SI
918                           (match_operand:QI 0 "memory_operand" "m")
919                           (match_operand 1 "immediate_operand" "n")
920                           (match_operand 2 "immediate_operand" "n"))
921                          (const_int 0)))
922    (clobber (match_scratch:QI 3 "=r"))]
923   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 8
924    && INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8"
925   "*
927   unsigned int mask = 0;
928   int cnt = INTVAL (operands[1]);
929   
930   while (cnt--)
931     mask = (mask << 1) | 1;
932   operands[1] = GEN_INT (mask << INTVAL (operands[2]));
933   output_asm_insn (\"ldr%?b\\t%3, %0\", operands);
934   output_asm_insn (\"tst%?\\t%3, %1\", operands);
935   return \"\";
938 [(set_attr "conds" "set")
939  (set_attr "length" "8")])
941 ;; constants for op 2 will never be given to these patterns.
942 (define_insn ""
943   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
944         (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
945                 (match_operand:DI 1 "s_register_operand" "0,r")))]
946   ""
947   "bic%?\\t%0, %1, %2\;bic%?\\t%R0, %R1, %R2"
948 [(set_attr "length" "8")])
949   
950 (define_insn ""
951   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
952         (and:DI (not:DI (zero_extend:DI
953                          (match_operand:SI 2 "s_register_operand" "r,r")))
954                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
955   ""
956   "@
957    bic%?\\t%0, %1, %2
958    bic%?\\t%0, %1, %2\;mov%?\\t%R0, %R1"
959 [(set_attr "length" "4,8")])
960   
961 (define_insn ""
962   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
963         (and:DI (not:DI (sign_extend:DI
964                          (match_operand:SI 2 "s_register_operand" "r,r")))
965                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
966   ""
967   "bic%?\\t%0, %1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
968 [(set_attr "length" "8")])
969   
970 (define_insn ""
971   [(set (match_operand:SI 0 "s_register_operand" "=r")
972         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
973                 (match_operand:SI 1 "s_register_operand" "r")))]
974   ""
975   "bic%?\\t%0, %1, %2")
977 (define_insn ""
978   [(set (reg:CC_NOOV 24)
979         (compare:CC_NOOV
980          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
981                  (match_operand:SI 1 "s_register_operand" "r"))
982          (const_int 0)))
983    (set (match_operand:SI 0 "s_register_operand" "=r")
984         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
985   ""
986   "bic%?s\\t%0, %1, %2"
987 [(set_attr "conds" "set")])
989 (define_insn ""
990   [(set (reg:CC_NOOV 24)
991         (compare:CC_NOOV
992          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
993                  (match_operand:SI 1 "s_register_operand" "r"))
994          (const_int 0)))
995    (clobber (match_scratch:SI 0 "=r"))]
996   ""
997   "bic%?s\\t%0, %1, %2"
998 [(set_attr "conds" "set")])
1000 (define_insn "iordi3"
1001   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1002         (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1003                 (match_operand:DI 2 "s_register_operand" "r")))]
1004   ""
1005   "orr%?\\t%0, %1, %2\;orr%?\\t%R0, %R1, %R2"
1006 [(set_attr "length" "8")])
1008 (define_insn ""
1009   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1010         (ior:DI (zero_extend:DI
1011                  (match_operand:SI 2 "s_register_operand" "r,r"))
1012                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1013   ""
1014   "@
1015    orr%?\\t%0, %1, %2
1016    orr%?\\t%0, %1, %2\;mov%?\\t%R0, %R1"
1017 [(set_attr "length" "4,8")])
1019 (define_insn ""
1020   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1021         (ior:DI (sign_extend:DI
1022                  (match_operand:SI 2 "s_register_operand" "r,r"))
1023                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1024   ""
1025   "orr%?\\t%0, %1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1026 [(set_attr "length" "8")])
1028 (define_expand "iorsi3"
1029   [(set (match_operand:SI 0 "s_register_operand" "")
1030         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1031                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1032   ""
1033   "
1034   if (GET_CODE (operands[2]) == CONST_INT)
1035     {
1036       arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1037                           operands[1],
1038                           (reload_in_progress || reload_completed
1039                            ? 0 : preserve_subexpressions_p ()));
1040       DONE;
1041     }
1044 (define_insn ""
1045   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1046         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1047                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1048   ""
1049   "@
1050    orr%?\\t%0, %1, %2
1051    #"
1052 [(set_attr "length" "4,16")])
1054 (define_split
1055   [(set (match_operand:SI 0 "s_register_operand" "")
1056         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1057                 (match_operand:SI 2 "const_int_operand" "")))]
1058   "! const_ok_for_arm (INTVAL (operands[2]))"
1059   [(clobber (const_int 0))]
1060   "
1061   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1062                       operands[1], 0);
1063   DONE;
1065   
1066 (define_insn ""
1067   [(set (reg:CC_NOOV 24)
1068         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1069                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1070                          (const_int 0)))
1071    (set (match_operand:SI 0 "s_register_operand" "=r")
1072         (ior:SI (match_dup 1) (match_dup 2)))]
1073   ""
1074   "orr%?s\\t%0, %1, %2"
1075 [(set_attr "conds" "set")])
1077 (define_insn ""
1078   [(set (reg:CC_NOOV 24)
1079         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1080                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1081                          (const_int 0)))
1082    (clobber (match_scratch:SI 0 "=r"))]
1083   ""
1084   "orr%?s\\t%0, %1, %2"
1085 [(set_attr "conds" "set")])
1087 (define_insn "xordi3"
1088   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1089         (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1090                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1091   ""
1092   "eor%?\\t%0, %1, %2\;eor%?\\t%R0, %R1, %R2"
1093 [(set_attr "length" "8")])
1095 (define_insn ""
1096   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1097         (xor:DI (zero_extend:DI
1098                  (match_operand:SI 2 "s_register_operand" "r,r"))
1099                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1100   ""
1101   "@
1102    eor%?\\t%0, %1, %2
1103    eor%?\\t%0, %1, %2\;mov%?\\t%R0, %R1"
1104 [(set_attr "length" "4,8")])
1106 (define_insn ""
1107   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1108         (xor:DI (sign_extend:DI
1109                  (match_operand:SI 2 "s_register_operand" "r,r"))
1110                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1111   ""
1112   "eor%?\\t%0, %1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1113 [(set_attr "length" "8")])
1115 (define_insn "xorsi3"
1116   [(set (match_operand:SI 0 "s_register_operand" "=r")
1117         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1118                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1119   ""
1120   "eor%?\\t%0, %1, %2")
1122 (define_insn ""
1123   [(set (reg:CC_NOOV 24)
1124         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1125                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1126                          (const_int 0)))
1127    (set (match_operand:SI 0 "s_register_operand" "=r")
1128         (xor:SI (match_dup 1) (match_dup 2)))]
1129   ""
1130   "eor%?s\\t%0, %1, %2"
1131 [(set_attr "conds" "set")])
1133 (define_insn ""
1134   [(set (reg:CC_NOOV 24)
1135         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1136                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
1137                          (const_int 0)))]
1138   ""
1139   "teq%?\\t%0, %1"
1140 [(set_attr "conds" "set")])
1142 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
1143 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1144 ;; insns
1146 (define_split
1147   [(set (match_operand:SI 0 "s_register_operand" "=r")
1148         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1149                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1150                 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1151    (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1152   ""
1153   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1154                               (not:SI (match_dup 3))))
1155    (set (match_dup 0) (not:SI (match_dup 4)))]
1156   ""
1159 (define_insn ""
1160   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1161         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1162                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1163                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1164   ""
1165   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1166 [(set_attr "length" "8")])
1170 ;; Minimum and maximum insns
1172 (define_insn "smaxsi3"
1173   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1174         (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1175                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1176    (clobber (reg:CC 24))]
1177   ""
1178   "@
1179    cmp\\t%1, %2\;movlt\\t%0, %2
1180    cmp\\t%1, %2\;movge\\t%0, %1
1181    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1182 [(set_attr "conds" "clob")
1183  (set_attr "length" "8,8,12")])
1185 (define_insn "sminsi3"
1186   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1187         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1188                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1189    (clobber (reg:CC 24))]
1190   ""
1191   "@
1192    cmp\\t%1, %2\;movge\\t%0, %2
1193    cmp\\t%1, %2\;movlt\\t%0, %1
1194    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1195 [(set_attr "conds" "clob")
1196  (set_attr "length" "8,8,12")])
1198 (define_insn "umaxsi3"
1199   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1200         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1201                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1202    (clobber (reg:CC 24))]
1203   ""
1204   "@
1205    cmp\\t%1, %2\;movcc\\t%0, %2
1206    cmp\\t%1, %2\;movcs\\t%0, %1
1207    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1208 [(set_attr "conds" "clob")
1209  (set_attr "length" "8,8,12")])
1211 (define_insn "uminsi3"
1212   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1213         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1214                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1215    (clobber (reg:CC 24))]
1216   ""
1217   "@
1218    cmp\\t%1, %2\;movcs\\t%0, %2
1219    cmp\\t%1, %2\;movcc\\t%0, %1
1220    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1221 [(set_attr "conds" "clob")
1222  (set_attr "length" "8,8,12")])
1224 (define_insn ""
1225   [(set (match_operand:SI 0 "memory_operand" "=m")
1226         (match_operator:SI 3 "minmax_operator"
1227          [(match_operand:SI 1 "s_register_operand" "r")
1228           (match_operand:SI 2 "s_register_operand" "r")]))
1229    (clobber (reg:CC 24))]
1230   ""
1231   "*
1232   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1233                          operands[2]);
1234   output_asm_insn (\"cmp\\t%1, %2\", operands);
1235   output_asm_insn (\"str%d3\\t%1, %0\", operands);
1236   output_asm_insn (\"str%D3\\t%2, %0\", operands);
1237   return \"\";
1239 [(set_attr "conds" "clob")
1240  (set_attr "length" "12")
1241  (set_attr "type" "store1")])
1243 (define_insn ""
1244   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1245         (match_operator:SI 4 "shiftable_operator"
1246          [(match_operator:SI 5 "minmax_operator"
1247            [(match_operand:SI 2 "s_register_operand" "r,r")
1248             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1249           (match_operand:SI 1 "s_register_operand" "0,?r")]))
1250    (clobber (reg:CC 24))]
1251   ""
1252   "*
1254   enum rtx_code code = GET_CODE (operands[4]);
1256   operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1257                          operands[3]);
1258   output_asm_insn (\"cmp\\t%2, %3\", operands);
1259   output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1260   if (which_alternative != 0 || operands[3] != const0_rtx
1261       || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1262     output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1263   return \"\";
1266 [(set_attr "conds" "clob")
1267  (set_attr "length" "12")])
1270 ;; Shift and rotation insns
1272 (define_expand "ashlsi3"
1273   [(set (match_operand:SI 0 "s_register_operand" "")
1274         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
1275                    (match_operand:SI 2 "arm_rhs_operand" "")))]
1276   ""
1277   "
1278   if (GET_CODE (operands[2]) == CONST_INT
1279       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1280     {
1281       emit_insn (gen_movsi (operands[0], const0_rtx));
1282       DONE;
1283     }
1286 (define_expand "ashrsi3"
1287   [(set (match_operand:SI 0 "s_register_operand" "")
1288         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1289                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1290   ""
1291   "
1292   if (GET_CODE (operands[2]) == CONST_INT
1293       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1294     operands[2] = GEN_INT (31);
1297 (define_expand "lshrsi3"
1298   [(set (match_operand:SI 0 "s_register_operand" "")
1299         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1300                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1301   ""
1302   "
1303   if (GET_CODE (operands[2]) == CONST_INT
1304       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1305     {
1306       emit_insn (gen_movsi (operands[0], const0_rtx));
1307       DONE;
1308     }
1311 (define_expand "rotlsi3"
1312   [(set (match_operand:SI 0 "s_register_operand" "")
1313         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1314                      (match_operand:SI 2 "reg_or_int_operand" "")))]
1315   ""
1316   "
1317   if (GET_CODE (operands[2]) == CONST_INT)
1318     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1319   else
1320     {
1321       rtx reg = gen_reg_rtx (SImode);
1322       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1323       operands[2] = reg;
1324     }
1327 (define_expand "rotrsi3"
1328   [(set (match_operand:SI 0 "s_register_operand" "")
1329         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1330                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1331   ""
1332   "
1333   if (GET_CODE (operands[2]) == CONST_INT
1334       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1335     operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1338 (define_insn ""
1339   [(set (match_operand:SI 0 "s_register_operand" "=r")
1340         (match_operator:SI 3 "shift_operator"
1341          [(match_operand:SI 1 "s_register_operand" "r")
1342           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1343   ""
1344   "mov%?\\t%0, %1%S3")
1346 (define_insn ""
1347   [(set (reg:CC_NOOV 24)
1348         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1349                           [(match_operand:SI 1 "s_register_operand" "r")
1350                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1351                          (const_int 0)))
1352    (set (match_operand:SI 0 "s_register_operand" "=r")
1353         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1354   ""
1355   "mov%?s\\t%0, %1%S3"
1356 [(set_attr "conds" "set")])
1358 (define_insn ""
1359   [(set (reg:CC_NOOV 24)
1360         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1361                           [(match_operand:SI 1 "s_register_operand" "r")
1362                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1363                          (const_int 0)))
1364    (clobber (match_scratch:SI 0 "=r"))]
1365   ""
1366   "mov%?s\\t%0, %1%S3"
1367 [(set_attr "conds" "set")])
1369 (define_insn ""
1370   [(set (match_operand:SI 0 "s_register_operand" "=r")
1371         (not:SI (match_operator:SI 3 "shift_operator"
1372                  [(match_operand:SI 1 "s_register_operand" "r")
1373                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1374   ""
1375   "mvn%?\\t%0, %1%S3")
1377 (define_insn ""
1378   [(set (reg:CC_NOOV 24)
1379         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1380                           [(match_operand:SI 1 "s_register_operand" "r")
1381                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1382                          (const_int 0)))
1383    (set (match_operand:SI 0 "s_register_operand" "=r")
1384         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1385   ""
1386   "mvn%?s\\t%0, %1%S3"
1387 [(set_attr "conds" "set")])
1389 (define_insn ""
1390   [(set (reg:CC_NOOV 24)
1391         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1392                           [(match_operand:SI 1 "s_register_operand" "r")
1393                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1394                          (const_int 0)))
1395    (clobber (match_scratch:SI 0 "=r"))]
1396   ""
1397   "mvn%?s\\t%0, %1%S3"
1398 [(set_attr "conds" "set")])
1401 ;; Unary arithmetic insns
1403 (define_insn "negdi2"
1404   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1405         (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1406   ""
1407   "rsbs\\t%0, %1, #0\;rsc\\t%R0, %R1, #0"
1408 [(set_attr "conds" "clob")
1409  (set_attr "length" "8")])
1411 (define_insn "negsi2"
1412   [(set (match_operand:SI 0 "s_register_operand" "=r")
1413         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1414   ""
1415   "rsb%?\\t%0, %1, #0")
1417 (define_insn "negsf2"
1418   [(set (match_operand:SF 0 "s_register_operand" "=f")
1419         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1420   ""
1421   "mnf%?s\\t%0, %1"
1422 [(set_attr "type" "float")])
1424 (define_insn "negdf2"
1425   [(set (match_operand:DF 0 "s_register_operand" "=f")
1426         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1427   ""
1428   "mnf%?d\\t%0, %1"
1429 [(set_attr "type" "float")])
1431 (define_insn ""
1432   [(set (match_operand:DF 0 "s_register_operand" "=f")
1433         (neg:DF (float_extend:DF
1434                  (match_operand:SF 1 "s_register_operand" "f"))))]
1435   ""
1436   "mnf%?d\\t%0, %1"
1437 [(set_attr "type" "float")])
1439 (define_insn "negxf2"
1440   [(set (match_operand:XF 0 "s_register_operand" "=f")
1441         (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1442   "ENABLE_XF_PATTERNS"
1443   "mnf%?e\\t%0, %1"
1444 [(set_attr "type" "float")])
1446 ;; abssi2 doesn't really clobber the condition codes if a different register
1447 ;; is being set.  To keep things simple, assume during rtl manipulations that
1448 ;; it does, but tell the final scan operator the truth.  Similarly for
1449 ;; (neg (abs...))
1451 (define_insn "abssi2"
1452   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1453         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1454    (clobber (reg 24))]
1455   ""
1456   "@
1457    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1458    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1459 [(set_attr "conds" "clob,*")
1460  (set_attr "length" "8")])
1462 (define_insn ""
1463   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1464         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1465    (clobber (reg 24))]
1466   ""
1467   "@
1468    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1469    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1470 [(set_attr "conds" "clob,*")
1471  (set_attr "length" "8")])
1473 (define_insn "abssf2"
1474   [(set (match_operand:SF 0 "s_register_operand" "=f")
1475          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1476   ""
1477   "abs%?s\\t%0, %1"
1478 [(set_attr "type" "float")])
1480 (define_insn "absdf2"
1481   [(set (match_operand:DF 0 "s_register_operand" "=f")
1482         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1483   ""
1484   "abs%?d\\t%0, %1"
1485 [(set_attr "type" "float")])
1487 (define_insn ""
1488   [(set (match_operand:DF 0 "s_register_operand" "=f")
1489         (abs:DF (float_extend:DF
1490                  (match_operand:SF 1 "s_register_operand" "f"))))]
1491   ""
1492   "abs%?d\\t%0, %1"
1493 [(set_attr "type" "float")])
1495 (define_insn "absxf2"
1496   [(set (match_operand:XF 0 "s_register_operand" "=f")
1497         (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1498   "ENABLE_XF_PATTERNS"
1499   "abs%?e\\t%0, %1"
1500 [(set_attr "type" "float")])
1502 (define_insn "sqrtsf2"
1503   [(set (match_operand:SF 0 "s_register_operand" "=f")
1504         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1505   ""
1506   "sqt%?s\\t%0, %1"
1507 [(set_attr "type" "float_em")])
1509 (define_insn "sqrtdf2"
1510   [(set (match_operand:DF 0 "s_register_operand" "=f")
1511         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1512   ""
1513   "sqt%?d\\t%0, %1"
1514 [(set_attr "type" "float_em")])
1516 (define_insn ""
1517   [(set (match_operand:DF 0 "s_register_operand" "=f")
1518         (sqrt:DF (float_extend:DF
1519                   (match_operand:SF 1 "s_register_operand" "f"))))]
1520   ""
1521   "sqt%?d\\t%0, %1"
1522 [(set_attr "type" "float_em")])
1524 (define_insn "sqrtxf2"
1525   [(set (match_operand:XF 0 "s_register_operand" "=f")
1526         (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1527   "ENABLE_XF_PATTERNS"
1528   "sqt%?e\\t%0, %1"
1529 [(set_attr "type" "float_em")])
1531 (define_insn "sinsf2"
1532   [(set (match_operand:SF 0 "s_register_operand" "=f")
1533         (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1534   ""
1535   "sin%?s\\t%0, %1"
1536 [(set_attr "type" "float_em")])
1538 (define_insn "sindf2"
1539   [(set (match_operand:DF 0 "s_register_operand" "=f")
1540         (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1541   ""
1542   "sin%?d\\t%0, %1"
1543 [(set_attr "type" "float_em")])
1545 (define_insn ""
1546   [(set (match_operand:DF 0 "s_register_operand" "=f")
1547         (unspec:DF [(float_extend:DF
1548                      (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1549   ""
1550   "sin%?d\\t%0, %1"
1551 [(set_attr "type" "float_em")])
1553 (define_insn "sinxf2"
1554   [(set (match_operand:XF 0 "s_register_operand" "=f")
1555         (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1556   "ENABLE_XF_PATTERNS"
1557   "sin%?e\\t%0, %1"
1558 [(set_attr "type" "float_em")])
1560 (define_insn "cossf2"
1561   [(set (match_operand:SF 0 "s_register_operand" "=f")
1562         (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
1563   ""
1564   "cos%?s\\t%0, %1"
1565 [(set_attr "type" "float_em")])
1567 (define_insn "cosdf2"
1568   [(set (match_operand:DF 0 "s_register_operand" "=f")
1569         (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
1570   ""
1571   "cos%?d\\t%0, %1"
1572 [(set_attr "type" "float_em")])
1574 (define_insn ""
1575   [(set (match_operand:DF 0 "s_register_operand" "=f")
1576         (unspec:DF [(float_extend:DF
1577                      (match_operand:SF 1 "s_register_operand" "f"))] 1))]
1578   ""
1579   "cos%?d\\t%0, %1"
1580 [(set_attr "type" "float_em")])
1582 (define_insn "cosxf2"
1583   [(set (match_operand:XF 0 "s_register_operand" "=f")
1584         (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
1585   "ENABLE_XF_PATTERNS"
1586   "cos%?e\\t%0, %1"
1587 [(set_attr "type" "float_em")])
1589 (define_insn "one_cmpldi2"
1590   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1591         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1592   ""
1593   "mvn%?\\t%0, %1\;mvn%?\\t%R0, %R1"
1594 [(set_attr "length" "8")])
1596 (define_insn "one_cmplsi2"
1597   [(set (match_operand:SI 0 "s_register_operand" "=r")
1598         (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
1599   ""
1600   "mvn%?\\t%0, %1")
1602 (define_insn ""
1603   [(set (reg:CC_NOOV 24)
1604         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1605                          (const_int 0)))
1606    (set (match_operand:SI 0 "s_register_operand" "=r")
1607         (not:SI (match_dup 1)))]
1608   ""
1609   "mvn%?s\\t%0, %1"
1610 [(set_attr "conds" "set")])
1612 (define_insn ""
1613   [(set (reg:CC_NOOV 24)
1614         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1615                          (const_int 0)))
1616    (clobber (match_scratch:SI 0 "=r"))]
1617   ""
1618   "mvn%?s\\t%0, %1"
1619 [(set_attr "conds" "set")])
1621 ;; Fixed <--> Floating conversion insns
1623 (define_insn "floatsisf2"
1624   [(set (match_operand:SF 0 "s_register_operand" "=f")
1625         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
1626   ""
1627   "flt%?s\\t%0, %1"
1628 [(set_attr "type" "r_2_f")])
1630 (define_insn "floatsidf2"
1631   [(set (match_operand:DF 0 "s_register_operand" "=f")
1632         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
1633   ""
1634   "flt%?d\\t%0, %1"
1635 [(set_attr "type" "r_2_f")])
1637 (define_insn "floatsixf2"
1638   [(set (match_operand:XF 0 "s_register_operand" "=f")
1639         (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
1640   "ENABLE_XF_PATTERNS"
1641   "flt%?e\\t%0, %1"
1642 [(set_attr "type" "r_2_f")])
1644 (define_insn "fix_truncsfsi2"
1645   [(set (match_operand:SI 0 "s_register_operand" "=r")
1646         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
1647   ""
1648   "fix%?z\\t%0, %1"
1649 [(set_attr "type" "f_2_r")])
1651 (define_insn "fix_truncdfsi2"
1652   [(set (match_operand:SI 0 "s_register_operand" "=r")
1653         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
1654   ""
1655   "fix%?z\\t%0, %1"
1656 [(set_attr "type" "f_2_r")])
1658 (define_insn "fix_truncxfsi2"
1659   [(set (match_operand:SI 0 "s_register_operand" "=r")
1660         (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
1661   "ENABLE_XF_PATTERNS"
1662   "fix%?z\\t%0, %1"
1663 [(set_attr "type" "f_2_r")])
1665 ;; Truncation insns
1667 (define_insn "truncdfsf2"
1668   [(set (match_operand:SF 0 "s_register_operand" "=f")
1669         (float_truncate:SF
1670          (match_operand:DF 1 "s_register_operand" "f")))]
1671   ""
1672   "mvf%?s\\t%0, %1"
1673 [(set_attr "type" "float")])
1675 (define_insn "truncxfsf2"
1676   [(set (match_operand:SF 0 "s_register_operand" "=f")
1677         (float_truncate:SF
1678          (match_operand:XF 1 "s_register_operand" "f")))]
1679   "ENABLE_XF_PATTERNS"
1680   "mvf%?s\\t%0, %1"
1681 [(set_attr "type" "float")])
1683 (define_insn "truncxfdf2"
1684   [(set (match_operand:DF 0 "s_register_operand" "=f")
1685         (float_truncate:DF
1686          (match_operand:XF 1 "s_register_operand" "f")))]
1687   "ENABLE_XF_PATTERNS"
1688   "mvf%?d\\t%0, %1"
1689 [(set_attr "type" "float")])
1691 ;; Zero and sign extension instructions.
1693 (define_insn "zero_extendsidi2"
1694   [(set (match_operand:DI 0 "s_register_operand" "=r")
1695         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
1696   ""
1697   "*
1698   if (REGNO (operands[1]) != REGNO (operands[0]))
1699     output_asm_insn (\"mov%?\\t%0, %1\", operands);
1700   return \"mov%?\\t%R0, #0\";
1702 [(set_attr "length" "8")])
1704 (define_insn "zero_extendqidi2"
1705   [(set (match_operand:DI 0 "s_register_operand" "=r,r")
1706         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1707   ""
1708   "@
1709    and%?\\t%0, %1, #255\;mov%?\\t%R0, #0
1710    ldr%?b\\t%0, %1\;mov%?\\t%R0, #0"
1711 [(set_attr "length" "8")
1712  (set_attr "type" "*,load")])
1714 (define_insn "extendsidi2"
1715   [(set (match_operand:DI 0 "s_register_operand" "=r")
1716         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
1717   ""
1718   "*
1719   if (REGNO (operands[1]) != REGNO (operands[0]))
1720     output_asm_insn (\"mov%?\\t%0, %1\", operands);
1721   return \"mov%?\\t%R0, %0, asr #31\";
1723 [(set_attr "length" "8")])
1725 (define_expand "zero_extendhisi2"
1726   [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "s_register_operand" "")
1727                                  (const_int 16)))
1728    (set (match_operand:SI 0 "s_register_operand" "")
1729         (lshiftrt:SI (match_dup 2) (const_int 16)))]
1730   ""
1731   "
1732 { operands[1] = gen_lowpart (SImode, operands[1]);
1733   operands[2] = gen_reg_rtx (SImode); 
1736 (define_expand "zero_extendqisi2"
1737   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1738         (zero_extend:SI
1739          (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1740   ""
1741   "
1742   if (GET_CODE (operands[1]) != MEM)
1743     {
1744       emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
1745                              GEN_INT (255)));
1746       DONE;
1747     }
1750 (define_insn ""
1751   [(set (match_operand:SI 0 "s_register_operand" "=r")
1752         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
1753   ""
1754   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
1755 [(set_attr "type" "load")])
1757 (define_split
1758   [(set (match_operand:SI 0 "s_register_operand" "")
1759         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
1760    (clobber (match_operand:SI 2 "s_register_operand" ""))]
1761   "GET_CODE (operands[1]) != MEM"
1762   [(set (match_dup 2) (match_dup 1))
1763    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
1764   "")
1766 (define_insn ""
1767   [(set (reg:CC_NOOV 24)
1768         (compare:CC_NOOV (match_operand:QI 0 "s_register_operand" "r")
1769                          (const_int 0)))]
1770   ""
1771   "tst\\t%0, #255"
1772 [(set_attr "conds" "set")])
1774 (define_expand "extendhisi2"
1775   [(set (match_dup 2)
1776         (ashift:SI (match_operand:HI 1 "s_register_operand" "")
1777                    (const_int 16)))
1778    (set (match_operand:SI 0 "s_register_operand" "")
1779         (ashiftrt:SI (match_dup 2)
1780                      (const_int 16)))]
1781   ""
1782   "
1783 { operands[1] = gen_lowpart (SImode, operands[1]);
1784   operands[2] = gen_reg_rtx (SImode); }")
1786 (define_expand "extendqihi2"
1787   [(set (match_dup 2)
1788         (ashift:SI (match_operand:QI 1 "s_register_operand" "")
1789                    (const_int 24)))
1790    (set (match_operand:HI 0 "s_register_operand" "")
1791         (ashiftrt:SI (match_dup 2)
1792                      (const_int 24)))]
1793   ""
1794   "
1795 { operands[0] = gen_lowpart (SImode, operands[0]);
1796   operands[1] = gen_lowpart (SImode, operands[1]);
1797   operands[2] = gen_reg_rtx (SImode); }")
1799 (define_expand "extendqisi2"
1800   [(set (match_dup 2)
1801         (ashift:SI (match_operand:QI 1 "s_register_operand" "")
1802                    (const_int 24)))
1803    (set (match_operand:SI 0 "s_register_operand" "")
1804         (ashiftrt:SI (match_dup 2)
1805                      (const_int 24)))]
1806   ""
1807   "
1808 { operands[1] = gen_lowpart (SImode, operands[1]);
1809   operands[2] = gen_reg_rtx (SImode); }")
1811 (define_insn "extendsfdf2"
1812   [(set (match_operand:DF 0 "s_register_operand" "=f")
1813         (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
1814   ""
1815   "mvf%?d\\t%0, %1"
1816 [(set_attr "type" "float")])
1818 (define_insn "extendsfxf2"
1819   [(set (match_operand:XF 0 "s_register_operand" "=f")
1820         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
1821   "ENABLE_XF_PATTERNS"
1822   "mvf%?e\\t%0, %1")
1824 (define_insn "extenddfxf2"
1825   [(set (match_operand:XF 0 "s_register_operand" "=f")
1826         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
1827   "ENABLE_XF_PATTERNS"
1828   "mvf%?e\\t%0, %1"
1829 [(set_attr "type" "float")])
1832 ;; Move insns (including loads and stores)
1834 ;; XXX Just some ideas about movti.
1835 ;; I don't think these are a good idea on the arm, there just aren't enough
1836 ;; registers
1837 ;;(define_expand "loadti"
1838 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
1839 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
1840 ;;  "" "")
1842 ;;(define_expand "storeti"
1843 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
1844 ;;      (match_operand:TI 1 "s_register_operand" ""))]
1845 ;;  "" "")
1847 ;;(define_expand "movti"
1848 ;;  [(set (match_operand:TI 0 "general_operand" "")
1849 ;;      (match_operand:TI 1 "general_operand" ""))]
1850 ;;  ""
1851 ;;  "
1853 ;;  rtx insn;
1855 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
1856 ;;    operands[1] = copy_to_reg (operands[1]);
1857 ;;  if (GET_CODE (operands[0]) == MEM)
1858 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
1859 ;;  else if (GET_CODE (operands[1]) == MEM)
1860 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
1861 ;;  else
1862 ;;    FAIL;
1864 ;;  emit_insn (insn);
1865 ;;  DONE;
1866 ;;}")
1868 ;; Recognise garbage generated above.
1870 ;;(define_insn ""
1871 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
1872 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
1873 ;;  ""
1874 ;;  "*
1875 ;;  {
1876 ;;    register mem = (which_alternative < 3);
1877 ;;    register char *template;
1879 ;;    operands[mem] = XEXP (operands[mem], 0);
1880 ;;    switch (which_alternative)
1881 ;;      {
1882 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
1883 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
1884 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
1885 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
1886 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
1887 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
1888 ;;      }
1889 ;;    output_asm_insn (template, operands);
1890 ;;    return \"\";
1891 ;;  }")
1894 (define_insn "movdi"
1895   [(set (match_operand:DI 0 "di_operand" "=r,r,r,o<>,r")
1896         (match_operand:DI 1 "di_operand" "rIK,n,o<>,r,F"))]
1897   ""
1898   "*
1899   return (output_move_double (operands));
1901 [(set_attr "length" "8,32,8,8,32")
1902  (set_attr "type" "*,*,load,store2,*")])
1904 (define_expand "movsi"
1905   [(set (match_operand:SI 0 "general_operand" "")
1906         (match_operand:SI 1 "general_operand" ""))]
1907   ""
1908   "
1909   /* Everything except mem = const or mem = mem can be done easily */
1910   if (GET_CODE (operands[0]) == MEM)
1911     operands[1] = force_reg (SImode, operands[1]);
1912   if (GET_CODE (operands[1]) == CONST_INT
1913       && !(const_ok_for_arm (INTVAL (operands[1]))
1914            || const_ok_for_arm (~INTVAL (operands[1]))))
1915     {
1916       arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
1917                           NULL_RTX,
1918                           (reload_in_progress || reload_completed ? 0
1919                            : preserve_subexpressions_p ()));
1920       DONE;
1921     }
1924 (define_insn ""
1925   [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,m,r,r")
1926         (match_operand:SI 1 "general_operand"  "R,m,K,rI,r,S,?n"))]
1927   "(register_operand (operands[0], SImode)
1928     && (GET_CODE (operands[1]) != SYMBOL_REF
1929         || CONSTANT_ADDRESS_P (operands[1])))
1930    || register_operand (operands[1], SImode)"
1931   "*
1932   switch (which_alternative)
1933     {
1934     case 0:
1935       /* NB Calling get_attr_length may cause the insn to be re-extracted... */
1936       if (get_attr_length (insn) == 8)
1937         {
1938           /* ... so modify the operands here.  */
1939           operands[1] = XEXP (operands[1], 0);
1940           output_asm_insn (\"sub%?\\t%0, %|pc, #(8 + . - %a1) & ~4095\",
1941                            operands);
1942           output_asm_insn (\"ldr%?\\t%0, [%0, #- ((4 + . - %a1) & 4095)]\",
1943                            operands);
1944         }
1945       else
1946         {
1947           /* ... and here.  */
1948           operands[1] = XEXP (operands[1], 0);
1949           output_asm_insn (\"ldr%?\\t%0, [%|pc, %1 - . - 8]\", operands);
1950         }
1951       return \"\";
1953     case 1:
1954       if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
1955           &&  CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
1956         abort ();
1957       return \"ldr%?\\t%0, %1\";
1959     case 3:
1960       return \"mov%?\\t%0, %1\";
1961     case 2:
1962       return \"mvn%?\\t%0, #%B1\";
1963     case 4:
1964       return \"str%?\\t%1, %0\";
1965     case 5:
1966       return output_load_symbol (insn, operands);
1967     case 6:
1968       return \"#\";
1969     }
1971 [(set (attr "length")
1972       (cond [(eq_attr "alternative" "0")
1973              (if_then_else
1974               (gt (minus 
1975                    (pc)
1976                    (symbol_ref "const_pool_offset (XEXP (operands[1], 0))"))
1977                   (const_int 4087))
1978               (const_int 8)
1979               (const_int 4))
1980              (ior (eq_attr "alternative" "5")
1981                   (eq_attr "alternative" "6")) (const_int 16)]
1982             (const_int 4)))
1983  (set_attr "type" "load,load,*,*,store1,*,*")])
1985 (define_split
1986   [(set (match_operand:SI 0 "s_register_operand" "")
1987         (match_operand:SI 1 "const_int_operand" ""))]
1988   "! (const_ok_for_arm (INTVAL (operands[1]))
1989       || const_ok_for_arm (~INTVAL (operands[1])))"
1990   [(clobber (const_int 0))]
1991   "
1992   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
1993                       NULL_RTX, 0);
1994   DONE;
1997 ;; If copying one reg to another we can set the condition codes according to
1998 ;; its value.  Such a move is common after a return from subroutine and the
1999 ;; result is being tested against zero.
2001 (define_insn ""
2002   [(set (reg:CC 24) (compare (match_operand:SI 1 "s_register_operand" "0,r")
2003                              (const_int 0)))
2004    (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2005   ""
2006   "@
2007    cmp%?\\t%0, #0
2008    sub%?s\\t%0, %1, #0"
2009 [(set_attr "conds" "set")])
2011 ;; Subroutine to store a half word from a register into memory.
2012 ;; Operand 0 is the source register (HImode)
2013 ;; Operand 1 is the destination address in a register (SImode)
2015 ;; In both this routine and the next, we must be careful not to spill
2016 ;; a memory address of reg+large_const into a seperate PLUS insn, since this
2017 ;; can generate unrecognizable rtl.
2019 (define_expand "storehi"
2020   [;; store the low byte
2021    (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3))
2022    ;; extract the high byte
2023    (set (match_dup 2)
2024         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2025    ;; store the high byte
2026    (set (mem:QI (match_dup 4))
2027         (subreg:QI (match_dup 2) 0))]   ;explicit subreg safe
2028   ""
2029   "
2031   enum rtx_code code = GET_CODE (operands[1]);
2033   if ((code == PLUS || code == MINUS)
2034       && (GET_CODE (XEXP (operands[1], 1)) == REG
2035           || GET_CODE (XEXP (operands[1], 0)) != REG))
2036     operands[1] = force_reg (SImode, operands[1]);
2037   operands[4] = plus_constant (operands[1], 1);
2038   operands[3] = gen_lowpart (QImode, operands[0]);
2039   operands[0] = gen_lowpart (SImode, operands[0]);
2040   operands[2] = gen_reg_rtx (SImode); 
2044 (define_expand "storehi_bigend"
2045   [(set (mem:QI (match_dup 4)) (match_dup 3))
2046    (set (match_dup 2)
2047         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2048    (set (mem:QI (match_operand 1 "" ""))
2049         (subreg:QI (match_dup 2) 0))]
2050   ""
2051   "
2053   enum rtx_code code = GET_CODE (operands[1]);
2054   if ((code == PLUS || code == MINUS)
2055       && (GET_CODE (XEXP (operands[1], 1)) == REG
2056           || GET_CODE (XEXP (operands[1], 0)) != REG))
2057     operands[1] = force_reg (SImode, operands[1]);
2059   operands[4] = plus_constant (operands[1], 1);
2060   operands[3] = gen_lowpart (QImode, operands[0]);
2061   operands[0] = gen_lowpart (SImode, operands[0]);
2062   operands[2] = gen_reg_rtx (SImode);
2066 ;; Subroutine to store a half word integer constant into memory.
2067 (define_expand "storeinthi"
2068   [(set (mem:QI (match_operand:SI 0 "" ""))
2069         (subreg:QI (match_operand 1 "" "") 0))
2070    (set (mem:QI (match_dup 3)) (subreg:QI (match_dup 2) 0))]
2071   ""
2072   "
2074   HOST_WIDE_INT value = INTVAL (operands[1]);
2075   enum rtx_code code = GET_CODE (operands[0]);
2077   if ((code == PLUS || code == MINUS)
2078       && (GET_CODE (XEXP (operands[0], 1)) == REG
2079           || GET_CODE (XEXP (operands[0], 0)) != REG))
2080   operands[0] = force_reg (SImode, operands[0]);
2082   operands[1] = gen_reg_rtx (SImode);
2083   if (BYTES_BIG_ENDIAN)
2084     {
2085       emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2086       if ((value & 255) == ((value >> 8) & 255))
2087         operands[2] = operands[1];
2088       else
2089         {
2090           operands[2] = gen_reg_rtx (SImode);
2091           emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2092         }
2093     }
2094   else
2095     {
2096       emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2097       if ((value & 255) == ((value >> 8) & 255))
2098         operands[2] = operands[1];
2099       else
2100         {
2101           operands[2] = gen_reg_rtx (SImode);
2102           emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2103         }
2104     }
2106   operands[3] = plus_constant (operands[0], 1);
2110 (define_expand "movhi"
2111   [(set (match_operand:HI 0 "general_operand" "")
2112         (match_operand:HI 1 "general_operand" ""))]
2113   ""
2114   "
2116   rtx insn;
2118   if (! (reload_in_progress || reload_completed))
2119     {
2120       if (GET_CODE (operands[0]) == MEM)
2121         {
2122           if (GET_CODE (operands[1]) == CONST_INT)
2123             emit_insn (gen_storeinthi (XEXP (operands[0], 0), operands[1]));
2124           else
2125             {
2126               if (GET_CODE (operands[1]) == MEM)
2127                 operands[1] = force_reg (HImode, operands[1]);
2128               if (BYTES_BIG_ENDIAN)
2129                 emit_insn (gen_storehi_bigend (operands[1],
2130                                                XEXP (operands[0], 0)));
2131               else
2132                 emit_insn (gen_storehi (operands[1], XEXP (operands[0], 0)));
2133             }
2134           DONE;
2135         }
2136       /* Sign extend a constant, and keep it in an SImode reg.  */
2137       else if (GET_CODE (operands[1]) == CONST_INT)
2138         {
2139           rtx reg = gen_reg_rtx (SImode);
2140           HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2142           /* If the constant is already valid, leave it alone.  */
2143           if (! const_ok_for_arm (val))
2144             {
2145               /* If setting all the top bits will make the constant 
2146                  loadable in a single instruction, then set them.  
2147                  Otherwise, sign extend the number.  */
2149               if (const_ok_for_arm (~ (val | ~0xffff)))
2150                 val |= ~0xffff;
2151               else if (val & 0x8000)
2152                 val |= ~0xffff;
2153             }
2155           emit_insn (gen_movsi (reg, GEN_INT (val)));
2156           operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
2157         }
2158       else if (BYTES_BIG_ENDIAN && GET_CODE (operands[1]) == MEM)
2159         {
2160           emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2161           DONE;
2162         }
2163     }
2167 (define_expand "movhi_bigend"
2168   [(set (match_dup 2)
2169         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
2170                    (const_int 16)))
2171    (set (match_dup 3)
2172         (ashiftrt:SI (match_dup 2) (const_int 16)))
2173    (set (match_operand:HI 0 "s_register_operand" "")
2174         (subreg:HI (match_dup 3) 0))]
2175   ""
2176   "
2177   operands[2] = gen_reg_rtx (SImode);
2178   operands[3] = gen_reg_rtx (SImode);
2181 ;; Pattern to recognise insn generated default case above
2183 (define_insn ""
2184   [(set (match_operand:HI 0 "general_operand" "=r,r,r")
2185         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2186   "(! BYTES_BIG_ENDIAN)
2187    && (GET_CODE (operands[1]) != CONST_INT
2188        || const_ok_for_arm (INTVAL (operands[1]))
2189        || const_ok_for_arm (~INTVAL (operands[1])))"
2190   "@
2191    mov%?\\t%0, %1\\t%@ movhi
2192    mvn%?\\t%0, #%B1\\t%@ movhi
2193    ldr%?\\t%0, %1\\t%@ movhi"
2194 [(set_attr "type" "*,*,load")])
2196 (define_insn ""
2197   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
2198         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2199   "BYTES_BIG_ENDIAN
2200    && (GET_CODE (operands[1]) != CONST_INT
2201        || const_ok_for_arm (INTVAL (operands[1]))
2202        || const_ok_for_arm (~INTVAL (operands[1])))"
2203   "@
2204    mov%?\\t%0, %1\\t%@ movhi
2205    mvn%?\\t%0, #%B1\\t%@ movhi
2206    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
2207 [(set_attr "type" "*,*,load")
2208  (set_attr "length" "4,4,8")])
2210 (define_insn ""
2211   [(set (match_operand:SI 0 "s_register_operand" "=r")
2212         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
2213                    (const_int 16)))]
2214   "BYTES_BIG_ENDIAN"
2215   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
2216 [(set_attr "type" "load")])
2218 (define_expand "reload_outhi"
2219   [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
2220               (match_operand:HI 1 "s_register_operand" "r")
2221               (match_operand:SI 2 "s_register_operand" "=&r")])]
2222   ""
2223   "
2224   arm_reload_out_hi (operands);
2225   DONE;
2228 (define_expand "movqi"
2229   [(set (match_operand:QI 0 "general_operand" "")
2230         (match_operand:QI 1 "general_operand" ""))]
2231   ""
2232   "
2233   /* Everything except mem = const or mem = mem can be done easily */
2235   if (!(reload_in_progress || reload_completed))
2236     {
2237       if (GET_CODE (operands[1]) == CONST_INT)
2238         {
2239           rtx reg = gen_reg_rtx (SImode);
2241           emit_insn (gen_movsi (reg, operands[1]));
2242           operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
2243         }
2244       if (GET_CODE (operands[0]) == MEM)
2245         operands[1] = force_reg (QImode, operands[1]);
2246     }
2250 (define_insn ""
2251   [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
2252         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
2253   "register_operand (operands[0], QImode)
2254    || register_operand (operands[1], QImode)"
2255   "@
2256    mov%?\\t%0, %1
2257    mvn%?\\t%0, #%B1
2258    ldr%?b\\t%0, %1
2259    str%?b\\t%1, %0"
2260 [(set_attr "type" "*,*,load,store1")])
2262 (define_expand "movsf"
2263   [(set (match_operand:SF 0 "general_operand" "")
2264         (match_operand:SF 1 "general_operand" ""))]
2265   ""
2266   "
2267   if (GET_CODE (operands[1]) == CONST_DOUBLE
2268       && ((GET_CODE (operands[0]) == REG
2269            && REGNO (operands[0]) < 16)
2270           || ! (const_double_rtx_ok_for_fpu (operands[1])
2271                 || neg_const_double_rtx_ok_for_fpu (operands[1]))))
2272     {
2273       extern int optimize;
2274       rtx mem = force_const_mem (SFmode, operands[1]);
2275       rtx addr = gen_reg_rtx (SImode);
2276       if (optimize == 0)
2277         {
2278           rtx ptr = force_const_mem (SImode, XEXP (mem, 0));
2279           emit_insn (gen_movsi (addr, ptr));
2280         }
2281       else
2282         emit_insn (gen_movsi (addr, XEXP (mem, 0)));
2283       operands[1] = gen_rtx (MEM, SFmode, addr);
2284     }
2285   if (GET_CODE (operands[0]) == MEM)
2286     operands[1] = force_reg (SFmode, operands[1]);
2289 (define_insn ""
2290   [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
2291         (match_operand:SF 1 "general_operand" "fG,H,m,f,r,f,r,m,r"))]
2292   "GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode)"
2293   "@
2294    mvf%?s\\t%0, %1
2295    mnf%?s\\t%0, #%N1
2296    ldf%?s\\t%0, %1
2297    stf%?s\\t%1, %0
2298    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
2299    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
2300    mov%?\\t%0, %1
2301    ldr%?\\t%0, %1\\t%@ float
2302    str%?\\t%1, %0\\t%@ float"
2303 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
2304  (set_attr "type" "float,float,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
2306 (define_expand "movdf"
2307   [(set (match_operand:DF 0 "general_operand" "")
2308         (match_operand:DF 1 "general_operand" ""))]
2309   ""
2310   "
2311   if (GET_CODE (operands[1]) == CONST_DOUBLE
2312       && ((GET_CODE (operands[0]) == REG
2313            && REGNO (operands[0]) < 16)
2314           || ! (const_double_rtx_ok_for_fpu (operands[1])
2315                 || neg_const_double_rtx_ok_for_fpu (operands[1]))))
2316     {
2317       extern int optimize;
2318       rtx mem = force_const_mem (DFmode, operands[1]);
2319       rtx addr = gen_reg_rtx (SImode);
2320       if (optimize == 0)
2321         {
2322           rtx ptr = force_const_mem (SImode, XEXP (mem, 0));
2323           emit_insn (gen_movsi (addr, ptr));
2324         }
2325       else
2326         emit_insn (gen_movsi (addr, XEXP (mem, 0)));
2327       operands[1] = gen_rtx (MEM, DFmode, addr);
2328     }
2329   if (GET_CODE (operands[0]) == MEM)
2330     operands[1] = force_reg (DFmode, operands[1]);
2333 ;; Reloading a df mode value stored in integer regs to memory can require a
2334 ;; scratch reg.
2335 (define_expand "reload_outdf"
2336   [(match_operand:DF 0 "reload_memory_operand" "=o")
2337    (match_operand:DF 1 "s_register_operand" "r")
2338    (match_operand:SI 2 "s_register_operand" "=&r")]
2339   ""
2340   "
2341   emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
2342                          XEXP (XEXP (operands[0], 0), 1)));
2343   emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DFmode, operands[2]),
2344                       operands[1]));
2345   DONE;
2348 (define_insn ""
2349   [(set (match_operand:DF 0 "general_operand" "=r,Q#m,r,f,f,f,f,m,!f,!r,r")
2350         (match_operand:DF 1 "general_operand" 
2351                 "Q,r,?o,?f,!G,!H,m,f,r,f,??r"))]
2352   "GET_CODE (operands[0]) != MEM || register_operand (operands[1], DFmode)"
2353   "*
2355   rtx ops[3];
2357   switch (which_alternative)
2358     {
2359     case 0:
2360       return \"ldm%?ia\\t%m1, {%0, %R0}\\t%@ double\";
2362     case 1:
2363       return \"stm%?ia\\t%m0, {%1, %R1}\\t%@ double\";
2365     case 2:
2366       ops[0] = operands[0];
2367       ops[1] = XEXP (XEXP (operands[1], 0), 0);
2368       ops[2] = XEXP (XEXP (operands[1], 0), 1);
2369       if (!INTVAL (ops[2]) || const_ok_for_arm (INTVAL (ops[2])))
2370         output_asm_insn (\"add%?\\t%0, %1, %2\", ops);
2371       else
2372         output_asm_insn (\"sub%?\\t%0, %1, #%n2\", ops);
2373       return \"ldm%?ia\\t%0, {%0, %R0}\\t%@ double\";
2375     case 3:
2376     case 4:
2377       return \"mvf%?d\\t%0, %1\";
2379     case 5: return \"mnf%?d\\t%0, #%N1\";
2380     case 6: return \"ldf%?d\\t%0, %1\";
2381     case 7: return \"stf%?d\\t%1, %0\";
2382     case 8: return output_mov_double_fpu_from_arm (operands);
2383     case 9: return output_mov_double_arm_from_fpu (operands);
2384     case 10: return output_move_double (operands);
2385     }
2388 [(set_attr "length" "4,4,8,4,4,4,4,4,8,8,8")
2389  (set_attr "type" 
2390 "load,store2,load,float,float,float,f_load,f_store,r_mem_f,f_mem_r,*")])
2392 (define_expand "movxf"
2393   [(set (match_operand:XF 0 "general_operand" "")
2394         (match_operand:XF 1 "general_operand" ""))]
2395   "ENABLE_XF_PATTERNS"
2396   "")
2398 ;; Even when the XFmode patterns aren't enabled, we enable this after
2399 ;; reloading so that we can push floating point registers in the prologue.
2401 (define_insn ""
2402   [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
2403         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
2404   "ENABLE_XF_PATTERNS || reload_completed"
2405   "*
2406   switch (which_alternative)
2407     {
2408     case 0: return \"mvf%?e\\t%0, %1\";
2409     case 1: return \"mnf%?e\\t%0, #%N1\";
2410     case 2: return \"ldf%?e\\t%0, %1\";
2411     case 3: return \"stf%?e\\t%1, %0\";
2412     case 4: return output_mov_long_double_fpu_from_arm (operands);
2413     case 5: return output_mov_long_double_arm_from_fpu (operands);
2414     case 6: return output_mov_long_double_arm_from_arm (operands);
2415     }
2417 [(set_attr "length" "4,4,4,4,8,8,12")
2418  (set_attr "type" "float,float,f_load,f_store,r_mem_f,f_mem_r,*")])
2421 ;; load- and store-multiple insns
2422 ;; The arm can load/store any set of registers, provided that they are in
2423 ;; ascending order; but that is beyond GCC so stick with what it knows.
2425 (define_expand "load_multiple"
2426   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2427                           (match_operand:SI 1 "" ""))
2428                      (use (match_operand:SI 2 "" ""))])]
2429   ""
2430   "
2431   /* Support only fixed point registers */
2432   if (GET_CODE (operands[2]) != CONST_INT
2433       || INTVAL (operands[2]) > 14
2434       || INTVAL (operands[2]) < 2
2435       || GET_CODE (operands[1]) != MEM
2436       || GET_CODE (operands[0]) != REG
2437       || REGNO (operands[0]) > 14
2438       || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
2439     FAIL;
2441   operands[3]
2442             = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
2443                                      force_reg (SImode, XEXP (operands[1], 0)),
2444                                      TRUE, FALSE);
2447 ;; Load multiple with write-back
2449 (define_insn ""
2450   [(match_parallel 0 "load_multiple_operation"
2451                    [(set (match_operand:SI 1 "s_register_operand" "+r")
2452                          (plus:SI (match_dup 1)
2453                                   (match_operand:SI 2 "immediate_operand" "n")))
2454                     (set (match_operand:SI 3 "s_register_operand" "=r")
2455                          (mem:SI (match_dup 1)))])]
2456   "(INTVAL (operands[2])  == 4 * (XVECLEN (operands[0], 0) - 2))"
2457   "*
2459   rtx ops[3];
2460   int count = XVECLEN (operands[0], 0);
2462   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2463   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
2464   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
2466   output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
2467   return \"\";
2470 [(set_attr "type" "load")])
2472 ;; Ordinary load multiple
2474 (define_insn ""
2475   [(match_parallel 0 "load_multiple_operation"
2476                    [(set (match_operand:SI 1 "s_register_operand" "=r")
2477                          (match_operand:SI 2 "indirect_operand" "Q"))])]
2478   ""
2479   "*
2481   rtx ops[3];
2482   int count = XVECLEN (operands[0], 0);
2484   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2485   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
2486   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
2488   output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
2489   return \"\";
2492 [(set_attr "type" "load")])
2494 (define_expand "store_multiple"
2495   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2496                           (match_operand:SI 1 "" ""))
2497                      (use (match_operand:SI 2 "" ""))])]
2498   ""
2499   "
2500   /* Support only fixed point registers */
2501   if (GET_CODE (operands[2]) != CONST_INT
2502       || INTVAL (operands[2]) > 14
2503       || INTVAL (operands[2]) < 2
2504       || GET_CODE (operands[1]) != REG
2505       || GET_CODE (operands[0]) != MEM
2506       || REGNO (operands[1]) > 14
2507       || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
2508     FAIL;
2510   operands[3]
2511            = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
2512                                      force_reg (SImode, XEXP (operands[0], 0)),
2513                                      TRUE, FALSE);
2516 ;; Store multiple with write-back
2518 (define_insn ""
2519   [(match_parallel 0 "store_multiple_operation"
2520                    [(set (match_operand:SI 1 "s_register_operand" "+r")
2521                          (plus:SI (match_dup 1)
2522                                   (match_operand:SI 2 "immediate_operand" "n")))
2523                     (set (mem:SI (match_dup 1))
2524                          (match_operand:SI 3 "s_register_operand" "r"))])]
2525   "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
2526   "*
2528   rtx ops[3];
2529   int count = XVECLEN (operands[0], 0);
2531   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2532   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
2533   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
2535   output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
2536   return \"\";
2539 [(set (attr "type")
2540       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2541                 (const_string "store2")
2542              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
2543                 (const_string "store3")]
2544           (const_string "store4")))])
2546 ;; Ordinary store multiple
2548 (define_insn ""
2549   [(match_parallel 0 "store_multiple_operation"
2550                    [(set (match_operand:SI 2 "indirect_operand" "=Q")
2551                          (match_operand:SI 1 "s_register_operand" "r"))])]
2552   ""
2553   "*
2555   rtx ops[3];
2556   int count = XVECLEN (operands[0], 0);
2558   ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
2559   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
2560   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
2562   output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
2563   return \"\";
2566 [(set (attr "type")
2567       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
2568                 (const_string "store2")
2569              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2570                 (const_string "store3")]
2571           (const_string "store4")))])
2573 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
2574 ;; We could let this apply for blocks of less than this, but it clobbers so
2575 ;; many registers that there is then probably a better way.
2577 ;; If optimizing, output redundant moves with REG_NOTES on them, this 
2578 ;; produces better code.
2580 (define_expand "movstrsi"
2581   [(set (match_operand:BLK 0 "general_operand" "=m")
2582         (match_operand:BLK 1 "general_operand" "m"))
2583    (use (match_operand:SI 2 "immediate_operand" "n"))
2584    (use (match_operand:SI 3 "immediate_operand" "n"))
2585    (clobber (reg:SI 0))
2586    (clobber (reg:SI 1))
2587    (clobber (reg:SI 2))
2588    (clobber (reg:SI 3))
2589    (clobber (match_scratch:SI 4 "=+r"))
2590    (clobber (match_scratch:SI 5 "=+r"))]
2591   ""
2592   "
2594   int words_to_go;
2595   int i, r;
2596   rtx const_sxteen = gen_rtx (CONST_INT, SImode, 16);
2597   rtx src = gen_reg_rtx (SImode);
2598   rtx dst = gen_reg_rtx (SImode);
2599   rtx st_src, st_dst, end_src, end_dst, fin_src, fin_dst;
2600   extern int optimize;
2602   if (GET_CODE (operands[2]) != CONST_INT
2603       || GET_CODE (operands[3]) != CONST_INT
2604       || INTVAL (operands[2]) % 4 != 0
2605       || INTVAL (operands[2]) < 4
2606       || INTVAL (operands[2]) > 64
2607       || INTVAL (operands[3]) < 4
2608       || INTVAL (operands[3]) % 4 != 0)
2609     FAIL;
2610   emit_move_insn (dst, st_dst = force_reg (SImode, XEXP (operands[0], 0)));
2611   emit_move_insn (src, st_src = force_reg (SImode, XEXP (operands[1], 0)));
2612   fin_src = src;
2613   fin_dst = dst;
2615   for (i = 0, words_to_go = INTVAL (operands[2]) / 4; words_to_go >= 2; i+=4)
2616     {
2617       emit_insn (arm_gen_load_multiple (0, words_to_go > 4 ? 4 : words_to_go,
2618                                         src, TRUE, TRUE));
2619       emit_insn (arm_gen_store_multiple (0, words_to_go > 4 ? 4 : words_to_go,
2620                                         dst, TRUE, TRUE));
2621       if (optimize)
2622         for (r = (words_to_go > 4) ? 3 : words_to_go - 1; r >= 0; r--)
2623           {
2624             rtx note;
2625             note = emit_move_insn (gen_reg_rtx (SImode),
2626                                    gen_rtx (REG, SImode, r));
2627             REG_NOTES (note) = gen_rtx (EXPR_LIST, REG_EQUIV,
2628                                         gen_rtx (MEM, SImode,
2629                                               plus_constant (st_src, 4*(i+r))),
2630                                         REG_NOTES (note));
2631             REG_NOTES (note) = gen_rtx (EXPR_LIST, REG_EQUIV,
2632                                         gen_rtx (MEM, SImode,
2633                                               plus_constant (st_dst, 4*(i+r))),
2634                                         REG_NOTES (note));
2635           }
2636       words_to_go -= words_to_go < 4 ? words_to_go : 4;
2637     }
2638   if (words_to_go)
2639   {
2640     rtx sreg;
2642     emit_move_insn (sreg = gen_reg_rtx (SImode), gen_rtx (MEM, SImode, src));
2643     emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));
2644     emit_move_insn (gen_rtx (MEM, SImode, dst), sreg);
2645     emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));
2646   }
2647   if (optimize)
2648     {
2649       /* Insns for the REG_NOTES: These notes tell the optimiser where the
2650          index registers have got to so that consecutive block moves of
2651          contiguous data work efficiently */
2653       end_src = emit_move_insn (fin_src, fin_src);
2654       REG_NOTES (end_src) = gen_rtx(EXPR_LIST, REG_EQUAL,
2655                                   plus_constant (st_src, INTVAL (operands[2])),
2656                                   REG_NOTES (end_src));
2657       end_dst = emit_move_insn (fin_dst, fin_dst);
2658       REG_NOTES (end_dst) = gen_rtx(EXPR_LIST, REG_EQUAL,
2659                                   plus_constant (st_dst, INTVAL (operands[2])),
2660                                   REG_NOTES (end_dst));
2661     }
2662   DONE;
2667 ;; Comparison and test insns
2669 (define_expand "cmpsi"
2670   [(set (reg:CC 24)
2671         (compare:CC (match_operand:SI 0 "s_register_operand" "")
2672                     (match_operand:SI 1 "arm_add_operand" "")))]
2673   ""
2674   "
2676   arm_compare_op0 = operands[0];
2677   arm_compare_op1 = operands[1];
2678   arm_compare_fp = 0;
2679   DONE;
2683 (define_expand "cmpsf"
2684   [(set (reg:CC 24)
2685         (compare:CC (match_operand:SF 0 "s_register_operand" "")
2686                     (match_operand:SF 1 "fpu_rhs_operand" "")))]
2687   ""
2688   "
2690   arm_compare_op0 = operands[0];
2691   arm_compare_op1 = operands[1];
2692   arm_compare_fp = 1;
2693   DONE;
2697 (define_expand "cmpdf"
2698   [(set (reg:CC 24)
2699         (compare:CC (match_operand:DF 0 "s_register_operand" "")
2700                     (match_operand:DF 1 "fpu_rhs_operand" "")))]
2701   ""
2702   "
2704   arm_compare_op0 = operands[0];
2705   arm_compare_op1 = operands[1];
2706   arm_compare_fp = 1;
2707   DONE;
2711 (define_expand "cmpxf"
2712   [(set (reg:CC 24)
2713         (compare:CC (match_operand:XF 0 "s_register_operand" "")
2714                     (match_operand:XF 1 "fpu_rhs_operand" "")))]
2715   "ENABLE_XF_PATTERNS"
2716   "
2718   arm_compare_op0 = operands[0];
2719   arm_compare_op1 = operands[1];
2720   arm_compare_fp = 1;
2721   DONE;
2725 (define_insn ""
2726   [(set (match_operand 0 "cc_register" "")
2727         (compare (match_operand:SI 1 "s_register_operand" "r,r")
2728                  (match_operand:SI 2 "arm_add_operand" "rI,L")))]
2729   ""
2730   "@
2731    cmp%?\\t%1, %2
2732    cmn%?\\t%1, #%n2"
2733 [(set_attr "conds" "set")])
2735 (define_insn ""
2736   [(set (match_operand 0 "cc_register" "")
2737         (compare (match_operand:SI 1 "s_register_operand" "r")
2738                  (neg:SI (match_operand:SI 2 "s_register_operand" "r"))))]
2739   ""
2740   "cmn%?\\t%1, %2"
2741 [(set_attr "conds" "set")])
2743 (define_insn ""
2744   [(set (match_operand 0 "cc_register" "")
2745         (compare (match_operand:SI 1 "s_register_operand" "r")
2746                  (match_operator:SI 2 "shift_operator"
2747                   [(match_operand:SI 3 "s_register_operand" "r")
2748                    (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
2749   ""
2750   "cmp%?\\t%1, %3%S2"
2751 [(set_attr "conds" "set")])
2753 (define_insn ""
2754   [(set (match_operand 0 "cc_register" "")
2755         (compare (match_operand:SI 1 "s_register_operand" "r")
2756                  (neg:SI (match_operator:SI 2 "shift_operator"
2757                           [(match_operand:SI 3 "s_register_operand" "r")
2758                            (match_operand:SI 4 "arm_rhs_operand" "rM")]))))]
2759   ""
2760   "cmn%?\\t%1, %3%S2"
2761 [(set_attr "conds" "set")])
2763 (define_insn ""
2764   [(set (reg:CCFP 24)
2765         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
2766                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
2767   ""
2768   "@
2769    cmf%?\\t%0, %1
2770    cnf%?\\t%0, #%N1"
2771 [(set_attr "conds" "set")
2772  (set_attr "type" "f_2_r")])
2774 (define_insn ""
2775   [(set (reg:CCFP 24)
2776         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
2777                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
2778   ""
2779   "@
2780    cmf%?\\t%0, %1
2781    cnf%?\\t%0, #%N1"
2782 [(set_attr "conds" "set")
2783  (set_attr "type" "f_2_r")])
2785 (define_insn ""
2786   [(set (reg:CCFP 24)
2787         (compare:CCFP (float_extend:DF
2788                        (match_operand:SF 0 "s_register_operand" "f,f"))
2789                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
2790   ""
2791   "@
2792    cmf%?\\t%0, %1
2793    cnf%?\\t%0, #%N1"
2794 [(set_attr "conds" "set")
2795  (set_attr "type" "f_2_r")])
2797 (define_insn ""
2798   [(set (reg:CCFP 24)
2799         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
2800                       (float_extend:DF
2801                        (match_operand:SF 1 "s_register_operand" "f"))))]
2802   ""
2803   "cmf%?\\t%0, %1"
2804 [(set_attr "conds" "set")
2805  (set_attr "type" "f_2_r")])
2807 (define_insn ""
2808   [(set (reg:CCFP 24)
2809         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
2810                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
2811   "ENABLE_XF_PATTERNS"
2812   "@
2813    cmf%?\\t%0, %1
2814    cnf%?\\t%0, #%N1"
2815 [(set_attr "conds" "set")
2816  (set_attr "type" "f_2_r")])
2818 (define_insn ""
2819   [(set (reg:CCFPE 24)
2820         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
2821                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
2822   ""
2823   "@
2824    cmf%?\\t%0, %1
2825    cnf%?\\t%0, #%N1"
2826 [(set_attr "conds" "set")
2827  (set_attr "type" "f_2_r")])
2829 (define_insn ""
2830   [(set (reg:CCFPE 24)
2831         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
2832                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
2833   ""
2834   "@
2835    cmf%?e\\t%0, %1
2836    cnf%?e\\t%0, #%N1"
2837 [(set_attr "conds" "set")
2838  (set_attr "type" "f_2_r")])
2840 (define_insn ""
2841   [(set (reg:CCFPE 24)
2842         (compare:CCFPE (float_extend:DF
2843                         (match_operand:SF 0 "s_register_operand" "f,f"))
2844                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
2845   ""
2846   "@
2847    cmf%?e\\t%0, %1
2848    cnf%?e\\t%0, #%N1"
2849 [(set_attr "conds" "set")
2850  (set_attr "type" "f_2_r")])
2852 (define_insn ""
2853   [(set (reg:CCFPE 24)
2854         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
2855                        (float_extend:DF
2856                         (match_operand:SF 1 "s_register_operand" "f"))))]
2857   ""
2858   "cmf%?e\\t%0, %1"
2859 [(set_attr "conds" "set")
2860  (set_attr "type" "f_2_r")])
2862 (define_insn ""
2863   [(set (reg:CCFPE 24)
2864         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
2865                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
2866   "ENABLE_XF_PATTERNS"
2867   "@
2868    cmf%?e\\t%0, %1
2869    cnf%?e\\t%0, #%N1"
2870 [(set_attr "conds" "set")
2871  (set_attr "type" "f_2_r")])
2873 ; This insn allows redundant compares to be removed by cse, nothing should
2874 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
2875 ; is deleted later on. The match_dup will match the mode here, so that
2876 ; mode changes of the condition codes aren't lost by this even though we don't
2877 ; specify what they are.
2879 (define_insn ""
2880   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
2881   ""
2882   "\\t%@ deleted compare"
2883 [(set_attr "conds" "set")
2884  (set_attr "length" "0")])
2887 ;; Conditional branch insns
2889 (define_expand "beq"
2890   [(set (pc)
2891         (if_then_else (eq (match_dup 1) (const_int 0))
2892                       (label_ref (match_operand 0 "" ""))
2893                       (pc)))]
2894   ""
2895   "
2897   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
2898                                  arm_compare_fp);
2902 (define_expand "bne"
2903   [(set (pc)
2904         (if_then_else (ne (match_dup 1) (const_int 0))
2905                       (label_ref (match_operand 0 "" ""))
2906                       (pc)))]
2907   ""
2908   "
2910   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
2911                                  arm_compare_fp);
2915 (define_expand "bgt"
2916   [(set (pc)
2917         (if_then_else (gt (match_dup 1) (const_int 0))
2918                       (label_ref (match_operand 0 "" ""))
2919                       (pc)))]
2920   ""
2921   "
2923   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
2924                                  arm_compare_fp);
2928 (define_expand "ble"
2929   [(set (pc)
2930         (if_then_else (le (match_dup 1) (const_int 0))
2931                       (label_ref (match_operand 0 "" ""))
2932                       (pc)))]
2933   ""
2934   "
2936   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
2937                                  arm_compare_fp);
2941 (define_expand "bge"
2942   [(set (pc)
2943         (if_then_else (ge (match_dup 1) (const_int 0))
2944                       (label_ref (match_operand 0 "" ""))
2945                       (pc)))]
2946   ""
2947   "
2949   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
2950                                  arm_compare_fp);
2954 (define_expand "blt"
2955   [(set (pc)
2956         (if_then_else (lt (match_dup 1) (const_int 0))
2957                       (label_ref (match_operand 0 "" ""))
2958                       (pc)))]
2959   ""
2960   "
2962   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
2963                                  arm_compare_fp);
2967 (define_expand "bgtu"
2968   [(set (pc)
2969         (if_then_else (gtu (match_dup 1) (const_int 0))
2970                       (label_ref (match_operand 0 "" ""))
2971                       (pc)))]
2972   ""
2973   "
2975   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
2976                                  arm_compare_fp);
2980 (define_expand "bleu"
2981   [(set (pc)
2982         (if_then_else (leu (match_dup 1) (const_int 0))
2983                       (label_ref (match_operand 0 "" ""))
2984                       (pc)))]
2985   ""
2986   "
2988   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
2989                                  arm_compare_fp);
2993 (define_expand "bgeu"
2994   [(set (pc)
2995         (if_then_else (geu (match_dup 1) (const_int 0))
2996                       (label_ref (match_operand 0 "" ""))
2997                       (pc)))]
2998   ""
2999   "
3001   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3002                                  arm_compare_fp);
3006 (define_expand "bltu"
3007   [(set (pc)
3008         (if_then_else (ltu (match_dup 1) (const_int 0))
3009                       (label_ref (match_operand 0 "" ""))
3010                       (pc)))]
3011   ""
3012   "
3014   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3015                                  arm_compare_fp);
3019 ;; patterns to match conditional branch insns
3021 (define_insn ""
3022   [(set (pc)
3023         (if_then_else (match_operator 1 "comparison_operator"
3024                                         [(reg 24) (const_int 0)])
3025                       (label_ref (match_operand 0 "" ""))
3026                       (pc)))]
3027   ""
3028   "*
3030   extern int arm_ccfsm_state;
3032   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3033   {
3034     arm_ccfsm_state += 2;
3035     return \"\";
3036   }
3037   return \"b%d1\\t%l0\";
3039 [(set_attr "conds" "use")])
3041 (define_insn ""
3042   [(set (pc)
3043         (if_then_else (match_operator 1 "comparison_operator"
3044                                         [(reg 24) (const_int 0)])
3045                       (pc)
3046                       (label_ref (match_operand 0 "" ""))))]
3047   "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
3048   "*
3050   extern int arm_ccfsm_state;
3052   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3053   {
3054     arm_ccfsm_state += 2;
3055     return \"\";
3056   }
3057   return \"b%D1\\t%l0\";
3059 [(set_attr "conds" "use")])
3062 ; scc insns
3064 (define_expand "seq"
3065   [(set (match_operand:SI 0 "s_register_operand" "=r")
3066         (eq:SI (match_dup 1) (const_int 0)))]
3067   ""
3068   "
3070   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3071                                  arm_compare_fp);
3075 (define_expand "sne"
3076   [(set (match_operand:SI 0 "s_register_operand" "=r")
3077         (ne:SI (match_dup 1) (const_int 0)))]
3078   ""
3079   "
3081   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3082                                  arm_compare_fp);
3086 (define_expand "sgt"
3087   [(set (match_operand:SI 0 "s_register_operand" "=r")
3088         (gt:SI (match_dup 1) (const_int 0)))]
3089   ""
3090   "
3092   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3093                                  arm_compare_fp);
3097 (define_expand "sle"
3098   [(set (match_operand:SI 0 "s_register_operand" "=r")
3099         (le:SI (match_dup 1) (const_int 0)))]
3100   ""
3101   "
3103   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3104                                  arm_compare_fp);
3108 (define_expand "sge"
3109   [(set (match_operand:SI 0 "s_register_operand" "=r")
3110         (ge:SI (match_dup 1) (const_int 0)))]
3111   ""
3112   "
3114   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3115                                  arm_compare_fp);
3119 (define_expand "slt"
3120   [(set (match_operand:SI 0 "s_register_operand" "=r")
3121         (lt:SI (match_dup 1) (const_int 0)))]
3122   ""
3123   "
3125   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3126                                  arm_compare_fp);
3130 (define_expand "sgtu"
3131   [(set (match_operand:SI 0 "s_register_operand" "=r")
3132         (gtu:SI (match_dup 1) (const_int 0)))]
3133   ""
3134   "
3136   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3137                                  arm_compare_fp);
3141 (define_expand "sleu"
3142   [(set (match_operand:SI 0 "s_register_operand" "=r")
3143         (leu:SI (match_dup 1) (const_int 0)))]
3144   ""
3145   "
3147   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3148                                  arm_compare_fp);
3152 (define_expand "sgeu"
3153   [(set (match_operand:SI 0 "s_register_operand" "=r")
3154         (geu:SI (match_dup 1) (const_int 0)))]
3155   ""
3156   "
3158   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3159                                  arm_compare_fp);
3163 (define_expand "sltu"
3164   [(set (match_operand:SI 0 "s_register_operand" "=r")
3165         (ltu:SI (match_dup 1) (const_int 0)))]
3166   ""
3167   "
3169   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3170                                  arm_compare_fp);
3174 (define_insn ""
3175   [(set (match_operand:SI 0 "s_register_operand" "=r")
3176         (match_operator:SI 1 "comparison_operator" [(reg 24) (const_int 0)]))]
3177   ""
3178   "mov%d1\\t%0, #1\;mov%D1\\t%0, #0"
3179 [(set_attr "conds" "use")
3180  (set_attr "length" "8")])
3182 (define_insn ""
3183   [(set (match_operand:SI 0 "s_register_operand" "=r")
3184         (neg:SI (match_operator:SI 1 "comparison_operator"
3185                  [(reg 24) (const_int 0)])))]
3186   ""
3187   "mvn%d1\\t%0, #0\;mov%D1\\t%0, #0"
3188 [(set_attr "conds" "use")
3189  (set_attr "length" "8")])
3191 (define_insn ""
3192   [(set (match_operand:SI 0 "s_register_operand" "=r")
3193         (not:SI (match_operator:SI 1 "comparison_operator"
3194                  [(reg 24) (const_int 0)])))]
3195   ""
3196   "mvn%d1\\t%0, #1\;mov%D1\\t%0, #0"
3197 [(set_attr "conds" "use")
3198  (set_attr "length" "8")])
3201 ;; Jump and linkage insns
3203 (define_insn "jump"
3204   [(set (pc)
3205         (label_ref (match_operand 0 "" "")))]
3206   ""
3207   "*
3209   extern int arm_ccfsm_state;
3211   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3212   {
3213     arm_ccfsm_state += 2;
3214     return \"\";
3215   }
3216   return \"b%?\\t%l0\";
3219 (define_expand "call"
3220   [(parallel [(call (match_operand 0 "memory_operand" "")
3221                     (match_operand 1 "general_operand" ""))
3222               (clobber (reg:SI 14))])]
3223   ""
3224   "")
3226 (define_insn ""
3227   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
3228          (match_operand 1 "" "g"))
3229    (clobber (reg:SI 14))]
3230   ""
3231   "*
3232   return output_call (operands);
3234 [(set (attr "conds")
3235       (if_then_else (eq_attr "cpu" "arm6")
3236                     (const_string "clob")
3237                     (const_string "nocond")))
3238 ;; length is worst case, normally it is only two
3239  (set_attr "length" "12")
3240  (set_attr "type" "call")])
3242 (define_insn ""
3243   [(call (mem:SI (match_operand 0 "memory_operand" "m"))
3244          (match_operand 1 "general_operand" "g"))
3245    (clobber (reg:SI 14))]
3246   ""
3247   "*
3248   return output_call_mem (operands);
3250 [(set (attr "conds")
3251       (if_then_else (eq_attr "cpu" "arm6")
3252                     (const_string "clob")
3253                     (const_string "nocond")))
3254  (set_attr "length" "12")
3255  (set_attr "type" "call")])
3257 (define_expand "call_value"
3258   [(parallel [(set (match_operand 0 "" "=rf")
3259                    (call (match_operand 1 "memory_operand" "m")
3260                          (match_operand 2 "general_operand" "g")))
3261               (clobber (reg:SI 14))])]
3262   ""
3263   "")
3265 (define_insn ""
3266   [(set (match_operand 0 "" "=rf")
3267         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
3268               (match_operand 2 "general_operand" "g")))
3269    (clobber (reg:SI 14))]
3270   ""
3271   "*
3272   return output_call (&operands[1]);
3274 [(set (attr "conds")
3275       (if_then_else (eq_attr "cpu" "arm6")
3276                     (const_string "clob")
3277                     (const_string "nocond")))
3278  (set_attr "length" "12")
3279  (set_attr "type" "call")])
3281 (define_insn ""
3282   [(set (match_operand 0 "" "=rf")
3283         (call (mem:SI (match_operand 1 "memory_operand" "m"))
3284         (match_operand 2 "general_operand" "g")))
3285    (clobber (reg:SI 14))]
3286   "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
3287   "*
3288   return output_call_mem (&operands[1]);
3290 [(set (attr "conds")
3291       (if_then_else (eq_attr "cpu" "arm6")
3292                     (const_string "clob")
3293                     (const_string "nocond")))
3294  (set_attr "length" "12")
3295  (set_attr "type" "call")])
3297 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
3298 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
3300 (define_insn ""
3301   [(call (mem:SI (match_operand:SI 0 "" "i"))
3302          (match_operand:SI 1 "general_operand" "g"))
3303    (clobber (reg:SI 14))]
3304   "GET_CODE (operands[0]) == SYMBOL_REF"
3305   "bl%?\\t%a0"
3306 [(set (attr "conds")
3307       (if_then_else (eq_attr "cpu" "arm6")
3308                     (const_string "clob")
3309                     (const_string "nocond")))
3310  (set_attr "type" "call")])
3312 (define_insn ""
3313   [(set (match_operand 0 "s_register_operand" "=rf")
3314         (call (mem:SI (match_operand:SI 1 "" "i"))
3315         (match_operand:SI 2 "general_operand" "g")))
3316    (clobber (reg:SI 14))]
3317   "GET_CODE(operands[1]) == SYMBOL_REF"
3318   "bl%?\\t%a1"
3319 [(set (attr "conds")
3320       (if_then_else (eq_attr "cpu" "arm6")
3321                     (const_string "clob")
3322                     (const_string "nocond")))
3323  (set_attr "type" "call")])
3325 ;; Often the return insn will be the same as loading from memory, so set attr
3326 (define_insn "return"
3327   [(return)]
3328   "USE_RETURN_INSN"
3329   "*
3331   extern int arm_ccfsm_state;
3333   if (arm_ccfsm_state == 2)
3334   {
3335     arm_ccfsm_state += 2;
3336     return \"\";
3337   }
3338   return output_return_instruction (NULL, TRUE);
3340 [(set_attr "type" "load")])
3342 (define_insn ""
3343   [(set (pc)
3344         (if_then_else (match_operator 0 "comparison_operator"
3345                        [(reg 24) (const_int 0)])
3346                       (return)
3347                       (pc)))]
3348   "USE_RETURN_INSN"
3349   "*
3351   extern int arm_ccfsm_state;
3353   if (arm_ccfsm_state == 2)
3354   {
3355     arm_ccfsm_state += 2;
3356     return \"\";
3357   }
3358   return output_return_instruction (operands[0], TRUE);
3360 [(set_attr "conds" "use")
3361  (set_attr "type" "load")])
3363 (define_insn ""
3364   [(set (pc)
3365         (if_then_else (match_operator 0 "comparison_operator"
3366                        [(reg 24) (const_int 0)])
3367                       (pc)
3368                       (return)))]
3369   "USE_RETURN_INSN"
3370   "*
3372   extern int arm_ccfsm_state;
3374   if (arm_ccfsm_state == 2)
3375   {
3376     arm_ccfsm_state += 2;
3377     return \"\";
3378   }
3379   return output_return_instruction 
3380         (gen_rtx (reverse_condition (GET_CODE (operands[0])),
3381                   GET_MODE (operands[0]), XEXP (operands[0], 0),
3382                   XEXP (operands[0], 1)),
3383          TRUE);
3385 [(set_attr "conds" "use")
3386  (set_attr "type" "load")])
3388 ;; Call subroutine returning any type.
3390 (define_expand "untyped_call"
3391   [(parallel [(call (match_operand 0 "" "")
3392                     (const_int 0))
3393               (match_operand 1 "" "")
3394               (match_operand 2 "" "")])]
3395   ""
3396   "
3398   int i;
3400   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
3402   for (i = 0; i < XVECLEN (operands[2], 0); i++)
3403     {
3404       rtx set = XVECEXP (operands[2], 0, i);
3405       emit_move_insn (SET_DEST (set), SET_SRC (set));
3406     }
3408   /* The optimizer does not know that the call sets the function value
3409      registers we stored in the result block.  We avoid problems by
3410      claiming that all hard registers are used and clobbered at this
3411      point.  */
3412   emit_insn (gen_blockage ());
3414   DONE;
3417 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
3418 ;; all of memory.  This blocks insns from being moved across this point.
3420 (define_insn "blockage"
3421   [(unspec_volatile [(const_int 0)] 0)]
3422   ""
3423   ""
3424 [(set_attr "length" "0")
3425  (set_attr "type" "block")])
3427 (define_insn "tablejump"
3428   [(set (pc)
3429         (match_operand:SI 0 "s_register_operand" "r"))
3430    (use (label_ref (match_operand 1 "" "")))]
3431   ""
3432   "mov%?\\t%|pc, %0\\t%@ table jump, label %l1")
3434 (define_insn ""
3435   [(set (pc)
3436         (match_operand:SI 0 "memory_operand" "m"))
3437    (use (label_ref (match_operand 1 "" "")))]
3438   ""
3439   "ldr%?\\t%|pc, %0\\t%@ table jump, label %l1"
3440 [(set_attr "type" "load")])
3442 (define_insn "indirect_jump"
3443   [(set (pc)
3444         (match_operand:SI 0 "s_register_operand" "r"))]
3445   ""
3446   "mov%?\\t%|pc, %0\\t%@ indirect jump")
3448 (define_insn ""
3449   [(set (pc)
3450         (match_operand:SI 0 "memory_operand" "m"))]
3451   ""
3452   "ldr%?\\t%|pc, %0\\t%@ indirect jump"
3453 [(set_attr "type" "load")])
3455 ;; Misc insns
3457 (define_insn "nop"
3458   [(const_int 0)]
3459   ""
3460   "mov%?\\tr0, r0\\t%@ nop")
3462 ;; Patterns to allow combination of arithmetic, cond code and shifts
3464 (define_insn ""
3465   [(set (match_operand:SI 0 "s_register_operand" "=r")
3466         (match_operator:SI 1 "shiftable_operator"
3467           [(match_operator:SI 3 "shift_operator"
3468              [(match_operand:SI 4 "s_register_operand" "r")
3469               (match_operand:SI 5 "reg_or_int_operand" "rI")])
3470            (match_operand:SI 2 "s_register_operand" "r")]))]
3471   ""
3472   "%i1%?\\t%0, %2, %4%S3")
3474 (define_insn ""
3475   [(set (reg:CC_NOOV 24)
3476         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3477                           [(match_operator:SI 3 "shift_operator"
3478                             [(match_operand:SI 4 "s_register_operand" "r")
3479                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
3480                            (match_operand:SI 2 "s_register_operand" "r")])
3481                          (const_int 0)))
3482    (set (match_operand:SI 0 "s_register_operand" "=r")
3483         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
3484                          (match_dup 2)]))]
3485   ""
3486   "%i1%?s\\t%0, %2, %4%S3"
3487 [(set_attr "conds" "set")])
3489 (define_insn ""
3490   [(set (reg:CC_NOOV 24)
3491         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3492                           [(match_operator:SI 3 "shift_operator"
3493                             [(match_operand:SI 4 "s_register_operand" "r")
3494                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
3495                            (match_operand:SI 2 "s_register_operand" "r")])
3496                          (const_int 0)))
3497    (clobber (match_scratch:SI 0 "=r"))]
3498   ""
3499   "%i1%?s\\t%0, %2, %4%S3"
3500 [(set_attr "conds" "set")])
3502 (define_insn ""
3503   [(set (match_operand:SI 0 "s_register_operand" "=r")
3504         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3505                   (match_operator:SI 2 "shift_operator"
3506                    [(match_operand:SI 3 "s_register_operand" "r")
3507                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
3508   ""
3509   "sub%?\\t%0, %1, %3%S2")
3511 (define_insn ""
3512   [(set (reg:CC_NOOV 24)
3513         (compare:CC_NOOV
3514          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3515                    (match_operator:SI 2 "shift_operator"
3516                     [(match_operand:SI 3 "s_register_operand" "r")
3517                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
3518          (const_int 0)))
3519    (set (match_operand:SI 0 "s_register_operand" "=r")
3520         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
3521                                                  (match_dup 4)])))]
3522   ""
3523   "sub%?s\\t%0, %1, %3%S2"
3524 [(set_attr "conds" "set")])
3526 (define_insn ""
3527   [(set (reg:CC_NOOV 24)
3528         (compare:CC_NOOV
3529          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3530                    (match_operator:SI 2 "shift_operator"
3531                     [(match_operand:SI 3 "s_register_operand" "r")
3532                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
3533          (const_int 0)))
3534    (clobber (match_scratch:SI 0 "=r"))]
3535   ""
3536   "sub%?s\\t%0, %1, %3%S2"
3537 [(set_attr "conds" "set")])
3539 ;; These variants of the above insns can occur if the first operand is the
3540 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
3541 ;; seem to be a way around it.  Most of the predicates have to be null
3542 ;; because the format can be generated part way through reload, so
3543 ;; if we don't match it as soon as it becomes available, reload doesn't know
3544 ;; how to reload pseudos that haven't got hard registers; the constraints will
3545 ;; sort everything out.
3547 (define_insn ""
3548   [(set (match_operand:SI 0 "" "=&r")
3549         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
3550                            [(match_operand:SI 3 "" "r")
3551                             (match_operand:SI 4 "" "rM")])
3552                           (match_operand:SI 2 "" "r"))
3553                  (match_operand:SI 1 "const_int_operand" "n")))]
3554   "reload_in_progress"
3555   "*
3556   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
3557   operands[2] = operands[1];
3558   operands[1] = operands[0];
3559   return output_add_immediate (operands);
3561 ; we have no idea how long the add_immediate is, it could be up to 4.
3562 [(set_attr "length" "20")])
3564 (define_insn ""
3565   [(set (reg:CC_NOOV 24)
3566         (compare:CC_NOOV (plus:SI
3567                           (plus:SI 
3568                            (match_operator:SI 5 "shift_operator"
3569                             [(match_operand:SI 3 "" "r")
3570                              (match_operand:SI 4 "" "rM")])
3571                            (match_operand:SI 1 "" "r"))
3572                           (match_operand:SI 2 "const_int_operand" "n"))
3573                          (const_int 0)))
3574    (set (match_operand:SI 0 "" "=&r")
3575         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
3576                           (match_dup 1))
3577                  (match_dup 2)))]
3578   "reload_in_progress"
3579   "*
3580   output_add_immediate (operands);
3581   return \"add%?s\\t%0, %0, %3%S5\";
3583 [(set_attr "conds" "set")
3584  (set_attr "length" "20")])
3586 (define_insn ""
3587   [(set (reg:CC_NOOV 24)
3588         (compare:CC_NOOV (plus:SI
3589                           (plus:SI 
3590                            (match_operator:SI 5 "shift_operator"
3591                             [(match_operand:SI 3 "" "r")
3592                              (match_operand:SI 4 "" "rM")])
3593                            (match_operand:SI 1 "" "r"))
3594                           (match_operand:SI 2 "const_int_operand" "n"))
3595                          (const_int 0)))
3596    (clobber (match_scratch:SI 0 "=&r"))]
3597   "reload_in_progress"
3598   "*
3599   output_add_immediate (operands);
3600   return \"add%?s\\t%0, %0, %3%S5\";
3602 [(set_attr "conds" "set")
3603  (set_attr "length" "20")])
3605 ;; These are similar, but are needed when the mla pattern contains the
3606 ;; eliminated register as operand 3.
3608 (define_insn ""
3609   [(set (match_operand:SI 0 "" "=&r,&r")
3610         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
3611                                    (match_operand:SI 2 "" "r,r"))
3612                           (match_operand:SI 3 "" "r,r"))
3613                  (match_operand:SI 4 "const_int_operand" "n,n")))]
3614   "reload_in_progress"
3615   "*
3616   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
3617   operands[2] = operands[4];
3618   operands[1] = operands[0];
3619   return output_add_immediate (operands);
3621 [(set_attr "length" "20")])
3623 (define_insn ""
3624   [(set (reg:CC_NOOV 24)
3625         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
3626                                             (match_operand:SI 3 "" "r")
3627                                             (match_operand:SI 4 "" "r"))
3628                                            (match_operand:SI 1 "" "r"))
3629                                   (match_operand:SI 2 "const_int_operand" "n"))
3630                          (const_int 0)))
3631    (set (match_operand:SI 0 "" "=&r")
3632         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
3633                  (match_dup 2)))]
3634   "reload_in_progress"
3635   "*
3636   output_add_immediate (operands);
3637   output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
3638   return \"\";
3640 [(set_attr "length" "20")
3641  (set_attr "conds" "set")])
3643 (define_insn ""
3644   [(set (reg:CC_NOOV 24)
3645         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
3646                                             (match_operand:SI 3 "" "r")
3647                                             (match_operand:SI 4 "" "r"))
3648                                            (match_operand:SI 1 "" "r"))
3649                                   (match_operand:SI 2 "const_int_operand" "n"))
3650                          (const_int 0)))
3651    (clobber (match_scratch:SI 0 "=&r"))]
3652   "reload_in_progress"
3653   "*
3654   output_add_immediate (operands);
3655   return \"mla%?s\\t%0, %3, %4, %0\";
3657 [(set_attr "length" "20")
3658  (set_attr "conds" "set")])
3663 (define_insn ""
3664   [(set (match_operand:SI 0 "s_register_operand" "=r")
3665         (and:SI (match_operator 1 "comparison_operator"
3666                  [(reg 24) (const_int 0)])
3667                 (match_operand:SI 2 "s_register_operand" "r")))]
3668   ""
3669   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
3670 [(set_attr "conds" "use")
3671  (set_attr "length" "8")])
3673 (define_insn ""
3674   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3675         (ior:SI (match_operator 2 "comparison_operator"
3676                  [(reg 24) (const_int 0)])
3677                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
3678   ""
3679   "@
3680    orr%d2\\t%0, %1, #1
3681    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
3682 [(set_attr "conds" "use")
3683  (set_attr "length" "4,8")])
3685 (define_insn ""
3686   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3687         (match_operator 1 "comparison_operator"
3688          [(match_operand:SI 2 "s_register_operand" "r,r")
3689           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
3690    (clobber (reg 24))]
3691   ""
3692   "*
3693   if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
3694     return \"mov\\t%0, %2, lsr #31\";
3696   if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
3697     return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
3699   if (GET_CODE (operands[1]) == NE)
3700     {
3701       if (which_alternative == 1)
3702         return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
3703       return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
3704     }
3705   if (which_alternative == 1)
3706     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
3707   else
3708     output_asm_insn (\"cmp\\t%2, %3\", operands);
3709   return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
3711 [(set_attr "conds" "clob")
3712  (set_attr "length" "12")])
3714 (define_insn ""
3715   [(set (match_operand:SI 0 "s_register_operand" "=&r")
3716         (ior:SI (match_operator 1 "comparison_operator"
3717                  [(match_operand:SI 2 "s_register_operand" "r")
3718                   (match_operand:SI 3 "arm_rhs_operand" "rI")])
3719                 (match_operator 4 "comparison_operator"
3720                  [(match_operand:SI 5 "s_register_operand" "r")
3721                   (match_operand:SI 6 "arm_rhs_operand" "rI")])))
3722    (clobber (reg 24))]
3723   ""
3724   "*
3726   int dominant = comparison_dominates_p (GET_CODE (operands[4]),
3727                                          GET_CODE (operands[1]));
3729   output_asm_insn (dominant ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
3730                    operands);
3731   output_asm_insn (\"mov\\t%0, #0\", operands);
3732   if (GET_CODE (operands[1]) == GET_CODE (operands[4])
3733       || comparison_dominates_p (GET_CODE (operands[1]),
3734                                  GET_CODE (operands[4]))
3735       || dominant)
3736     output_asm_insn (dominant ? \"cmp%D4\\t%2, %3\" : \"cmp%D1\\t%5,%6\",
3737                      operands);
3738   else
3739     output_asm_insn (\"mov%d1\\t%0, #1\;cmp\\t%5, %6\", operands);
3740   return dominant ? \"mov%d1\\t%0, #1\" : \"mov%d4\\t%0, #1\";
3743 [(set_attr "conds" "clob")
3744 ; worst case length
3745  (set_attr "length" "20")])
3747 (define_split
3748   [(set (pc)
3749         (if_then_else
3750          (match_operator 5 "equality_operator"
3751           [(ior:SI (match_operator 6 "comparison_operator"
3752                     [(match_operand:SI 0 "s_register_operand" "")
3753                      (match_operand:SI 1 "arm_add_operand" "")])
3754                    (match_operator 7 "comparison_operator"
3755                     [(match_operand:SI 2 "s_register_operand" "")
3756                      (match_operand:SI 3 "arm_add_operand" "")]))
3757           (const_int 0)])
3758          (label_ref (match_operand 4 "" ""))
3759          (pc)))
3760    (clobber (reg 24))]
3761   "(GET_CODE (operands[6]) == GET_CODE (operands[7])
3762     || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[7]))
3763     || comparison_dominates_p (GET_CODE (operands[7]), GET_CODE (operands[6])))"
3764   [(set (reg:CC 24)
3765         (compare:CC (ior:CC (match_op_dup 6
3766                              [(match_dup 0) (match_dup 1)])
3767                             (match_op_dup 7
3768                              [(match_dup 2) (match_dup 3)]))
3769                     (const_int 0)))
3770    (set (pc)
3771         (if_then_else (match_op_dup 5 [(reg:CC 24) (const_int 0)])
3772                       (label_ref (match_dup 4))
3773                       (pc)))]
3774   "
3776   enum rtx_code code = comparison_dominates_p (GET_CODE (operands[6]),
3777                                                GET_CODE (operands[7]))
3778                        ? GET_CODE (operands[7]) : GET_CODE (operands[6]);
3780   if (GET_CODE (operands[5]) == NE)
3781     operands[5] = gen_rtx (code, CCmode,
3782                            XEXP (operands[5], 0), XEXP (operands[5], 1));
3783   else
3784     operands[5] = gen_rtx (reverse_condition (code), CCmode,
3785                            XEXP (operands[5], 0), XEXP (operands[5], 1));
3789 ;; Don't match these patterns if we can use a conditional compare, since they
3790 ;; tell the final prescan branch elimator code that full branch inlining
3791 ;; can't be done.
3793 (define_insn ""
3794   [(set (pc)
3795         (if_then_else
3796          (ne (ior:SI (match_operator 5 "comparison_operator"
3797                       [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
3798                        (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
3799                      (match_operator 6 "comparison_operator"
3800                       [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
3801                        (match_operand:SI 3 "arm_rhs_operand" "rI,rI,L,L")]))
3802              (const_int 0))
3803          (label_ref (match_operand 4 "" ""))
3804          (pc)))
3805    (clobber (reg 24))]
3806   "!(GET_CODE (operands[5]) == GET_CODE (operands[6])
3807      || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[6]))
3808      || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[5])))"
3809   "*
3811   extern int arm_ccfsm_state;
3813   if (which_alternative & 1)
3814     output_asm_insn (\"cmn\\t%0, #%n1\;b%d5\\t%l4\", operands);
3815   else
3816     output_asm_insn (\"cmp\\t%0, %1\;b%d5\\t%l4\", operands);
3818   if (which_alternative >= 2)
3819     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
3820   else
3821     output_asm_insn (\"cmp\\t%2, %3\", operands);
3823   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3824   {
3825     arm_ccfsm_state += 2;
3826     return \"\";
3827   }
3828   return \"b%d6\\t%l4\";
3830 [(set_attr "conds" "jump_clob")
3831  (set_attr "length" "16")])
3833 (define_insn ""
3834   [(set (reg:CC 24)
3835         (compare:CC
3836          (ior:CC (match_operator 4 "comparison_operator"
3837                   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
3838                    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
3839                  (match_operator 5 "comparison_operator"
3840                   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
3841                    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
3842          (const_int 0)))]
3843   "(GET_CODE (operands[4]) == GET_CODE (operands[5])
3844     || comparison_dominates_p (GET_CODE (operands[4]), GET_CODE (operands[5]))
3845     || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))"
3846   "*
3847   if (comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))
3848     {
3849       if (which_alternative >= 2)
3850         output_asm_insn (\"cmn\\t%2, #%n3\", operands);
3851       else
3852         output_asm_insn (\"cmp\\t%2, %3\", operands);
3854       if (which_alternative & 1)
3855         return \"cmn%D5\\t%0, #%n1\";
3856       return \"cmp%D5\\t%0, %1\";
3857     }
3859   if (which_alternative & 1)
3860     output_asm_insn (\"cmn\\t%0, #%n1\", operands);
3861   else
3862     output_asm_insn (\"cmp\\t%0, %1\", operands);
3864   if (which_alternative >= 2)
3865     return \"cmn%D4\\t%2, #%n3\";
3866   return \"cmp%D4\\t%2, %3\";
3868 [(set_attr "conds" "set")
3869  (set_attr "length" "8")])
3871 (define_insn ""
3872   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3873         (if_then_else (match_operator 3 "equality_operator"
3874                        [(match_operator 4 "comparison_operator"
3875                          [(reg 24) (const_int 0)])
3876                         (const_int 0)])
3877                       (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
3878                       (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
3879   ""
3880   "*
3881   if (GET_CODE (operands[3]) == NE)
3882     {
3883       if (which_alternative != 0)
3884         output_asm_insn (\"mov%d4\\t%0, %1\", operands);
3885       if (which_alternative != 1)
3886         output_asm_insn (\"mov%D4\\t%0, %2\", operands);
3887       return \"\";
3888     }
3889   if (which_alternative != 0)
3890     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
3891   if (which_alternative != 1)
3892     output_asm_insn (\"mov%d4\\t%0, %2\", operands);
3893   return \"\";
3895 [(set_attr "conds" "use")
3896  (set_attr "length" "4,4,8")])
3898 (define_insn ""
3899   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3900         (match_operator:SI 5 "shiftable_operator" 
3901          [(match_operator:SI 4 "comparison_operator"
3902            [(match_operand:SI 2 "s_register_operand" "r,r")
3903             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3904           (match_operand:SI 1 "s_register_operand" "0,?r")]))
3905    (clobber (reg 24))]
3906   ""
3907   "*
3908   if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
3909     return \"%i5\\t%0, %1, %2, lsr #31\";
3911   output_asm_insn (\"cmp\\t%2, %3\", operands);
3912   if (GET_CODE (operands[5]) == AND)
3913     output_asm_insn (\"mov%D4\\t%0, #0\", operands);
3914   else if (which_alternative != 0)
3915     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
3916   return \"%i5%d4\\t%0, %1, #1\";
3918 [(set_attr "conds" "clob")
3919  (set_attr "length" "12")])
3921 (define_insn ""
3922   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3923         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
3924                   (match_operator:SI 4 "comparison_operator"
3925                    [(match_operand:SI 2 "s_register_operand" "r,r")
3926                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
3927    (clobber (reg 24))]
3928   ""
3929   "*
3930   output_asm_insn (\"cmp\\t%2, %3\", operands);
3931   if (which_alternative != 0)
3932     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
3933   return \"sub%d4\\t%0, %1, #1\";
3935 [(set_attr "conds" "clob")
3936  (set_attr "length" "8,12")])
3938 (define_insn ""
3939   [(set (match_operand:SI 0 "s_register_operand" "=&r")
3940         (and:SI (match_operator 1 "comparison_operator"
3941                  [(match_operand:SI 2 "s_register_operand" "r")
3942                   (match_operand:SI 3 "arm_rhs_operand" "rI")])
3943                 (match_operator 4 "comparison_operator"
3944                  [(match_operand:SI 5 "s_register_operand" "r")
3945                   (match_operand:SI 6 "arm_rhs_operand" "rI")])))
3946    (clobber (reg 24))]
3947   ""
3948   "*
3950   int dominant =
3951         comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
3952                                 reverse_condition (GET_CODE (operands[4])))
3953         ? 1 
3954         : comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
3955                                   reverse_condition (GET_CODE (operands[1])))
3956         ? 2 : 0;
3957   output_asm_insn (dominant == 2 ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
3958                        operands);
3959   output_asm_insn (\"mov\\t%0, #1\", operands);
3960   if (GET_CODE (operands[1]) == GET_CODE (operands[4]) || dominant)
3961     {
3962       output_asm_insn (dominant == 2 ? \"cmp%d4\\t%2, %3\"
3963                            : \"cmp%d1\\t%5, %6\", operands);
3964     }
3965   else
3966     {
3967       output_asm_insn (\"mov%D1\\t%0, #0\", operands);
3968       output_asm_insn (\"cmp\\t%5, %6\", operands);
3969     }
3970   return dominant == 2 ? \"mov%D1\\t%0, #0\" : \"mov%D4\\t%0, #0\";
3973 [(set_attr "conds" "clob")
3974  (set_attr "length" "20")])
3976 (define_split
3977   [(set (pc)
3978         (if_then_else (match_operator 1 "equality_operator"
3979                        [(and:SI (match_operator 2 "comparison_operator"
3980                                  [(match_operand:SI 3 "s_register_operand" "")
3981                                   (match_operand:SI 4 "arm_add_operand" "")])
3982                                 (match_operator 0 "comparison_operator"
3983                                  [(match_operand:SI 5 "s_register_operand" "")
3984                                   (match_operand:SI 6 "arm_add_operand" "")]))
3985                         (const_int 0)])
3986                       (label_ref (match_operand 7 "" ""))
3987                       (pc)))
3988    (clobber (reg 24))]
3989   "(GET_CODE (operands[2]) == GET_CODE (operands[0])
3990     || comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
3991                                reverse_condition (GET_CODE (operands[0])))
3992     || comparison_dominates_p (reverse_condition (GET_CODE (operands[0])),
3993                                reverse_condition (GET_CODE (operands[2]))))"
3994   [(set (reg:CC 24)
3995         (compare:CC (ior:CC (match_op_dup 2
3996                              [(match_dup 3) (match_dup 4)])
3997                             (match_op_dup 0
3998                              [(match_dup 5) (match_dup 6)]))
3999                     (const_int 0)))
4000    (set (pc)
4001         (if_then_else (match_op_dup 1 [(reg:CC 24) (const_int 0)])
4002                       (label_ref (match_dup 7))
4003                       (pc)))]
4004   "
4006   /* Use DeMorgans law to convert this into an IOR of the inverse conditions 
4007      This is safe since we only do it for integer comparisons. */
4008   enum rtx_code code = 
4009         comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
4010                                 reverse_condition (GET_CODE (operands[0])))
4011         ? GET_CODE (operands[0]) : GET_CODE (operands[2]);
4013   operands[2] = gen_rtx (reverse_condition (GET_CODE (operands[2])),
4014                          GET_MODE (operands[2]), operands[3], operands[4]);
4015   operands[0] = gen_rtx (reverse_condition (GET_CODE (operands[0])),
4016                          GET_MODE (operands[0]), operands[5], operands[6]);
4017   if (GET_CODE (operands[1]) == NE)
4018     operands[1] = gen_rtx (code, CCmode,
4019                            XEXP (operands[1], 0), XEXP (operands[1], 1));
4020   else
4021     operands[1] = gen_rtx (reverse_condition (code), CCmode,
4022                            XEXP (operands[1], 0), XEXP (operands[1], 1));
4026 ;; Don't match these patterns if we can use a conditional compare, since they
4027 ;; tell the final prescan branch elimator code that full branch inlining
4028 ;; can't be done.
4030 (define_insn ""
4031   [(set (pc)
4032         (if_then_else
4033          (eq (and:SI (match_operator 1 "comparison_operator"
4034                       [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4035                        (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L")])
4036                      (match_operator 4 "comparison_operator"
4037                       [(match_operand:SI 5 "s_register_operand" "r,r,r,r")
4038                        (match_operand:SI 6 "arm_rhs_operand" "rI,rI,L,L")]))
4039              (const_int 0))
4040          (label_ref (match_operand 0 "" ""))
4041          (pc)))
4042    (clobber (reg 24))]
4043   "!(GET_CODE (operands[1]) == GET_CODE (operands[4])
4044      || comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
4045                                 reverse_condition (GET_CODE (operands[4])))
4046      || comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
4047                                 reverse_condition (GET_CODE (operands[1]))))"
4048   "*
4050   extern int arm_ccfsm_state;
4052   if (which_alternative & 1)
4053     output_asm_insn (\"cmn\\t%2, #%n3\;b%D1\\t%l0\", operands);
4054   else
4055     output_asm_insn (\"cmp\\t%2, %3\;b%D1\\t%l0\", operands);
4057   if (which_alternative >= 2)
4058     output_asm_insn (\"cmn\\t%5, #%n6\", operands);
4059   else
4060     output_asm_insn (\"cmp\\t%5, %6\", operands);
4062   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4063   {
4064     arm_ccfsm_state += 2;
4065     return \"\";
4066   }
4067   return \"b%D4\\t%l0\";
4069 [(set_attr "conds" "jump_clob")
4070  (set_attr "length" "16")])
4072 (define_insn ""
4073   [(set (match_operand:SI 0 "s_register_operand" "=r")
4074         (neg:SI (match_operator 3 "comparison_operator"
4075                  [(match_operand:SI 1 "s_register_operand" "r")
4076                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4077    (clobber (reg 24))]
4078   ""
4079   "*
4080   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4081     return \"mov\\t%0, %1, asr #31\";
4083   if (GET_CODE (operands[3]) == NE)
4084     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4086   if (GET_CODE (operands[3]) == GT)
4087     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4089   output_asm_insn (\"cmp\\t%1, %2\", operands);
4090   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4091   return \"mvn%d3\\t%0, #0\";
4093 [(set_attr "conds" "clob")
4094  (set_attr "length" "12")])
4096 (define_insn "movcond"
4097   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4098         (if_then_else:SI
4099          (match_operator 5 "comparison_operator"
4100           [(match_operand:SI 3 "s_register_operand" "r,r,r")
4101            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4102          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4103          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4104    (clobber (reg 24))]
4105   ""
4106   "*
4107   if (GET_CODE (operands[5]) == LT
4108       && (operands[4] == const0_rtx))
4109     {
4110       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4111         {
4112           if (operands[2] == const0_rtx)
4113             return \"and\\t%0, %1, %3, asr #31\";
4114           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4115         }
4116       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4117         {
4118           if (operands[1] == const0_rtx)
4119             return \"bic\\t%0, %2, %3, asr #31\";
4120           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4121         }
4122       /* The only case that falls through to here is when both ops 1 & 2
4123          are constants */
4124     }
4126   if (GET_CODE (operands[5]) == GE
4127       && (operands[4] == const0_rtx))
4128     {
4129       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4130         {
4131           if (operands[2] == const0_rtx)
4132             return \"bic\\t%0, %1, %3, asr #31\";
4133           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4134         }
4135       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4136         {
4137           if (operands[1] == const0_rtx)
4138             return \"and\\t%0, %2, %3, asr #31\";
4139           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4140         }
4141       /* The only case that falls through to here is when both ops 1 & 2
4142          are constants */
4143     }
4144   if (GET_CODE (operands[4]) == CONST_INT
4145       && !const_ok_for_arm (INTVAL (operands[4])))
4146     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4147   else
4148     output_asm_insn (\"cmp\\t%3, %4\", operands);
4149   if (which_alternative != 0)
4150     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4151   if (which_alternative != 1)
4152     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4153   return \"\";
4155 [(set_attr "conds" "clob")
4156  (set_attr "length" "8,8,12")])
4158 (define_insn ""
4159   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4160         (if_then_else:SI (match_operator 9 "comparison_operator"
4161                           [(match_operand:SI 5 "s_register_operand" "r,r")
4162                            (match_operand:SI 6 "arm_add_operand" "rI,L")])
4163                          (match_operator:SI 8 "shiftable_operator"
4164                           [(match_operand:SI 1 "s_register_operand" "r,r")
4165                            (match_operand:SI 2 "arm_rhs_operand" "rI,rI")])
4166                          (match_operator:SI 7 "shiftable_operator"
4167                           [(match_operand:SI 3 "s_register_operand" "r,r")
4168                            (match_operand:SI 4 "arm_rhs_operand" "rI,rI")])))
4169    (clobber (reg 24))]
4170   ""
4171   "@
4172    cmp\\t%5, %6\;%I8%d9\\t%0, %1, %2\;%I7%D9\\t%0, %3, %4
4173    cmn\\t%5, #%n6\;%I8%d9\\t%0, %1, %2\;%I7%D9\\t%0, %3, %4"
4174 [(set_attr "conds" "clob")
4175  (set_attr "length" "12")])
4177 (define_insn ""
4178   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4179         (if_then_else:SI (match_operator 6 "comparison_operator"
4180                           [(match_operand:SI 2 "s_register_operand" "r,r")
4181                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
4182                          (match_operator:SI 7 "shiftable_operator"
4183                           [(match_operand:SI 4 "s_register_operand" "r,r")
4184                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
4185                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4186    (clobber (reg 24))]
4187   ""
4188   "*
4189   /* If we have an operation where (op x 0) is the identity operation and
4190      the condtional operator is LT or GE and we are comparing against zero and
4191      everything is in registers then we can do this in two instructions */
4192   if (operands[3] == const0_rtx
4193       && GET_CODE (operands[7]) != AND
4194       && GET_CODE (operands[5]) == REG
4195       && GET_CODE (operands[1]) == REG 
4196       && REGNO (operands[1]) == REGNO (operands[4])
4197       && REGNO (operands[4]) != REGNO (operands[0]))
4198     {
4199       if (GET_CODE (operands[6]) == LT)
4200         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4201       else if (GET_CODE (operands[6]) == GE)
4202         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4203     }
4204   if (GET_CODE (operands[3]) == CONST_INT
4205       && !const_ok_for_arm (INTVAL (operands[3])))
4206     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4207   else
4208     output_asm_insn (\"cmp\\t%2, %3\", operands);
4209   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
4210   if (which_alternative != 0)
4211     {
4212       if (GET_CODE (operands[1]) == MEM)
4213         return \"ldr%D6\\t%0, %1\";
4214       else
4215         return \"mov%D6\\t%0, %1\";
4216     }
4217   return \"\";
4219 [(set_attr "conds" "clob")
4220  (set_attr "length" "8,12")])
4222 (define_insn ""
4223   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4224         (if_then_else:SI (match_operator 6 "comparison_operator"
4225                           [(match_operand:SI 4 "s_register_operand" "r,r")
4226                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4227                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4228                          (match_operator:SI 7 "shiftable_operator"
4229                           [(match_operand:SI 2 "s_register_operand" "r,r")
4230                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4231    (clobber (reg 24))]
4232   ""
4233   "*
4234   /* If we have an operation where (op x 0) is the identity operation and
4235      the condtional operator is LT or GE and we are comparing against zero and
4236      everything is in registers then we can do this in two instructions */
4237   if (operands[5] == const0_rtx
4238       && GET_CODE (operands[7]) != AND
4239       && GET_CODE (operands[3]) == REG
4240       && GET_CODE (operands[1]) == REG 
4241       && REGNO (operands[1]) == REGNO (operands[2])
4242       && REGNO (operands[2]) != REGNO (operands[0]))
4243     {
4244       if (GET_CODE (operands[6]) == GE)
4245         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4246       else if (GET_CODE (operands[6]) == LT)
4247         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4248     }
4250   if (GET_CODE (operands[5]) == CONST_INT
4251       && !const_ok_for_arm (INTVAL (operands[5])))
4252     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4253   else
4254     output_asm_insn (\"cmp\\t%4, %5\", operands);
4256   if (which_alternative != 0)
4257     {
4258       if (GET_CODE (operands[1]) == MEM)
4259         output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4260       else
4261         output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4262     }
4263   return \"%I7%D6\\t%0, %2, %3\";
4265 [(set_attr "conds" "clob")
4266  (set_attr "length" "8,12")])
4268 (define_insn ""
4269   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4270         (if_then_else:SI (match_operator 6 "comparison_operator"
4271                           [(match_operand:SI 4 "s_register_operand" "r,r")
4272                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4273                          (plus:SI
4274                           (match_operand:SI 2 "s_register_operand" "r,r")
4275                           (match_operand:SI 3 "arm_add_operand" "rL,rL"))
4276                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4277    (clobber (reg 24))]
4278   ""
4279   "*
4281   if (GET_CODE (operands[5]) == CONST_INT
4282       && !const_ok_for_arm (INTVAL (operands[5])))
4283     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4284   else
4285     output_asm_insn (\"cmp\\t%4, %5\", operands);
4286   if (GET_CODE (operands[3]) == CONST_INT
4287       && !const_ok_for_arm (INTVAL (operands[3])))
4288     output_asm_insn (\"sub%d6\\t%0, %2, #%n3\", operands);
4289   else
4290     output_asm_insn (\"add%d6\\t%0, %2, %3\", operands);
4291   if (which_alternative != 0)
4292     {
4293       if (GET_CODE (operands[1]) == MEM)
4294         output_asm_insn (\"ldr%D6\\t%0, %1\", operands);
4295       else
4296         output_asm_insn (\"mov%D6\\t%0, %1\", operands);
4297     }
4298   return \"\";
4301 [(set_attr "conds" "clob")
4302  (set_attr "length" "8,12")])
4304 (define_insn ""
4305   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4306         (if_then_else:SI (match_operator 6 "comparison_operator"
4307                           [(match_operand:SI 4 "s_register_operand" "r,r")
4308                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4309                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4310                          (plus:SI
4311                           (match_operand:SI 2 "s_register_operand" "r,r")
4312                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4313    (clobber (reg 24))]
4314   ""
4315   "*
4317   if (GET_CODE (operands[5]) == CONST_INT
4318       && !const_ok_for_arm (INTVAL (operands[5])))
4319     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4320   else
4321     output_asm_insn (\"cmp\\t%4, %5\", operands);
4322   if (GET_CODE (operands[3]) == CONST_INT
4323       && !const_ok_for_arm (INTVAL (operands[3])))
4324     output_asm_insn (\"sub%D6\\t%0, %2, #%n3\", operands);
4325   else
4326     output_asm_insn (\"add%D6\\t%0, %2, %3\", operands);
4327   if (which_alternative != 0)
4328     {
4329       if (GET_CODE (operands[6]) == MEM)
4330         output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4331       else
4332         output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4333     }
4334   return \"\";
4337 [(set_attr "conds" "clob")
4338  (set_attr "length" "8,12")])
4340 (define_insn ""
4341   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4342         (if_then_else:SI (match_operator 5 "comparison_operator"
4343                           [(match_operand:SI 3 "s_register_operand" "r,r")
4344                            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
4345                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4346                          (not:SI
4347                           (match_operand:SI 2 "s_register_operand" "r,r"))))
4348    (clobber (reg 24))]
4349   ""
4350   "#"
4351 [(set_attr "conds" "clob")
4352  (set_attr "length" "8,12")])
4354 (define_insn ""
4355   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4356         (if_then_else:SI 
4357          (match_operator 5 "comparison_operator"
4358           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4359            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4360          (not:SI
4361           (match_operand:SI 2 "s_register_operand" "r,r,r,r"))
4362          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4363    (clobber (reg 24))]
4364   ""
4365   "@
4366    cmp\\t%3, %4\;mvn%d5\\t%0, %2
4367    cmn\\t%3, #%n4\;mvn%d5\\t%0, %2
4368    cmp\\t%3, %4\;mov%D5\\t%0, %1\;mvn%d5\\t%0, %2
4369    cmn\\t%3, #%n4\;mov%D5\\t%0, %1\;mvn%d5\\t%0, %2"
4370 [(set_attr "conds" "clob")
4371  (set_attr "length" "8,8,12,12")])
4373 (define_insn ""
4374   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4375         (if_then_else:SI
4376          (match_operator 6 "comparison_operator"
4377           [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
4378            (match_operand:SI 5 "arm_add_operand" "rI,L,rI,L")])
4379          (match_operator:SI 7 "shift_operator"
4380           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4381            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM,rM")])
4382          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4383    (clobber (reg 24))]
4384   ""
4385   "@
4386    cmp\\t%4, %5\;mov%d6\\t%0, %2%S7
4387    cmn\\t%4, #%n5\;mov%d6\\t%0, %2%S7
4388    cmp\\t%4, %5\;mov%D6\\t%0, %1\;mov%d6\\t%0, %2%S7
4389    cmn\\t%4, #%n5\;mov%D6\\t%0, %1\;mov%d6\\t%0, %2%S7"
4390 [(set_attr "conds" "clob")
4391  (set_attr "length" "8,8,12,12")])
4393 (define_insn ""
4394   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4395         (if_then_else:SI
4396          (match_operator 6 "comparison_operator"
4397           [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
4398            (match_operand:SI 5 "arm_add_operand" "rI,L,rI,L")])
4399          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4400          (match_operator:SI 7 "shift_operator"
4401           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4402            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM,rM")])))
4403    (clobber (reg 24))]
4404   ""
4405   "@
4406    cmp\\t%4, %5\;mov%D6\\t%0, %2%S7
4407    cmn\\t%4, #%n5\;mov%D6\\t%0, %2%S7
4408    cmp\\t%4, %5\;mov%d6\\t%0, %1\;mov%D6\\t%0, %2%S7
4409    cmn\\t%4, #%n5\;mov%d6\\t%0, %1\;mov%D6\\t%0, %2%S7"
4410 [(set_attr "conds" "clob")
4411  (set_attr "length" "8,8,12,12")])
4413 (define_insn ""
4414   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4415         (if_then_else:SI
4416          (match_operator 7 "comparison_operator"
4417           [(match_operand:SI 5 "s_register_operand" "r,r")
4418            (match_operand:SI 6 "arm_add_operand" "rI,L")])
4419          (match_operator:SI 8 "shift_operator"
4420           [(match_operand:SI 1 "s_register_operand" "r,r")
4421            (match_operand:SI 2 "arm_rhs_operand" "rM,rM")])
4422          (match_operator:SI 9 "shift_operator"
4423           [(match_operand:SI 3 "s_register_operand" "r,r")
4424            (match_operand:SI 4 "arm_rhs_operand" "rI,rI")])))
4425    (clobber (reg 24))]
4426   ""
4427   "@
4428    cmp\\t%5, %6\;mov%d7\\t%0, %1%S8\;mov%D7\\t%0, %3%S9
4429    cmn\\t%5, #%n6\;mov%d7\\t%0, %1%S8\;mov%D7\\t%0, %3%S9"
4430 [(set_attr "conds" "clob")
4431  (set_attr "length" "12")])
4433 (define_insn ""
4434   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4435         (if_then_else:SI
4436          (match_operator 6 "comparison_operator"
4437           [(match_operand:SI 4 "s_register_operand" "r,r")
4438            (match_operand:SI 5 "arm_add_operand" "rI,L")])
4439          (not:SI (match_operand:SI 1 "s_register_operand" "r,r"))
4440          (match_operator:SI 7 "shiftable_operator"
4441           [(match_operand:SI 2 "s_register_operand" "r,r")
4442            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4443    (clobber (reg 24))]
4444   ""
4445   "@
4446    cmp\\t%4, %5\;mvn%d6\\t%0, %1\;%I7%D6\\t%0, %2, %3
4447    cmn\\t%4, #%n5\;mvn%d6\\t%0, %1\;%I7%D6\\t%0, %2, %3"
4448 [(set_attr "conds" "clob")
4449  (set_attr "length" "12")])
4451 (define_insn ""
4452   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4453         (if_then_else:SI
4454          (match_operator 6 "comparison_operator"
4455           [(match_operand:SI 4 "s_register_operand" "r,r")
4456            (match_operand:SI 5 "arm_add_operand" "rI,L")])
4457          (match_operator:SI 7 "shiftable_operator"
4458           [(match_operand:SI 2 "s_register_operand" "r,r")
4459            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4460          (not:SI (match_operand:SI 1 "s_register_operand" "r,r"))))
4461    (clobber (reg 24))]
4462   ""
4463   "@
4464    cmp\\t%4, %5\;mvn%D6\\t%0, %1\;%I7%d6\\t%0, %2, %3
4465    cmn\\t%4, #%n5\;mvn%D6\\t%0, %1\;%I7%d6\\t%0, %2, %3"
4466 [(set_attr "conds" "clob")
4467  (set_attr "length" "12")])
4469 (define_insn ""
4470   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4471         (if_then_else:SI
4472          (match_operator 5 "comparison_operator"
4473           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4474            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4475          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r"))
4476          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4477    (clobber (reg:CC 24))]
4478   ""
4479   "@
4480    cmp\\t%3, %4\;rsb%d5\\t%0, %2, #0
4481    cmn\\t%3, #%n4\;rsb%d5\\t%0, %2, #0
4482    cmp\\t%3, %4\;mov%D5\\t%0, %1\;rsb%d5\\t%0, %2, #0
4483    cmn\\t%3, #%n4\;mov%D5\\t%0, %1\;rsb%d5\\t%0, %2, #0"
4484 [(set_attr "conds" "clob")
4485  (set_attr "length" "8,8,12,12")])
4487 (define_insn ""
4488   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4489         (if_then_else:SI
4490          (match_operator 5 "comparison_operator"
4491           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4492            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4493          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4494          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r"))))
4495    (clobber (reg:CC 24))]
4496   ""
4497   "@
4498    cmp\\t%3, %4\;rsb%D5\\t%0, %2, #0
4499    cmn\\t%3, #%n4\;rsb%D5\\t%0, %2, #0
4500    cmp\\t%3, %4\;mov%d5\\t%0, %1\;rsb%D5\\t%0, %2, #0
4501    cmn\\t%3, #%n4\;mov%d5\\t%0, %1\;rsb%D5\\t%0, %2, #0"
4502 [(set_attr "conds" "clob")
4503  (set_attr "length" "8,8,12,12")])
4505 (define_insn ""
4506   [(set (match_operand:SI 0 "s_register_operand" "=r")
4507         (match_operator:SI 1 "shiftable_operator"
4508          [(match_operand:SI 2 "memory_operand" "m")
4509           (match_operand:SI 3 "memory_operand" "m")]))
4510    (clobber (match_scratch:SI 4 "=r"))]
4511   "adjacent_mem_locations (operands[2], operands[3])"
4512   "*
4514   rtx ldm[3];
4515   rtx arith[4];
4516   int val1 = 0, val2 = 0;
4518   if (REGNO (operands[0]) > REGNO (operands[4]))
4519     {
4520       ldm[1] = operands[4];
4521       ldm[2] = operands[0];
4522     }
4523   else
4524     {
4525       ldm[1] = operands[0];
4526       ldm[2] = operands[4];
4527     }
4528   if (GET_CODE (XEXP (operands[2], 0)) != REG)
4529     val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
4530   if (GET_CODE (XEXP (operands[3], 0)) != REG)
4531     val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
4532   arith[0] = operands[0];
4533   arith[3] = operands[1];
4534   if (val1 < val2)
4535     {
4536       arith[1] = ldm[1];
4537       arith[2] = ldm[2];
4538     }
4539   else
4540     {
4541       arith[1] = ldm[2];
4542       arith[2] = ldm[1];
4543     }
4544   if (val1 && val2)
4545     {
4546       rtx ops[3];
4547       ldm[0] = ops[0] = operands[4];
4548       ops[1] = XEXP (XEXP (operands[2], 0), 0);
4549       ops[2] = XEXP (XEXP (operands[2], 0), 1);
4550       output_add_immediate (ops);
4551       if (val1 < val2)
4552         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4553       else
4554         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4555     }
4556   else if (val1)
4557     {
4558       ldm[0] = XEXP (operands[3], 0);
4559       if (val1 < val2)
4560         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4561       else
4562         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4563     }
4564   else
4565     {
4566       ldm[0] = XEXP (operands[2], 0);
4567       if (val1 < val2)
4568         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4569       else
4570         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4571     }
4572   output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
4573   return \"\";
4576 [(set_attr "length" "12")
4577  (set_attr "type" "load")])
4579 ;; the arm can support extended pre-inc instructions
4581 ;; In all these cases, we use operands 0 and 1 for the register being
4582 ;; incremented because those are the operands that local-alloc will
4583 ;; tie and these are the pair most likely to be tieable (and the ones
4584 ;; that will benefit the most).
4586 ;; We reject the frame pointer if it occurs anywhere in these patterns since
4587 ;; elimination will cause too many headaches.
4589 (define_insn ""
4590   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4591                          (match_operand:SI 2 "index_operand" "rJ")))
4592         (match_operand:QI 3 "s_register_operand" "r"))
4593    (set (match_operand:SI 0 "s_register_operand" "=r")
4594         (plus:SI (match_dup 1) (match_dup 2)))]
4595   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4596    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4597    && (GET_CODE (operands[2]) != REG
4598        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4599   "str%?b\\t%3, [%0, %2]!"
4600 [(set_attr "type" "store1")])
4602 (define_insn ""
4603   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4604                           (match_operand:SI 2 "s_register_operand" "r")))
4605         (match_operand:QI 3 "s_register_operand" "r"))
4606    (set (match_operand:SI 0 "s_register_operand" "=r")
4607         (minus:SI (match_dup 1) (match_dup 2)))]
4608   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4609    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4610    && (GET_CODE (operands[2]) != REG
4611        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4612   "str%?b\\t%3, [%0, -%2]!"
4613 [(set_attr "type" "store1")])
4615 (define_insn ""
4616   [(set (match_operand:QI 3 "s_register_operand" "=r")
4617         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4618                          (match_operand:SI 2 "index_operand" "rJ"))))
4619    (set (match_operand:SI 0 "s_register_operand" "=r")
4620         (plus:SI (match_dup 1) (match_dup 2)))]
4621   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4622    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4623    && (GET_CODE (operands[2]) != REG
4624        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4625   "ldr%?b\\t%3, [%0, %2]!"
4626 [(set_attr "type" "load")])
4628 (define_insn ""
4629   [(set (match_operand:QI 3 "s_register_operand" "=r")
4630         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4631                           (match_operand:SI 2 "s_register_operand" "r"))))
4632    (set (match_operand:SI 0 "s_register_operand" "=r")
4633         (minus:SI (match_dup 1) (match_dup 2)))]
4634   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4635    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4636    && (GET_CODE (operands[2]) != REG
4637        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4638   "ldr%?b\\t%3, [%0, -%2]!"
4639 [(set_attr "type" "load")])
4641 (define_insn ""
4642   [(set (match_operand:SI 3 "s_register_operand" "=r")
4643         (zero_extend:SI
4644          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4645                           (match_operand:SI 2 "index_operand" "rJ")))))
4646    (set (match_operand:SI 0 "s_register_operand" "=r")
4647         (plus:SI (match_dup 1) (match_dup 2)))]
4648   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4649    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4650    && (GET_CODE (operands[2]) != REG
4651        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4652   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
4653 [(set_attr "type" "load")])
4655 (define_insn ""
4656   [(set (match_operand:SI 3 "s_register_operand" "=r")
4657         (zero_extend:SI
4658          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4659                            (match_operand:SI 2 "s_register_operand" "r")))))
4660    (set (match_operand:SI 0 "s_register_operand" "=r")
4661         (minus:SI (match_dup 1) (match_dup 2)))]
4662   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4663    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4664    && (GET_CODE (operands[2]) != REG
4665        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4666   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
4667 [(set_attr "type" "load")])
4669 (define_insn ""
4670   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4671                          (match_operand:SI 2 "index_operand" "rJ")))
4672         (match_operand:SI 3 "s_register_operand" "r"))
4673    (set (match_operand:SI 0 "s_register_operand" "=r")
4674         (plus:SI (match_dup 1) (match_dup 2)))]
4675   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4676    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4677    && (GET_CODE (operands[2]) != REG
4678        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4679   "str%?\\t%3, [%0, %2]!"
4680 [(set_attr "type" "store1")])
4682 (define_insn ""
4683   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4684                           (match_operand:SI 2 "s_register_operand" "r")))
4685         (match_operand:SI 3 "s_register_operand" "r"))
4686    (set (match_operand:SI 0 "s_register_operand" "=r")
4687         (minus:SI (match_dup 1) (match_dup 2)))]
4688   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4689    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4690    && (GET_CODE (operands[2]) != REG
4691        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4692   "str%?\\t%3, [%0, -%2]!"
4693 [(set_attr "type" "store1")])
4695 (define_insn ""
4696   [(set (match_operand:SI 3 "s_register_operand" "=r")
4697         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4698                          (match_operand:SI 2 "index_operand" "rJ"))))
4699    (set (match_operand:SI 0 "s_register_operand" "=r")
4700         (plus:SI (match_dup 1) (match_dup 2)))]
4701   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4702    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4703    && (GET_CODE (operands[2]) != REG
4704        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4705   "ldr%?\\t%3, [%0, %2]!"
4706 [(set_attr "type" "load")])
4708 (define_insn ""
4709   [(set (match_operand:SI 3 "s_register_operand" "=r")
4710         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4711                           (match_operand:SI 2 "s_register_operand" "r"))))
4712    (set (match_operand:SI 0 "s_register_operand" "=r")
4713         (minus:SI (match_dup 1) (match_dup 2)))]
4714   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4715    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4716    && (GET_CODE (operands[2]) != REG
4717        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4718   "ldr%?\\t%3, [%0, -%2]!"
4719 [(set_attr "type" "load")])
4721 (define_insn ""
4722   [(set (match_operand:HI 3 "s_register_operand" "=r")
4723         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4724                          (match_operand:SI 2 "index_operand" "rJ"))))
4725    (set (match_operand:SI 0 "s_register_operand" "=r")
4726         (plus:SI (match_dup 1) (match_dup 2)))]
4727   "(! BYTES_BIG_ENDIAN)
4728    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
4729    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4730    && (GET_CODE (operands[2]) != REG
4731        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4732   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
4733 [(set_attr "type" "load")])
4735 (define_insn ""
4736   [(set (match_operand:HI 3 "s_register_operand" "=r")
4737         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4738                           (match_operand:SI 2 "s_register_operand" "r"))))
4739    (set (match_operand:SI 0 "s_register_operand" "=r")
4740         (minus:SI (match_dup 1) (match_dup 2)))]
4741   "(!BYTES_BIG_ENDIAN)
4742    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
4743    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4744    && (GET_CODE (operands[2]) != REG
4745        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4746   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
4747 [(set_attr "type" "load")])
4749 (define_insn ""
4750   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
4751                           [(match_operand:SI 3 "s_register_operand" "r")
4752                            (match_operand:SI 4 "const_shift_operand" "n")])
4753                          (match_operand:SI 1 "s_register_operand" "0")))
4754         (match_operand:QI 5 "s_register_operand" "r"))
4755    (set (match_operand:SI 0 "s_register_operand" "=r")
4756         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
4757                  (match_dup 1)))]
4758   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4759    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4760    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4761   "str%?b\\t%5, [%0, %3%S2]!"
4762 [(set_attr "type" "store1")])
4764 (define_insn ""
4765   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4766                           (match_operator:SI 2 "shift_operator"
4767                            [(match_operand:SI 3 "s_register_operand" "r")
4768                             (match_operand:SI 4 "const_shift_operand" "n")])))
4769         (match_operand:QI 5 "s_register_operand" "r"))
4770    (set (match_operand:SI 0 "s_register_operand" "=r")
4771         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4772                                                  (match_dup 4)])))]
4773   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4774    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4775    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4776   "str%?b\\t%5, [%0, -%3%S2]!"
4777 [(set_attr "type" "store1")])
4779 (define_insn ""
4780   [(set (match_operand:QI 5 "s_register_operand" "=r")
4781         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
4782                           [(match_operand:SI 3 "s_register_operand" "r")
4783                            (match_operand:SI 4 "const_shift_operand" "n")])
4784                          (match_operand:SI 1 "s_register_operand" "0"))))
4785    (set (match_operand:SI 0 "s_register_operand" "=r")
4786         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
4787                  (match_dup 1)))]
4788   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4789    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4790    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4791   "ldr%?b\\t%5, [%0, %3%S2]!"
4792 [(set_attr "type" "load")])
4794 (define_insn ""
4795   [(set (match_operand:QI 5 "s_register_operand" "=r")
4796         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4797                           (match_operator:SI 2 "shift_operator"
4798                            [(match_operand:SI 3 "s_register_operand" "r")
4799                             (match_operand:SI 4 "const_shift_operand" "n")]))))
4800    (set (match_operand:SI 0 "s_register_operand" "=r")
4801         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4802                                                  (match_dup 4)])))]
4803   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4804    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4805    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4806   "ldr%?b\\t%5, [%0, -%3%S2]!"
4807 [(set_attr "type" "load")])
4809 (define_insn ""
4810   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
4811                           [(match_operand:SI 3 "s_register_operand" "r")
4812                            (match_operand:SI 4 "const_shift_operand" "n")])
4813                          (match_operand:SI 1 "s_register_operand" "0")))
4814         (match_operand:SI 5 "s_register_operand" "r"))
4815    (set (match_operand:SI 0 "s_register_operand" "=r")
4816         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
4817                  (match_dup 1)))]
4818   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4819    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4820    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4821   "str%?\\t%5, [%0, %3%S2]!"
4822 [(set_attr "type" "store1")])
4824 (define_insn ""
4825   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4826                           (match_operator:SI 2 "shift_operator"
4827                            [(match_operand:SI 3 "s_register_operand" "r")
4828                             (match_operand:SI 4 "const_shift_operand" "n")])))
4829         (match_operand:SI 5 "s_register_operand" "r"))
4830    (set (match_operand:SI 0 "s_register_operand" "=r")
4831         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4832                                                  (match_dup 4)])))]
4833   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4834    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4835    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4836   "str%?\\t%5, [%0, -%3%S2]!"
4837 [(set_attr "type" "store1")])
4839 (define_insn ""
4840   [(set (match_operand:SI 5 "s_register_operand" "=r")
4841         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
4842                           [(match_operand:SI 3 "s_register_operand" "r")
4843                            (match_operand:SI 4 "const_shift_operand" "n")])
4844                          (match_operand:SI 1 "s_register_operand" "0"))))
4845    (set (match_operand:SI 0 "s_register_operand" "=r")
4846         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
4847                  (match_dup 1)))]
4848   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4849    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4850    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4851   "ldr%?\\t%5, [%0, %3%S2]!"
4852 [(set_attr "type" "load")])
4854 (define_insn ""
4855   [(set (match_operand:SI 5 "s_register_operand" "=r")
4856         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4857                           (match_operator:SI 2 "shift_operator"
4858                            [(match_operand:SI 3 "s_register_operand" "r")
4859                             (match_operand:SI 4 "const_shift_operand" "n")]))))
4860    (set (match_operand:SI 0 "s_register_operand" "=r")
4861         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4862                                                  (match_dup 4)])))]
4863   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4864    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4865    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4866   "ldr%?\\t%5, [%0, -%3%S2]!"
4867 [(set_attr "type" "load")])
4869 (define_insn ""
4870   [(set (match_operand:HI 5 "s_register_operand" "=r")
4871         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
4872                           [(match_operand:SI 3 "s_register_operand" "r")
4873                            (match_operand:SI 4 "const_shift_operand" "n")])
4874                          (match_operand:SI 1 "s_register_operand" "0"))))
4875    (set (match_operand:SI 0 "s_register_operand" "=r")
4876         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
4877                  (match_dup 1)))]
4878   "(! BYTES_BIG_ENDIAN)
4879    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
4880    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4881    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4882   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
4883 [(set_attr "type" "load")])
4885 (define_insn ""
4886   [(set (match_operand:HI 5 "s_register_operand" "=r")
4887         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4888                           (match_operator:SI 2 "shift_operator"
4889                            [(match_operand:SI 3 "s_register_operand" "r")
4890                             (match_operand:SI 4 "const_shift_operand" "n")]))))
4891    (set (match_operand:SI 0 "s_register_operand" "=r")
4892         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4893                                                  (match_dup 4)])))]
4894   "(! BYTES_BIG_ENDIAN)
4895    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
4896    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4897    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4898   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
4899 [(set_attr "type" "load")])
4901 ; It can also support extended post-inc expressions, but combine doesn't
4902 ; try these....
4903 ; It doesn't seem worth adding peepholes for anything but the most common
4904 ; cases since, unlike combine, the increment must immediately follow the load
4905 ; for this pattern to match.
4906 ; When loading we must watch to see that the base register isn't trampled by
4907 ; the load.  In such cases this isn't a post-inc expression.
4909 (define_peephole
4910   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
4911         (match_operand:QI 2 "s_register_operand" "r"))
4912    (set (match_dup 0)
4913         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
4914   ""
4915   "str%?b\\t%2, [%0], %1")
4917 (define_peephole
4918   [(set (match_operand:QI 0 "s_register_operand" "=r")
4919         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
4920    (set (match_dup 1)
4921         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
4922   "REGNO(operands[0]) != REGNO(operands[1])
4923    && (GET_CODE (operands[2]) != REG
4924        || REGNO(operands[0]) != REGNO (operands[2]))"
4925   "ldr%?b\\t%0, [%1], %2")
4927 (define_peephole
4928   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
4929         (match_operand:SI 2 "s_register_operand" "r"))
4930    (set (match_dup 0)
4931         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
4932   ""
4933   "str%?\\t%2, [%0], %1")
4935 (define_peephole
4936   [(set (match_operand:HI 0 "s_register_operand" "=r")
4937         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
4938    (set (match_dup 1)
4939         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
4940   "(! BYTES_BIG_ENDIAN)
4941    && REGNO(operands[0]) != REGNO(operands[1])
4942    && (GET_CODE (operands[2]) != REG
4943        || REGNO(operands[0]) != REGNO (operands[2]))"
4944   "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
4946 (define_peephole
4947   [(set (match_operand:SI 0 "s_register_operand" "=r")
4948         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
4949    (set (match_dup 1)
4950         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
4951   "REGNO(operands[0]) != REGNO(operands[1])
4952    && (GET_CODE (operands[2]) != REG
4953        || REGNO(operands[0]) != REGNO (operands[2]))"
4954   "ldr%?\\t%0, [%1], %2")
4956 (define_peephole
4957   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
4958                          (match_operand:SI 1 "index_operand" "rJ")))
4959         (match_operand:QI 2 "s_register_operand" "r"))
4960    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
4961   ""
4962   "str%?b\\t%2, [%0, %1]!")
4964 (define_peephole
4965   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
4966                           [(match_operand:SI 0 "s_register_operand" "r")
4967                            (match_operand:SI 1 "const_int_operand" "n")])
4968                          (match_operand:SI 2 "s_register_operand" "+r")))
4969         (match_operand:QI 3 "s_register_operand" "r"))
4970    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
4971                                (match_dup 2)))]
4972   ""
4973   "str%?b\\t%3, [%2, %0%S4]!")
4975 ; This pattern is never tried by combine, so do it as a peephole
4977 (define_peephole
4978   [(set (match_operand:SI 0 "s_register_operand" "=r")
4979         (match_operand:SI 1 "s_register_operand" "r"))
4980    (set (match_operand 2 "cc_register" "")
4981         (compare (match_dup 1) (const_int 0)))]
4982   ""
4983   "sub%?s\\t%0, %1, #0"
4984 [(set_attr "conds" "set")])
4986 ; Peepholes to spot possible load- and store-multiples, if the ordering is
4987 ; reversed, check that the memory references aren't volatile.
4989 (define_peephole
4990   [(set (match_operand:SI 0 "s_register_operand" "=r")
4991         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
4992                          (const_int 12))))
4993    (set (match_operand:SI 2 "s_register_operand" "=r")
4994         (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4995    (set (match_operand:SI 3 "s_register_operand" "=r")
4996         (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4997    (set (match_operand:SI 4 "s_register_operand" "=r")
4998         (mem:SI (match_dup 1)))]
4999   "REGNO (operands[0]) > REGNO (operands[2])
5000    && REGNO (operands[2]) > REGNO (operands[3])
5001    && REGNO (operands[3]) > REGNO (operands[4])
5002    && !(REGNO (operands[1]) == REGNO (operands[0])
5003        || REGNO (operands[1]) == REGNO (operands[2])
5004        || REGNO (operands[1]) == REGNO (operands[3])
5005        || REGNO (operands[1]) == REGNO (operands[4]))
5006    && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5007    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
5008    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5009                                          (prev_nonnote_insn (insn)))))
5010    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5011                                          (prev_nonnote_insn 
5012                                           (prev_nonnote_insn (insn))))))"
5013   "ldm%?ia\\t%1, {%4, %3, %2, %0}\\t%@ phole ldm")
5015 (define_peephole
5016   [(set (match_operand:SI 0 "s_register_operand" "=r")
5017         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5018                          (const_int 8))))
5019    (set (match_operand:SI 2 "s_register_operand" "=r")
5020         (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5021    (set (match_operand:SI 3 "s_register_operand" "=r")
5022         (mem:SI (match_dup 1)))]
5023   "REGNO (operands[0]) >  REGNO (operands[2])
5024    && REGNO (operands[2]) > REGNO (operands[3])
5025    && !(REGNO (operands[1]) == REGNO (operands[0])
5026        || REGNO (operands[1]) == REGNO (operands[2])
5027        || REGNO (operands[1]) == REGNO (operands[3]))
5028    && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5029    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
5030    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5031                                          (prev_nonnote_insn (insn)))))"
5032   "ldm%?ia\\t%1, {%3, %2, %0}\\t%@ phole ldm")
5034 (define_peephole
5035   [(set (match_operand:SI 0 "s_register_operand" "=r")
5036         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5037                          (const_int 4))))
5038    (set (match_operand:SI 2 "s_register_operand" "=r")
5039         (mem:SI (match_dup 1)))]
5040   "REGNO (operands[0]) > REGNO (operands[2])
5041    && !(REGNO (operands[1]) == REGNO (operands[0])
5042        || REGNO (operands[1]) == REGNO (operands[2]))
5043    && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5044    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))"
5045   "ldm%?ia\\t%1, {%2, %0}\\t%@ phole ldm")
5047 (define_peephole
5048   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5049                          (const_int 12)))
5050         (match_operand:SI 0 "s_register_operand" "r"))
5051    (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5052         (match_operand:SI 2 "s_register_operand" "r"))
5053    (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5054         (match_operand:SI 3 "s_register_operand" "r"))
5055    (set (mem:SI (match_dup 1))
5056         (match_operand:SI 4 "s_register_operand" "r"))]
5057   "REGNO (operands[0]) >  REGNO (operands[2])
5058    && REGNO (operands[2]) > REGNO (operands[3])
5059    && REGNO (operands[3]) > REGNO (operands[4])
5060    && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5061    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5062    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5063                                           (prev_nonnote_insn (insn)))))
5064    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5065                                           (prev_nonnote_insn 
5066                                            (prev_nonnote_insn (insn))))))"
5067   "stm%?ia\\t%1, {%4, %3, %2, %0}\\t%@ phole stm")
5069 (define_peephole
5070   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5071                          (const_int 8)))
5072         (match_operand:SI 0 "s_register_operand" "r"))
5073    (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5074         (match_operand:SI 2 "s_register_operand" "r"))
5075    (set (mem:SI (match_dup 1))
5076         (match_operand:SI 3 "s_register_operand" "r"))]
5077   "REGNO (operands[0]) >  REGNO (operands[2])
5078    && REGNO (operands[2]) > REGNO (operands[3])
5079    && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5080    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5081    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5082                                           (prev_nonnote_insn (insn)))))"
5083   "stm%?ia\\t%1, {%3, %2, %0}\\t%@ phole stm")
5085 (define_peephole
5086   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5087                          (const_int 4)))
5088         (match_operand:SI 0 "s_register_operand" "r"))
5089    (set (mem:SI (match_dup 1))
5090         (match_operand:SI 2 "s_register_operand" "r"))]
5091   "REGNO (operands[0]) >  REGNO (operands[2])
5092    && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5093    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))"
5094   "stm%?ia\\t%1, {%2, %0}\\t%@ phole stm")
5096 ;; A call followed by return can be replaced by restoring the regs and
5097 ;; jumping to the subroutine, provided we aren't passing the address of
5098 ;; any of our local variables.  If we call alloca then this is unsafe
5099 ;; since restoring the frame frees the memory, which is not what we want.
5100 ;; Sometimes the return might have been targeted by the final prescan:
5101 ;; if so then emit a propper return insn as well.
5102 ;; Unfortunately, if the frame pointer is required, we don't know if the
5103 ;; current function has any implicit stack pointer adjustments that will 
5104 ;; be restored by the return: we can't therefore do a tail call.
5105 ;; Another unfortunate that we can't handle is if current_function_args_size
5106 ;; is non-zero: in this case elimination of the argument pointer assumed
5107 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5108 ;; calculations.
5110 (define_peephole
5111   [(parallel [(call (mem:SI (match_operand:SI 0 "" "i"))
5112                           (match_operand:SI 1 "general_operand" "g"))
5113                     (clobber (reg:SI 14))])
5114    (return)]
5115   "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN
5116     && !get_frame_size () && !current_function_calls_alloca
5117     && !frame_pointer_needed && !current_function_args_size)"
5118   "*
5120   extern rtx arm_target_insn;
5121   extern int arm_ccfsm_state, arm_current_cc;
5123   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5124   {
5125     arm_current_cc ^= 1;
5126     output_return_instruction (NULL, TRUE);
5127     arm_ccfsm_state = 0;
5128     arm_target_insn = NULL;
5129   }
5131   output_return_instruction (NULL, FALSE);
5132   return \"b%?\\t%a0\";
5134 [(set (attr "conds")
5135       (if_then_else (eq_attr "cpu" "arm6")
5136                     (const_string "clob")
5137                     (const_string "nocond")))
5138  (set_attr "length" "8")])
5140 (define_peephole
5141   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5142                    (call (mem:SI (match_operand:SI 1 "" "i"))
5143                          (match_operand:SI 2 "general_operand" "g")))
5144               (clobber (reg:SI 14))])
5145    (return)]
5146   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5147     && !get_frame_size () && !current_function_calls_alloca
5148     && !frame_pointer_needed && !current_function_args_size)"
5149   "*
5151   extern rtx arm_target_insn;
5152   extern int arm_ccfsm_state, arm_current_cc;
5154   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5155   {
5156     arm_current_cc ^= 1;
5157     output_return_instruction (NULL, TRUE);
5158     arm_ccfsm_state = 0;
5159     arm_target_insn = NULL;
5160   }
5162   output_return_instruction (NULL, FALSE);
5163   return \"b%?\\t%a1\";
5165 [(set (attr "conds")
5166       (if_then_else (eq_attr "cpu" "arm6")
5167                     (const_string "clob")
5168                     (const_string "nocond")))
5169  (set_attr "length" "8")])
5171 ;; As above but when this function is not void, we must be returning the
5172 ;; result of the called subroutine.
5174 (define_peephole
5175   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5176                    (call (mem:SI (match_operand:SI 1 "" "i"))
5177                          (match_operand:SI 2 "general_operand" "g")))
5178               (clobber (reg:SI 14))])
5179    (use (match_dup 0))
5180    (return)]
5181   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5182     && !get_frame_size () && !current_function_calls_alloca
5183     && !frame_pointer_needed && !current_function_args_size)"
5184   "*
5186   extern rtx arm_target_insn;
5187   extern int arm_ccfsm_state, arm_current_cc;
5189   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5190   {
5191     arm_current_cc ^= 1;
5192     output_return_instruction (NULL, TRUE);
5193     arm_ccfsm_state = 0;
5194     arm_target_insn = NULL;
5195   }
5197   output_return_instruction (NULL, FALSE);
5198   return \"b%?\\t%a1\";
5200 [(set (attr "conds")
5201       (if_then_else (eq_attr "cpu" "arm6")
5202                     (const_string "clob")
5203                     (const_string "nocond")))
5204  (set_attr "length" "8")])
5206 ;; If calling a subroutine and then jumping back to somewhere else, but not
5207 ;; too far away, then we can set the link register with the branch address
5208 ;; and jump direct to the subroutine.  On return from the subroutine
5209 ;; execution continues at the branch; this avoids a prefetch stall.
5210 ;; We use the length attribute (via short_branch ()) to establish whether or
5211 ;; not this is possible, this is the same asthe sparc does.
5213 (define_peephole
5214   [(parallel[(call (mem:SI (match_operand:SI 0 "" "i"))
5215                    (match_operand:SI 1 "general_operand" "g"))
5216              (clobber (reg:SI 14))])
5217    (set (pc)
5218         (label_ref (match_operand 2 "" "")))]
5219   "GET_CODE (operands[0]) == SYMBOL_REF 
5220    && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
5221    && arm_insn_not_targeted (insn)"
5222   "*
5224   int backward = arm_backwards_branch (INSN_UID (insn),
5225                                        INSN_UID (operands[2]));
5227 #if 0
5228   /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
5229    * above, leaving it out means that the code will still run on an arm 2 or 3
5230    */
5231   if (TARGET_6)
5232     {
5233       if (backward)
5234         output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l2)\", operands);
5235       else
5236         output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l2 - . -8)\", operands);
5237     }
5238   else
5239 #endif
5240     {
5241       output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands);
5242       if (backward)
5243         output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l2)\", operands);
5244       else
5245         output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l2 - . -4)\", operands);
5246     }
5247   return \"b%?\\t%a0\";
5249 [(set (attr "conds")
5250       (if_then_else (eq_attr "cpu" "arm6")
5251                     (const_string "clob")
5252                     (const_string "nocond")))
5253  (set (attr "length")
5254       (if_then_else (eq_attr "cpu" "arm6")
5255                     (const_int 8)
5256                     (const_int 12)))])
5258 (define_peephole
5259   [(parallel[(set (match_operand:SI 0 "s_register_operand" "=r")
5260                   (call (mem:SI (match_operand:SI 1 "" "i"))
5261                         (match_operand:SI 2 "general_operand" "g")))
5262              (clobber (reg:SI 14))])
5263    (set (pc)
5264         (label_ref (match_operand 3 "" "")))]
5265   "GET_CODE (operands[0]) == SYMBOL_REF
5266    && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
5267    && arm_insn_not_targeted (insn)"
5268   "*
5270   int backward = arm_backwards_branch (INSN_UID (insn),
5271                                        INSN_UID (operands[3]));
5273 #if 0
5274   /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
5275    * above, leaving it out means that the code will still run on an arm 2 or 3
5276    */
5277   if (TARGET_6)
5278     {
5279       if (backward)
5280         output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l3)\", operands);
5281       else
5282         output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l3 - . -8)\", operands);
5283     }
5284   else
5285 #endif
5286     {
5287       output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands);
5288       if (backward)
5289         output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l3)\", operands);
5290       else
5291         output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l3 - . -4)\", operands);
5292     }
5293   return \"b%?\\t%a1\";
5295 [(set (attr "conds")
5296       (if_then_else (eq_attr "cpu" "arm6")
5297                     (const_string "clob")
5298                     (const_string "nocond")))
5299  (set (attr "length")
5300       (if_then_else (eq_attr "cpu" "arm6")
5301                     (const_int 8)
5302                     (const_int 12)))])
5304 (define_split
5305   [(set (pc)
5306         (if_then_else (match_operator 0 "comparison_operator"
5307                        [(match_operator:SI 1 "shift_operator"
5308                          [(match_operand:SI 2 "s_register_operand" "r")
5309                           (match_operand:SI 3 "reg_or_int_operand" "rM")])
5310                         (match_operand:SI 4 "s_register_operand" "r")])
5311                       (label_ref (match_operand 5 "" ""))
5312                       (pc)))
5313    (clobber (reg 24))]
5314   ""
5315   [(set (reg:CC 24)
5316         (compare:CC (match_dup 4)
5317                     (match_op_dup 1 [(match_dup 2) (match_dup 3)])))
5318    (set (pc)
5319         (if_then_else (match_op_dup 0 [(reg 24) (const_int 0)])
5320                       (label_ref (match_dup 5))
5321                       (pc)))]
5322   "
5323   operands[0] = gen_rtx (swap_condition (GET_CODE (operands[0])), VOIDmode,
5324                          operands[1], operands[2]);
5327 (define_split
5328   [(set (match_operand:SI 0 "s_register_operand" "")
5329         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
5330                        (const_int 0))
5331                 (neg:SI (match_operator:SI 2 "comparison_operator"
5332                          [(match_operand:SI 3 "s_register_operand" "")
5333                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
5334    (clobber (match_operand:SI 5 "s_register_operand" ""))]
5335   ""
5336   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
5337    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5338                               (match_dup 5)))]
5339   "")
5341 ;; This pattern can be used because cc_noov mode implies that the following
5342 ;; branch will be an equality (EQ or NE), so the sign extension is not
5343 ;; needed.  Combine doesn't eliminate these because by the time it sees the
5344 ;; branch it no-longer knows that the data came from memory.
5346 (define_insn ""
5347   [(set (reg:CC_NOOV 24)
5348         (compare:CC_NOOV
5349          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "m") 0)
5350                     (const_int 24))
5351          (match_operand 1 "immediate_operand" "I")))
5352    (clobber (match_scratch:SI 2 "=r"))]
5353   "((unsigned long) INTVAL (operands[1]))
5354    == (((unsigned long) INTVAL (operands[1])) >> 24) << 24"
5355   "*
5356   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
5357   output_asm_insn (\"ldr%?b\\t%2, %0\", operands);
5358   output_asm_insn (\"cmp%?\\t%2, %1\", operands);
5359   return \"\";
5361 [(set_attr "conds" "set")
5362  (set_attr "length" "8")
5363  (set_attr "type" "load")])
5365 (define_expand "prologue"
5366   [(clobber (const_int 0))]
5367   ""
5368   "
5369   arm_expand_prologue ();
5370   DONE;
5373 (define_expand "save_stack_nonlocal"
5374   [(match_operand:DI 0 "memory_operand" "")
5375    (match_operand:SI 1 "s_register_operand" "")]
5376   ""
5377   "
5379   /* We also need to save the frame pointer for non-local gotos */
5380   emit_move_insn (operand_subword (operands[0], 0, 0, DImode),
5381                   hard_frame_pointer_rtx);
5382   emit_move_insn (operand_subword (operands[0], 1, 0, DImode), operands[1]);
5383   DONE;
5386 (define_expand "restore_stack_nonlocal"
5387   [(match_operand:SI 0 "s_register_operand" "")
5388    (match_operand:DI 1 "memory_operand" "")]
5389   ""
5390   "
5392   /* Restore the frame pointer first, the stack pointer second. */
5393   emit_move_insn (operands[0], operand_subword (operands[1], 1, 0, DImode));
5394   emit_move_insn (hard_frame_pointer_rtx, operand_subword (operands[1], 0, 0,
5395                                                            DImode));
5396   DONE;
5399 ;; This split is only used during output to reduce the number of patterns
5400 ;; that need assembler instructions adding to them.  We allowed the setting
5401 ;; of the conditions to be implicit during rtl generation so that
5402 ;; the conditional compare patterns would work.  However this conflicts to
5403 ;; some extend with the conditional data operations, so we have to split them
5404 ;; up again here.
5406 (define_split
5407   [(set (match_operand:SI 0 "s_register_operand" "")
5408         (if_then_else:SI (match_operator 1 "comparison_operator"
5409                           [(match_operand 2 "" "") (match_operand 3 "" "")])
5410                          (match_operand 4 "" "")
5411                          (match_operand 5 "" "")))
5412    (clobber (reg 24))]
5413   "reload_completed"
5414   [(set (match_dup 6) (match_dup 7))
5415    (set (match_dup 0) 
5416         (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
5417                          (match_dup 4)
5418                          (match_dup 5)))]
5419   "
5421   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
5422                                            operands[3]);
5424   operands[6] = gen_rtx (REG, mode, 24);
5425   operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
5430 (define_insn ""
5431   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5432         (if_then_else:SI (match_operator 4 "comparison_operator"
5433                           [(match_operand 3 "cc_register" "") (const_int 0)])
5434                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5435                          (not:SI
5436                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
5437   ""
5438   "@
5439    mvn%D4\\t%0, %2
5440    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
5441 [(set_attr "conds" "use")
5442  (set_attr "length" "4,8")])
5444 ;; The next two patterns occur when an AND operation is followed by a
5445 ;; scc insn sequence 
5447 (define_insn ""
5448   [(set (match_operand:SI 0 "s_register_operand" "=r")
5449         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5450                          (const_int 1)
5451                          (match_operand:SI 2 "immediate_operand" "n")))]
5452   ""
5453   "*
5454   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5455   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
5456   return \"mvnne\\t%0, #0\";
5458 [(set_attr "conds" "clob")
5459  (set_attr "length" "8")])
5461 (define_insn ""
5462   [(set (match_operand:SI 0 "s_register_operand" "=r")
5463         (not:SI
5464          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5465                           (const_int 1)
5466                           (match_operand:SI 2 "immediate_operand" "n"))))]
5467   ""
5468   "*
5469   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5470   output_asm_insn (\"tst\\t%1, %2\", operands);
5471   output_asm_insn (\"mvneq\\t%0, #0\", operands);
5472   return \"movne\\t%0, #0\";
5474 [(set_attr "conds" "clob")
5475  (set_attr "length" "12")])
5477 ;; Push multiple registers to the stack.  The first register is in the
5478 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
5479 ;; expressions.
5480 (define_insn ""
5481   [(match_parallel 2 "multi_register_push"
5482     [(set (match_operand:BLK 0 "memory_operand" "=m")
5483           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
5484   ""
5485   "*
5487   char pattern[100];
5488   int i;
5489   extern int lr_save_eliminated;
5491   if (lr_save_eliminated)
5492     {
5493       if (XVECLEN (operands[2], 0) > 1)
5494         abort ();
5495       return \"\";
5496     }
5497   strcpy (pattern, \"stmfd\\t%m0!, {%|%1\");
5498   for (i = 1; i < XVECLEN (operands[2], 0); i++)
5499     {
5500       strcat (pattern, \", %|\");
5501       strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
5502                                               0))]);
5503     }
5504   strcat (pattern, \"}\");
5505   output_asm_insn (pattern, operands);
5506   return \"\";
5508 [(set_attr "type" "store4")])