(attributes): Rearrange order, so that condition clobbering
[official-gcc.git] / gcc / config / arm / arm.md
blob6bdcd8081932f093a69d9e1ddc4def356a8d09bc
1 ;;- Machine description for Advanced RISC Machines' ARM for GNU compiler
2 ;;  Copyright (C) 1991, 1993, 1994, 1995 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, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26 ;; There are patterns in this file to support XFmode arithmetic.
27 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
28 ;; (See arm.h)
30 ;; UNSPEC Usage:
31 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
32 ;;   the mode is MODE_FLOAT
33 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
34 ;;   the mode is MODE_FLOAT
35 ;; 2 `push multiple' operation: operand 0 is the first register.  Subsequent
36 ;;   registers are in parallel (use...) expressions.
37 ;; 3 A symbol that has been treated properly for pic usage, that is, we
38 ;;   will add the pic_register value to it before trying to dereference it.
40 ;; Attributes
42 ; PROG_MODE attribute is used to determine whether condition codes are
43 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
44 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
45 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
47 ; CPU attribute is used to determine whether condition codes are clobbered
48 ; by a call insn: on the arm6 they are if in 32-bit addressing mode; on the
49 ; arm2 and arm3 the condition codes are restored by the return.
51 (define_attr "cpu" "arm2,arm3,arm6,arm7"
52         (const (symbol_ref "arm_cpu_attr")))
54 ; Floating Point Unit.  If we only have floating point emulation, then there
55 ; is no point in scheduling the floating point insns.  (Well, for best
56 ; performance we should try and group them together).
58 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
60 ; LENGTH of an instruction (in bytes)
61 (define_attr "length" "" (const_int 4))
63 ; An assembler sequence may clobber the condition codes without us knowing
64 (define_asm_attributes
65  [(set_attr "conds" "clob")
66   (set_attr "length" "4")])
68 ; TYPE attribute is used to detect floating point instructions which, if
69 ; running on a co-processor can run in parallel with other, basic instructions
70 ; If write-buffer scheduling is enabled then it can also be used in the
71 ; scheduling of writes.
73 ; Classification of each insn
74 ; normal        any data instruction that doesn't hit memory or fp regs
75 ; mult          a multiply instruction
76 ; block         blockage insn, this blocks all functional units
77 ; float         a floating point arithmetic operation (subject to expansion)
78 ; fdivx         XFmode floating point division
79 ; fdivd         DFmode floating point division
80 ; fdivs         SFmode floating point division
81 ; fmul          Floating point multiply
82 ; ffmul         Fast floating point multiply
83 ; farith        Floating point arithmetic (4 cycle)
84 ; ffarith       Fast floating point arithmetic (2 cycle)
85 ; float_em      a floating point arithmetic operation that is normally emulated
86 ;               even on a machine with an fpa.
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,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4" 
102         (const_string "normal"))
104 ; condition codes: this one is used by final_prescan_insn to speed up
105 ; conditionalizing instructions.  It saves having to scan the rtl to see if
106 ; it uses or alters the condition codes.
108 ; USE means that the condition codes are used by the insn in the process of
109 ; outputting code, this means (at present) that we can't use the insn in
110 ; inlined branches
112 ; SET means that the purpose of the insn is to set the condition codes in a
113 ; well defined manner.
115 ; CLOB means that the condition codes are altered in an undefined manner, if
116 ; they are altered at all
118 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
119 ; but are if the branch wasn't taken; the effect is to limit the branch
120 ; elimination scanning.
122 ; NOCOND means that the condition codes are neither altered nor affect the
123 ; output of this insn
125 (define_attr "conds" "use,set,clob,jump_clob,nocond"
126         (if_then_else (eq_attr "type" "call")
127          (if_then_else (eq_attr "prog_mode" "prog32")
128           (const_string "clob") (const_string "nocond"))
129          (const_string "nocond")))
131 (define_attr "write_conflict" "no,yes"
132   (if_then_else (eq_attr "type"
133                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
134                 (const_string "yes")
135                 (const_string "no")))
137 (define_attr "core_cycles" "single,multi"
138   (if_then_else (eq_attr "type"
139                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
140                 (const_string "single")
141                 (const_string "multi")))
143 ; The write buffer on some of the arm6 processors is hard to model exactly.
144 ; There is room in the buffer for up to two addresses and up to eight words
145 ; of memory, but the two needn't be split evenly.  When writing the two
146 ; addresses are fully pipelined.  However, a read from memory that is not
147 ; currently in the cache will block until the writes have completed.
148 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
149 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
150 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
151 ; cycle to add as well.
153 ;; (define_function_unit {name} {num-units} {n-users} {test}
154 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
155 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
156                                      (eq_attr "type" "fdivx")) 71 69)
158 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
159                                      (eq_attr "type" "fdivd")) 59 57)
161 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
162                                      (eq_attr "type" "fdivs")) 31 29)
164 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
165                                      (eq_attr "type" "fmul")) 9 7)
167 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
168                                      (eq_attr "type" "ffmul")) 6 4)
170 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
171                                      (eq_attr "type" "farith")) 4 2)
173 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
174                                      (eq_attr "type" "ffarith")) 2 2)
176 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
177                                      (eq_attr "type" "r_2_f")) 5 3)
179 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
180                                      (eq_attr "type" "f_2_r")) 1 2)
182 ;; The fpa10 doesn't really have a memory read unit, but it can start to
183 ;; speculatively execute the instruction in the pipeline, provided the data
184 ;; is already loaded, so pretend reads have a delay of 2 (and that the
185 ;; pipeline is infinite.
187 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
188                                          (eq_attr "type" "f_load")) 3 1)
190 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store1") 5 3)
191 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store2") 7 4)
192 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store3") 9 5)
193 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store4") 11 6)
194 (define_function_unit "write_buf" 1 2 (eq_attr "type" "r_mem_f") 5 3)
196 ;; The write_blockage unit models (partially), the fact that writes will stall
197 ;; until the write buffer empties.
199 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store1") 5 5
200         [(eq_attr "write_conflict" "yes")])
201 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store2") 7 7
202         [(eq_attr "write_conflict" "yes")])
203 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store3") 9 9
204         [(eq_attr "write_conflict" "yes")])
205 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store4") 11 11
206         [(eq_attr "write_conflict" "yes")])
207 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "r_mem_f") 5 5
208         [(eq_attr "write_conflict" "yes")])
209 (define_function_unit "write_blockage" 1 0 
210         (eq_attr "write_conflict" "yes") 1 1)
212 (define_function_unit "core" 1 1 (eq_attr "core_cycles" "single") 1 1)
214 (define_function_unit "core" 1 1 (eq_attr "type" "load") 2 2)
216 (define_function_unit "core" 1 1 (eq_attr "type" "mult") 16 16)
218 (define_function_unit "core" 1 1 (eq_attr "type" "store1") 2 2)
220 (define_function_unit "core" 1 1 (eq_attr "type" "store2") 3 3)
222 (define_function_unit "core" 1 1 (eq_attr "type" "store3") 4 4)
224 (define_function_unit "core" 1 1 (eq_attr "type" "store4") 5 5)
226 (define_function_unit "core" 1 1
227   (and (eq_attr "core_cycles" "multi")
228        (eq_attr "type" "!mult,load,store2,store3,store4")) 32 32)
231 ;; Note: For DImode insns, there is normally no reason why operands should
232 ;; not be in the same register, what we don't want is for something being
233 ;; written to partially overlap something that is an input.
235 ;; Addition insns.
237 (define_insn "adddi3"
238   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
239         (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
240                  (match_operand:DI 2 "s_register_operand" "r,0")))
241    (clobber (reg:CC 24))]
242   ""
243   "adds\\t%0, %1, %2\;adc\\t%R0, %R1, %R2"
244 [(set_attr "conds" "clob")
245  (set_attr "length" "8")])
247 (define_insn "*adddi_sesidi_di"
248   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
249         (plus:DI (sign_extend:DI
250                   (match_operand:SI 1 "s_register_operand" "r,r"))
251                  (match_operand:DI 2 "s_register_operand" "r,0")))
252    (clobber (reg:CC 24))]
253   ""
254   "adds\\t%0, %2, %1\;adc\\t%R0, %R2, %1, asr #31"
255 [(set_attr "conds" "clob")
256  (set_attr "length" "8")])
258 (define_insn "*adddi_zesidi_di"
259   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
260         (plus:DI (zero_extend:DI
261                   (match_operand:SI 1 "s_register_operand" "r,r"))
262                  (match_operand:DI 2 "s_register_operand" "r,0")))
263    (clobber (reg:CC 24))]
264   ""
265   "adds\\t%0, %2, %1\;adc\\t%R0, %R2, #0"
266 [(set_attr "conds" "clob")
267  (set_attr "length" "8")])
269 (define_expand "addsi3"
270   [(set (match_operand:SI 0 "s_register_operand" "")
271         (plus:SI (match_operand:SI 1 "s_register_operand" "")
272                  (match_operand:SI 2 "reg_or_int_operand" "")))]
273   ""
274   "
275   if (GET_CODE (operands[2]) == CONST_INT)
276     {
277       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
278                           operands[1],
279                           (reload_in_progress || reload_completed ? 0
280                            : preserve_subexpressions_p ()));
281       DONE;
282     }
285 (define_split
286   [(set (match_operand:SI 0 "s_register_operand" "")
287         (plus:SI (match_operand:SI 1 "s_register_operand" "")
288                  (match_operand:SI 2 "const_int_operand" "")))]
289   "! (const_ok_for_arm (INTVAL (operands[2]))
290       || const_ok_for_arm (-INTVAL (operands[2])))"
291   [(clobber (const_int 0))]
292   "
293   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
294                       operands[1], 0);
295   DONE;
298 (define_insn "*addsi3_insn"
299   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
300         (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
301                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
302   ""
303   "@
304    add%?\\t%0, %1, %2
305    sub%?\\t%0, %1, #%n2
306    #"
307 [(set_attr "length" "4,4,16")])
309 (define_insn "*addsi3_compare0"
310   [(set (reg:CC_NOOV 24)
311         (compare:CC_NOOV
312          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
313                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
314          (const_int 0)))
315    (set (match_operand:SI 0 "s_register_operand" "=r,r")
316         (plus:SI (match_dup 1) (match_dup 2)))]
317   ""
318   "@
319    add%?s\\t%0, %1, %2
320    sub%?s\\t%0, %1, #%n2"
321 [(set_attr "conds" "set")])
323 (define_insn "*addsi3_compareneg"
324   [(set (reg:CC 24)
325         (compare:CC (match_operand:SI 1 "s_register_operand" "r,r")
326                     (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
327    (set (match_operand:SI 0 "s_register_operand" "=r,r")
328         (plus:SI (match_dup 1) (match_dup 2)))]
329   ""
330   "@
331    add%?s\\t%0, %1, %2
332    sub%?s\\t%0, %1, #%n2"
333 [(set_attr "conds" "set")])
335 (define_insn "incscc"
336   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
337         (plus:SI (match_operator:SI 2 "comparison_operator"
338                     [(reg 24) (const_int 0)])
339                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
340   ""
341   "@
342   add%d2\\t%0, %1, #1
343   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
344 [(set_attr "conds" "use")
345  (set_attr "length" "4,8")])
347 ; If a constant is too big to fit in a single instruction then the constant
348 ; will be pre-loaded into a register taking at least two insns, we might be
349 ; able to merge it with an add, but it depends on the exact value.
351 (define_split
352   [(set (match_operand:SI 0 "s_register_operand" "=r")
353         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
354                  (match_operand:SI 2 "immediate_operand" "n")))]
355   "!(const_ok_for_arm (INTVAL (operands[2]))
356      || const_ok_for_arm (-INTVAL (operands[2])))"
357   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
358    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
359   "
361   unsigned int val = (unsigned) INTVAL (operands[2]);
362   int i;
363   unsigned int temp;
365   /* this code is similar to the approach followed in movsi, but it must
366      generate exactly two insns */
368   for (i = 30; i >= 0; i -= 2)
369     {
370       if (val & (3 << i))
371         {
372           i -= 6;
373           if (i < 0) i = 0;
374           if (const_ok_for_arm (temp = (val & ~(255 << i))))
375             {
376               val &= 255 << i;
377               break;
378             }
379           /* we might be able to do this as (larger number - small number) */
380           temp = ((val >> i) & 255) + 1;
381           if (temp > 255 && i < 24)
382             {
383               i += 2;
384               temp = ((val >> i) & 255) + 1;
385             }
386           if (const_ok_for_arm ((temp << i) - val))
387             {
388               i = temp << i;
389               temp = (unsigned) - (int) (i - val);
390               val = i;
391               break;
392             }
393           FAIL;
394         }
395     }
396   /* if we got here, we have found a way of doing it in two instructions.
397      the two constants are in val and temp */
398   operands[2] = GEN_INT ((int)val);
399   operands[3] = GEN_INT ((int)temp);
403 (define_insn "addsf3"
404   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
405         (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
406                  (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
407   "TARGET_HARD_FLOAT"
408   "@
409    adf%?s\\t%0, %1, %2
410    suf%?s\\t%0, %1, #%N2"
411 [(set_attr "type" "farith")])
413 (define_insn "adddf3"
414   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
415         (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
416                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
417   "TARGET_HARD_FLOAT"
418   "@
419    adf%?d\\t%0, %1, %2
420    suf%?d\\t%0, %1, #%N2"
421 [(set_attr "type" "farith")])
423 (define_insn "*adddf_df_esfdf"
424   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
425         (plus:DF (float_extend:DF
426                   (match_operand:SF 1 "s_register_operand" "f,f"))
427                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
428   "TARGET_HARD_FLOAT"
429   "@
430    adf%?d\\t%0, %1, %2
431    suf%?d\\t%0, %1, #%N2"
432 [(set_attr "type" "farith")])
434 (define_insn "*adddf_df_esfdf"
435   [(set (match_operand:DF 0 "s_register_operand" "=f")
436         (plus:DF (match_operand:DF 1 "s_register_operand" "f")
437                  (float_extend:DF
438                   (match_operand:SF 2 "s_register_operand" "f"))))]
439   "TARGET_HARD_FLOAT"
440   "adf%?d\\t%0, %1, %2"
441 [(set_attr "type" "farith")])
443 (define_insn "*adddf_esfdf_esfdf"
444   [(set (match_operand:DF 0 "s_register_operand" "=f")
445         (plus:DF (float_extend:DF 
446                   (match_operand:SF 1 "s_register_operand" "f"))
447                  (float_extend:DF
448                   (match_operand:SF 2 "s_register_operand" "f"))))]
449   "TARGET_HARD_FLOAT"
450   "adf%?d\\t%0, %1, %2"
451 [(set_attr "type" "farith")])
453 (define_insn "addxf3"
454   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
455         (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
456                  (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
457   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
458   "@
459    adf%?e\\t%0, %1, %2
460    suf%?e\\t%0, %1, #%N2"
461 [(set_attr "type" "farith")])
463 (define_insn "subdi3"
464   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
465         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
466                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
467    (clobber (reg:CC 24))]
468   ""
469   "subs\\t%0, %1, %2\;sbc\\t%R0, %R1, %R2"
470 [(set_attr "conds" "clob")
471  (set_attr "length" "8")])
473 (define_insn "*subdi_di_zesidi"
474   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
475         (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
476                   (zero_extend:DI
477                    (match_operand:SI 2 "s_register_operand" "r,r"))))
478    (clobber (reg:CC 24))]
479   ""
480   "subs\\t%0, %1, %2\;sbc\\t%R0, %R1, #0"
481 [(set_attr "conds" "clob")
482  (set_attr "length" "8")])
484 (define_insn "*subdi_di_sesidi"
485   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
486         (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
487                   (sign_extend:DI
488                    (match_operand:SI 2 "s_register_operand" "r,r"))))
489    (clobber (reg:CC 24))]
490   ""
491   "subs\\t%0, %1, %2\;sbc\\t%R0, %R1, %2, asr #31"
492 [(set_attr "conds" "clob")
493  (set_attr "length" "8")])
495 (define_insn "*subdi_zesidi_di"
496   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
497         (minus:DI (zero_extend:DI
498                    (match_operand:SI 2 "s_register_operand" "r,r"))
499                   (match_operand:DI 1 "s_register_operand" "?r,0")))
500    (clobber (reg:CC 24))]
501   ""
502   "rsbs\\t%0, %1, %2\;rsc\\t%R0, %R1, #0"
503 [(set_attr "conds" "clob")
504  (set_attr "length" "8")])
506 (define_insn "*subdi_sesidi_di"
507   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
508         (minus:DI (sign_extend:DI
509                    (match_operand:SI 2 "s_register_operand" "r,r"))
510                   (match_operand:DI 1 "s_register_operand" "?r,0")))
511    (clobber (reg:CC 24))]
512   ""
513   "rsbs\\t%0, %1, %2\;rsc\\t%R0, %R1, %2, asr #31"
514 [(set_attr "conds" "clob")
515  (set_attr "length" "8")])
517 (define_insn "*subdi_zesidi_zesidi"
518   [(set (match_operand:DI 0 "s_register_operand" "=r")
519         (minus:DI (zero_extend:DI
520                    (match_operand:SI 1 "s_register_operand" "r"))
521                   (zero_extend:DI
522                    (match_operand:SI 2 "s_register_operand" "r"))))
523    (clobber (reg:CC 24))]
524   ""
525   "subs\\t%0, %1, %2\;rsc\\t%R0, %1, %1"
526 [(set_attr "conds" "clob")
527  (set_attr "length" "8")])
529 (define_expand "subsi3"
530   [(set (match_operand:SI 0 "s_register_operand" "")
531         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
532                   (match_operand:SI 2 "s_register_operand" "")))]
533   ""
534   "
535   if (GET_CODE (operands[1]) == CONST_INT)
536     {
537       arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
538                           operands[2],
539                           (reload_in_progress || reload_completed ? 0
540                            : preserve_subexpressions_p ()));
541       DONE;
542     }
545 (define_insn "*subsi3_insn"
546   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
547         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
548                   (match_operand:SI 2 "s_register_operand" "r,r")))]
549   ""
550   "@
551    rsb%?\\t%0, %2, %1
552    #"
553 [(set_attr "length" "4,16")])
555 (define_split
556   [(set (match_operand:SI 0 "s_register_operand" "")
557         (minus:SI (match_operand:SI 1 "const_int_operand" "")
558                   (match_operand:SI 2 "s_register_operand" "")))]
559   "! const_ok_for_arm (INTVAL (operands[1]))"
560   [(clobber (const_int 0))]
561   "
562   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
563                       operands[2], 0);
564   DONE;
567 (define_insn "*subsi3_compare0"
568   [(set (reg:CC_NOOV 24)
569         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
570                                  (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
571                          (const_int 0)))
572    (set (match_operand:SI 0 "s_register_operand" "=r,r")
573         (minus:SI (match_dup 1) (match_dup 2)))]
574   ""
575   "@
576    sub%?s\\t%0, %1, %2
577    rsb%?s\\t%0, %2, %1"
578 [(set_attr "conds" "set")])
580 (define_insn "decscc"
581   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
582         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
583                   (match_operator:SI 2 "comparison_operator"
584                    [(reg 24) (const_int 0)])))]
585   ""
586   "@
587   sub%d2\\t%0, %1, #1
588   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
589 [(set_attr "conds" "use")
590  (set_attr "length" "*,8")])
592 (define_insn "subsf3"
593   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
594         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
595                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
596   "TARGET_HARD_FLOAT"
597   "@
598    suf%?s\\t%0, %1, %2
599    rsf%?s\\t%0, %2, %1"
600 [(set_attr "type" "farith")])
602 (define_insn "subdf3"
603   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
604         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
605                   (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
606   "TARGET_HARD_FLOAT"
607   "@
608    suf%?d\\t%0, %1, %2
609    rsf%?d\\t%0, %2, %1"
610 [(set_attr "type" "farith")])
612 (define_insn "*subdf_esfdf_df"
613   [(set (match_operand:DF 0 "s_register_operand" "=f")
614         (minus:DF (float_extend:DF
615                    (match_operand:SF 1 "s_register_operand" "f"))
616                   (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
617   "TARGET_HARD_FLOAT"
618   "suf%?d\\t%0, %1, %2"
619 [(set_attr "type" "farith")])
621 (define_insn "*subdf_df_esfdf"
622   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
623         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
624                   (float_extend:DF
625                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
626   "TARGET_HARD_FLOAT"
627   "@
628    suf%?d\\t%0, %1, %2
629    rsf%?d\\t%0, %2, %1"
630 [(set_attr "type" "farith")])
632 (define_insn "*subdf_esfdf_esfdf"
633   [(set (match_operand:DF 0 "s_register_operand" "=f")
634         (minus:DF (float_extend:DF
635                    (match_operand:SF 1 "s_register_operand" "f"))
636                   (float_extend:DF
637                    (match_operand:SF 2 "s_register_operand" "f"))))]
638   "TARGET_HARD_FLOAT"
639   "suf%?d\\t%0, %1, %2"
640 [(set_attr "type" "farith")])
642 (define_insn "subxf3"
643   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
644         (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
645                   (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
646   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
647   "@
648    suf%?e\\t%0, %1, %2
649    rsf%?e\\t%0, %2, %1"
650 [(set_attr "type" "farith")])
652 ;; Multiplication insns
654 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
655 (define_insn "mulsi3"
656   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
657         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
658                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
659   ""
660   "mul%?\\t%0, %2, %1"
661 [(set_attr "type" "mult")])
663 (define_insn "*mulsi3_compare0"
664   [(set (reg:CC_NOOV 24)
665         (compare:CC_NOOV (mult:SI
666                           (match_operand:SI 2 "s_register_operand" "r,r")
667                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
668                          (const_int 0)))
669    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
670         (mult:SI (match_dup 2) (match_dup 1)))]
671   ""
672   "mul%?s\\t%0, %2, %1"
673 [(set_attr "conds" "set")
674  (set_attr "type" "mult")])
676 (define_insn "*mulsi_compare0_scratch"
677   [(set (reg:CC_NOOV 24)
678         (compare:CC_NOOV (mult:SI
679                           (match_operand:SI 2 "s_register_operand" "r,r")
680                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
681                          (const_int 0)))
682    (clobber (match_scratch:SI 0 "=&r,&r"))]
683   ""
684   "mul%?s\\t%0, %2, %1"
685 [(set_attr "conds" "set")
686  (set_attr "type" "mult")])
688 ;; Unnamed templates to match MLA instruction.
690 (define_insn "*mulsi3addsi"
691   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
692         (plus:SI
693           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
694                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
695           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
696   ""
697   "mla%?\\t%0, %2, %1, %3"
698 [(set_attr "type" "mult")])
700 (define_insn "*mulsi3addsi_compare0"
701   [(set (reg:CC_NOOV 24)
702         (compare:CC_NOOV (plus:SI
703                           (mult:SI
704                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
705                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
706                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
707                          (const_int 0)))
708    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
709         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
710                  (match_dup 3)))]
711   ""
712   "mla%?s\\t%0, %2, %1, %3"
713 [(set_attr "conds" "set")
714  (set_attr "type" "mult")])
716 (define_insn "*mulsi3addsi_compare0_scratch"
717   [(set (reg:CC_NOOV 24)
718         (compare:CC_NOOV (plus:SI
719                           (mult:SI
720                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
721                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
722                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
723                          (const_int 0)))
724    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
725   ""
726   "mla%?s\\t%0, %2, %1, %3"
727 [(set_attr "conds" "set")
728  (set_attr "type" "mult")])
730 (define_insn "mulsidi3"
731   [(set (match_operand:DI 0 "s_register_operand" "=&r")
732       (mult:DI (sign_extend:DI
733                 (match_operand:SI 1 "s_register_operand" "%r"))
734                (sign_extend:DI
735                (match_operand:SI 2 "s_register_operand" "r"))))]
736   "arm_fast_multiply"
737   "smull%?\\t%0, %R0, %1, %2"
738 [(set_attr "type" "mult")])
740 (define_insn "umulsidi3"
741   [(set (match_operand:DI 0 "s_register_operand" "=&r")
742       (mult:DI (zero_extend:DI
743                 (match_operand:SI 1 "s_register_operand" "%r"))
744                (zero_extend:DI
745                 (match_operand:SI 2 "s_register_operand" "r"))))]
746   "arm_fast_multiply"
747   "umull%?\\t%0, %R0, %1, %2"
748 [(set_attr "type" "mult")])
750 (define_insn "mulsf3"
751   [(set (match_operand:SF 0 "s_register_operand" "=f")
752         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
753                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
754   "TARGET_HARD_FLOAT"
755   "fml%?s\\t%0, %1, %2"
756 [(set_attr "type" "ffmul")])
758 (define_insn "muldf3"
759   [(set (match_operand:DF 0 "s_register_operand" "=f")
760         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
761                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
762   "TARGET_HARD_FLOAT"
763   "muf%?d\\t%0, %1, %2"
764 [(set_attr "type" "fmul")])
766 (define_insn "*muldf_esfdf_df"
767   [(set (match_operand:DF 0 "s_register_operand" "=f")
768         (mult:DF (float_extend:DF
769                   (match_operand:SF 1 "s_register_operand" "f"))
770                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
771   "TARGET_HARD_FLOAT"
772   "muf%?d\\t%0, %1, %2"
773 [(set_attr "type" "fmul")])
775 (define_insn "*muldf_df_esfdf"
776   [(set (match_operand:DF 0 "s_register_operand" "=f")
777         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
778                  (float_extend:DF
779                   (match_operand:SF 2 "s_register_operand" "f"))))]
780   "TARGET_HARD_FLOAT"
781   "muf%?d\\t%0, %1, %2"
782 [(set_attr "type" "fmul")])
784 (define_insn "*muldf_esfdf_esfdf"
785   [(set (match_operand:DF 0 "s_register_operand" "=f")
786         (mult:DF (float_extend:DF
787                   (match_operand:SF 1 "s_register_operand" "f"))
788                  (float_extend:DF
789                   (match_operand:SF 2 "s_register_operand" "f"))))]
790   "TARGET_HARD_FLOAT"
791   "muf%?d\\t%0, %1, %2"
792 [(set_attr "type" "fmul")])
794 (define_insn "mulxf3"
795   [(set (match_operand:XF 0 "s_register_operand" "=f")
796         (mult:XF (match_operand:XF 1 "s_register_operand" "f")
797                  (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
798   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
799   "muf%?e\\t%0, %1, %2"
800 [(set_attr "type" "fmul")])
802 ;; Division insns
804 (define_insn "divsf3"
805   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
806         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
807                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
808   "TARGET_HARD_FLOAT"
809   "@
810    fdv%?s\\t%0, %1, %2
811    frd%?s\\t%0, %2, %1"
812 [(set_attr "type" "fdivs")])
814 (define_insn "divdf3"
815   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
816         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
817                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
818   "TARGET_HARD_FLOAT"
819   "@
820    dvf%?d\\t%0, %1, %2
821    rdf%?d\\t%0, %2, %1"
822 [(set_attr "type" "fdivd")])
824 (define_insn "*divdf_esfdf_df"
825   [(set (match_operand:DF 0 "s_register_operand" "=f")
826         (div:DF (float_extend:DF
827                  (match_operand:SF 1 "s_register_operand" "f"))
828                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
829   "TARGET_HARD_FLOAT"
830   "dvf%?d\\t%0, %1, %2"
831 [(set_attr "type" "fdivd")])
833 (define_insn "*divdf_df_esfdf"
834   [(set (match_operand:DF 0 "s_register_operand" "=f")
835         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
836                 (float_extend:DF
837                  (match_operand:SF 2 "s_register_operand" "f"))))]
838   "TARGET_HARD_FLOAT"
839   "rdf%?d\\t%0, %2, %1"
840 [(set_attr "type" "fdivd")])
842 (define_insn "*divdf_esfdf_esfdf"
843   [(set (match_operand:DF 0 "s_register_operand" "=f")
844         (div:DF (float_extend:DF
845                  (match_operand:SF 1 "s_register_operand" "f"))
846                 (float_extend:DF
847                  (match_operand:SF 2 "s_register_operand" "f"))))]
848   "TARGET_HARD_FLOAT"
849   "dvf%?d\\t%0, %1, %2"
850 [(set_attr "type" "fdivd")])
852 (define_insn "divxf3"
853   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
854         (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
855                 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
856   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
857   "@
858    dvf%?e\\t%0, %1, %2
859    rdf%?e\\t%0, %2, %1"
860 [(set_attr "type" "fdivx")])
862 ;; Modulo insns
864 (define_insn "modsf3"
865   [(set (match_operand:SF 0 "s_register_operand" "=f")
866         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
867                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
868   "TARGET_HARD_FLOAT"
869   "rmf%?s\\t%0, %1, %2"
870 [(set_attr "type" "fdivs")])
872 (define_insn "moddf3"
873   [(set (match_operand:DF 0 "s_register_operand" "=f")
874         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
875                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
876   "TARGET_HARD_FLOAT"
877   "rmf%?d\\t%0, %1, %2"
878 [(set_attr "type" "fdivd")])
880 (define_insn "*moddf_esfdf_df"
881   [(set (match_operand:DF 0 "s_register_operand" "=f")
882         (mod:DF (float_extend:DF
883                  (match_operand:SF 1 "s_register_operand" "f"))
884                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
885   "TARGET_HARD_FLOAT"
886   "rmf%?d\\t%0, %1, %2"
887 [(set_attr "type" "fdivd")])
889 (define_insn "*moddf_df_esfdf"
890   [(set (match_operand:DF 0 "s_register_operand" "=f")
891         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
892                 (float_extend:DF
893                  (match_operand:SF 2 "s_register_operand" "f"))))]
894   "TARGET_HARD_FLOAT"
895   "rmf%?d\\t%0, %1, %2"
896 [(set_attr "type" "fdivd")])
898 (define_insn "*moddf_esfdf_esfdf"
899   [(set (match_operand:DF 0 "s_register_operand" "=f")
900         (mod:DF (float_extend:DF
901                  (match_operand:SF 1 "s_register_operand" "f"))
902                 (float_extend:DF
903                  (match_operand:SF 2 "s_register_operand" "f"))))]
904   "TARGET_HARD_FLOAT"
905   "rmf%?d\\t%0, %1, %2"
906 [(set_attr "type" "fdivd")])
908 (define_insn "modxf3"
909   [(set (match_operand:XF 0 "s_register_operand" "=f")
910         (mod:XF (match_operand:XF 1 "s_register_operand" "f")
911                 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
912   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
913   "rmf%?e\\t%0, %1, %2"
914 [(set_attr "type" "fdivx")])
916 ;; Boolean and,ior,xor insns
918 (define_insn "anddi3"
919   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
920         (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
921                 (match_operand:DI 2 "s_register_operand" "r,0")))]
922   ""
923   "and%?\\t%0, %1, %2\;and%?\\t%R0, %R1, %R2"
924 [(set_attr "length" "8")])
926 (define_insn "*anddi_zesidi_di"
927   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
928         (and:DI (zero_extend:DI
929                  (match_operand:SI 2 "s_register_operand" "r,r"))
930                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
931   ""
932   "and%?\\t%0, %1, %2\;mov%?\\t%R0, #0"
933 [(set_attr "length" "8")])
935 (define_insn "*anddi_sesdi_di"
936   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
937         (and:DI (sign_extend:DI
938                  (match_operand:SI 2 "s_register_operand" "r,r"))
939                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
940   ""
941   "and%?\\t%0, %1, %2\;and%?\\t%R0, %R1, %2, asr #31"
942 [(set_attr "length" "8")])
944 (define_expand "andsi3"
945   [(set (match_operand:SI 0 "s_register_operand" "")
946         (and:SI (match_operand:SI 1 "s_register_operand" "")
947                 (match_operand:SI 2 "reg_or_int_operand" "")))]
948   ""
949   "
950   if (GET_CODE (operands[2]) == CONST_INT)
951     {
952       arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
953                           operands[1],
954                           (reload_in_progress || reload_completed
955                            ? 0 : preserve_subexpressions_p ()));
956       DONE;
957     }
960 (define_insn "*andsi3_insn"
961   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
962         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
963                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
964   ""
965   "@
966    and%?\\t%0, %1, %2
967    bic%?\\t%0, %1, #%B2
968    #"
969 [(set_attr "length" "4,4,16")])
971 (define_split
972   [(set (match_operand:SI 0 "s_register_operand" "")
973         (and:SI (match_operand:SI 1 "s_register_operand" "")
974                 (match_operand:SI 2 "const_int_operand" "")))]
975   "! (const_ok_for_arm (INTVAL (operands[2]))
976       || const_ok_for_arm (~ INTVAL (operands[2])))"
977   [(clobber (const_int 0))]
978   "
979   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
980                        operands[1], 0);
981   DONE;
984 (define_insn "*andsi3_compare0"
985   [(set (reg:CC_NOOV 24)
986         (compare:CC_NOOV
987          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
988                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
989          (const_int 0)))
990    (set (match_operand:SI 0 "s_register_operand" "=r,r")
991         (and:SI (match_dup 1) (match_dup 2)))]
992   ""
993   "@
994    and%?s\\t%0, %1, %2
995    bic%?s\\t%0, %1, #%B2"
996 [(set_attr "conds" "set")])
998 (define_insn "*andsi3_compare0_scratch"
999   [(set (reg:CC_NOOV 24)
1000         (compare:CC_NOOV
1001          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1002                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1003          (const_int 0)))
1004    (clobber (match_scratch:SI 3 "=X,r"))]
1005   ""
1006   "@
1007    tst%?\\t%0, %1
1008    bic%?s\\t%3, %0, #%B1"
1009 [(set_attr "conds" "set")])
1011 (define_insn "*zeroextractsi_compare0_scratch"
1012   [(set (reg:CC_NOOV 24)
1013         (compare:CC_NOOV (zero_extract:SI
1014                           (match_operand:SI 0 "s_register_operand" "r")
1015                           (match_operand:SI 1 "immediate_operand" "n")
1016                           (match_operand:SI 2 "immediate_operand" "n"))
1017                          (const_int 0)))]
1018   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1019    && INTVAL (operands[1]) > 0 
1020    && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1021    && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1022   "*
1024   unsigned int mask = 0;
1025   int cnt = INTVAL (operands[1]);
1026   
1027   while (cnt--)
1028     mask = (mask << 1) | 1;
1029   operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1030   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1031   return \"\";
1034 [(set_attr "conds" "set")])
1036 (define_insn "*zeroextractqi_compare0_scratch"
1037   [(set (reg:CC_NOOV 24)
1038         (compare:CC_NOOV (zero_extract:SI
1039                           (match_operand:QI 0 "memory_operand" "m")
1040                           (match_operand 1 "immediate_operand" "n")
1041                           (match_operand 2 "immediate_operand" "n"))
1042                          (const_int 0)))
1043    (clobber (match_scratch:QI 3 "=r"))]
1044   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 8
1045    && INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8"
1046   "*
1048   unsigned int mask = 0;
1049   int cnt = INTVAL (operands[1]);
1050   
1051   while (cnt--)
1052     mask = (mask << 1) | 1;
1053   operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1054   output_asm_insn (\"ldr%?b\\t%3, %0\", operands);
1055   output_asm_insn (\"tst%?\\t%3, %1\", operands);
1056   return \"\";
1059 [(set_attr "conds" "set")
1060  (set_attr "length" "8")])
1062 ;; constants for op 2 will never be given to these patterns.
1063 (define_insn "*anddi_notdi_di"
1064   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1065         (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1066                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1067   ""
1068   "bic%?\\t%0, %1, %2\;bic%?\\t%R0, %R1, %R2"
1069 [(set_attr "length" "8")])
1070   
1071 (define_insn "*anddi_notzesidi_di"
1072   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1073         (and:DI (not:DI (zero_extend:DI
1074                          (match_operand:SI 2 "s_register_operand" "r,r")))
1075                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1076   ""
1077   "@
1078    bic%?\\t%0, %1, %2
1079    bic%?\\t%0, %1, %2\;mov%?\\t%R0, %R1"
1080 [(set_attr "length" "4,8")])
1081   
1082 (define_insn "*anddi_notsesidi_di"
1083   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1084         (and:DI (not:DI (sign_extend:DI
1085                          (match_operand:SI 2 "s_register_operand" "r,r")))
1086                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1087   ""
1088   "bic%?\\t%0, %1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
1089 [(set_attr "length" "8")])
1090   
1091 (define_insn "*andsi_notsi_si"
1092   [(set (match_operand:SI 0 "s_register_operand" "=r")
1093         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1094                 (match_operand:SI 1 "s_register_operand" "r")))]
1095   ""
1096   "bic%?\\t%0, %1, %2")
1098 (define_insn "*andsi_notsi_si_compare0"
1099   [(set (reg:CC_NOOV 24)
1100         (compare:CC_NOOV
1101          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1102                  (match_operand:SI 1 "s_register_operand" "r"))
1103          (const_int 0)))
1104    (set (match_operand:SI 0 "s_register_operand" "=r")
1105         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1106   ""
1107   "bic%?s\\t%0, %1, %2"
1108 [(set_attr "conds" "set")])
1110 (define_insn "*andsi_notsi_si_compare0_scratch"
1111   [(set (reg:CC_NOOV 24)
1112         (compare:CC_NOOV
1113          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1114                  (match_operand:SI 1 "s_register_operand" "r"))
1115          (const_int 0)))
1116    (clobber (match_scratch:SI 0 "=r"))]
1117   ""
1118   "bic%?s\\t%0, %1, %2"
1119 [(set_attr "conds" "set")])
1121 (define_insn "iordi3"
1122   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1123         (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1124                 (match_operand:DI 2 "s_register_operand" "r")))]
1125   ""
1126   "orr%?\\t%0, %1, %2\;orr%?\\t%R0, %R1, %R2"
1127 [(set_attr "length" "8")])
1129 (define_insn "*iordi_zesidi_di"
1130   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1131         (ior:DI (zero_extend:DI
1132                  (match_operand:SI 2 "s_register_operand" "r,r"))
1133                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1134   ""
1135   "@
1136    orr%?\\t%0, %1, %2
1137    orr%?\\t%0, %1, %2\;mov%?\\t%R0, %R1"
1138 [(set_attr "length" "4,8")])
1140 (define_insn "*iordi_sesidi_di"
1141   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1142         (ior:DI (sign_extend:DI
1143                  (match_operand:SI 2 "s_register_operand" "r,r"))
1144                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1145   ""
1146   "orr%?\\t%0, %1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1147 [(set_attr "length" "8")])
1149 (define_expand "iorsi3"
1150   [(set (match_operand:SI 0 "s_register_operand" "")
1151         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1152                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1153   ""
1154   "
1155   if (GET_CODE (operands[2]) == CONST_INT)
1156     {
1157       arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1158                           operands[1],
1159                           (reload_in_progress || reload_completed
1160                            ? 0 : preserve_subexpressions_p ()));
1161       DONE;
1162     }
1165 (define_insn "*iorsi3_insn"
1166   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1167         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1168                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1169   ""
1170   "@
1171    orr%?\\t%0, %1, %2
1172    #"
1173 [(set_attr "length" "4,16")])
1175 (define_split
1176   [(set (match_operand:SI 0 "s_register_operand" "")
1177         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1178                 (match_operand:SI 2 "const_int_operand" "")))]
1179   "! const_ok_for_arm (INTVAL (operands[2]))"
1180   [(clobber (const_int 0))]
1181   "
1182   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1183                       operands[1], 0);
1184   DONE;
1186   
1187 (define_insn "*iorsi3_compare0"
1188   [(set (reg:CC_NOOV 24)
1189         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1190                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1191                          (const_int 0)))
1192    (set (match_operand:SI 0 "s_register_operand" "=r")
1193         (ior:SI (match_dup 1) (match_dup 2)))]
1194   ""
1195   "orr%?s\\t%0, %1, %2"
1196 [(set_attr "conds" "set")])
1198 (define_insn "*iorsi3_compare0_scratch"
1199   [(set (reg:CC_NOOV 24)
1200         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1201                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1202                          (const_int 0)))
1203    (clobber (match_scratch:SI 0 "=r"))]
1204   ""
1205   "orr%?s\\t%0, %1, %2"
1206 [(set_attr "conds" "set")])
1208 (define_insn "xordi3"
1209   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1210         (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1211                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1212   ""
1213   "eor%?\\t%0, %1, %2\;eor%?\\t%R0, %R1, %R2"
1214 [(set_attr "length" "8")])
1216 (define_insn "*xordi_zesidi_di"
1217   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1218         (xor:DI (zero_extend:DI
1219                  (match_operand:SI 2 "s_register_operand" "r,r"))
1220                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1221   ""
1222   "@
1223    eor%?\\t%0, %1, %2
1224    eor%?\\t%0, %1, %2\;mov%?\\t%R0, %R1"
1225 [(set_attr "length" "4,8")])
1227 (define_insn "*xordi_sesidi_di"
1228   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1229         (xor:DI (sign_extend:DI
1230                  (match_operand:SI 2 "s_register_operand" "r,r"))
1231                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1232   ""
1233   "eor%?\\t%0, %1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1234 [(set_attr "length" "8")])
1236 (define_insn "xorsi3"
1237   [(set (match_operand:SI 0 "s_register_operand" "=r")
1238         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1239                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1240   ""
1241   "eor%?\\t%0, %1, %2")
1243 (define_insn "*xorsi3_compare0"
1244   [(set (reg:CC_NOOV 24)
1245         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1246                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1247                          (const_int 0)))
1248    (set (match_operand:SI 0 "s_register_operand" "=r")
1249         (xor:SI (match_dup 1) (match_dup 2)))]
1250   ""
1251   "eor%?s\\t%0, %1, %2"
1252 [(set_attr "conds" "set")])
1254 (define_insn "*xorsi3_compare0_scratch"
1255   [(set (reg:CC_NOOV 24)
1256         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1257                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
1258                          (const_int 0)))]
1259   ""
1260   "teq%?\\t%0, %1"
1261 [(set_attr "conds" "set")])
1263 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
1264 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1265 ;; insns
1267 (define_split
1268   [(set (match_operand:SI 0 "s_register_operand" "=r")
1269         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1270                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1271                 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1272    (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1273   ""
1274   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1275                               (not:SI (match_dup 3))))
1276    (set (match_dup 0) (not:SI (match_dup 4)))]
1277   ""
1280 (define_insn "*andsi_iorsi3_notsi"
1281   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1282         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1283                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1284                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1285   ""
1286   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1287 [(set_attr "length" "8")])
1291 ;; Minimum and maximum insns
1293 (define_insn "smaxsi3"
1294   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1295         (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1296                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1297    (clobber (reg:CC 24))]
1298   ""
1299   "@
1300    cmp\\t%1, %2\;movlt\\t%0, %2
1301    cmp\\t%1, %2\;movge\\t%0, %1
1302    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1303 [(set_attr "conds" "clob")
1304  (set_attr "length" "8,8,12")])
1306 (define_insn "sminsi3"
1307   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1308         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1309                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1310    (clobber (reg:CC 24))]
1311   ""
1312   "@
1313    cmp\\t%1, %2\;movge\\t%0, %2
1314    cmp\\t%1, %2\;movlt\\t%0, %1
1315    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1316 [(set_attr "conds" "clob")
1317  (set_attr "length" "8,8,12")])
1319 (define_insn "umaxsi3"
1320   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1321         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1322                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1323    (clobber (reg:CC 24))]
1324   ""
1325   "@
1326    cmp\\t%1, %2\;movcc\\t%0, %2
1327    cmp\\t%1, %2\;movcs\\t%0, %1
1328    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1329 [(set_attr "conds" "clob")
1330  (set_attr "length" "8,8,12")])
1332 (define_insn "uminsi3"
1333   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1334         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1335                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1336    (clobber (reg:CC 24))]
1337   ""
1338   "@
1339    cmp\\t%1, %2\;movcs\\t%0, %2
1340    cmp\\t%1, %2\;movcc\\t%0, %1
1341    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1342 [(set_attr "conds" "clob")
1343  (set_attr "length" "8,8,12")])
1345 (define_insn "*store_minmansi"
1346   [(set (match_operand:SI 0 "memory_operand" "=m")
1347         (match_operator:SI 3 "minmax_operator"
1348          [(match_operand:SI 1 "s_register_operand" "r")
1349           (match_operand:SI 2 "s_register_operand" "r")]))
1350    (clobber (reg:CC 24))]
1351   ""
1352   "*
1353   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1354                          operands[2]);
1355   output_asm_insn (\"cmp\\t%1, %2\", operands);
1356   output_asm_insn (\"str%d3\\t%1, %0\", operands);
1357   output_asm_insn (\"str%D3\\t%2, %0\", operands);
1358   return \"\";
1360 [(set_attr "conds" "clob")
1361  (set_attr "length" "12")
1362  (set_attr "type" "store1")])
1364 (define_insn "*minmax_arithsi"
1365   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1366         (match_operator:SI 4 "shiftable_operator"
1367          [(match_operator:SI 5 "minmax_operator"
1368            [(match_operand:SI 2 "s_register_operand" "r,r")
1369             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1370           (match_operand:SI 1 "s_register_operand" "0,?r")]))
1371    (clobber (reg:CC 24))]
1372   ""
1373   "*
1375   enum rtx_code code = GET_CODE (operands[4]);
1377   operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1378                          operands[3]);
1379   output_asm_insn (\"cmp\\t%2, %3\", operands);
1380   output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1381   if (which_alternative != 0 || operands[3] != const0_rtx
1382       || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1383     output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1384   return \"\";
1387 [(set_attr "conds" "clob")
1388  (set_attr "length" "12")])
1391 ;; Shift and rotation insns
1393 (define_expand "ashlsi3"
1394   [(set (match_operand:SI 0 "s_register_operand" "")
1395         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
1396                    (match_operand:SI 2 "arm_rhs_operand" "")))]
1397   ""
1398   "
1399   if (GET_CODE (operands[2]) == CONST_INT
1400       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1401     {
1402       emit_insn (gen_movsi (operands[0], const0_rtx));
1403       DONE;
1404     }
1407 (define_expand "ashrsi3"
1408   [(set (match_operand:SI 0 "s_register_operand" "")
1409         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1410                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1411   ""
1412   "
1413   if (GET_CODE (operands[2]) == CONST_INT
1414       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1415     operands[2] = GEN_INT (31);
1418 (define_expand "lshrsi3"
1419   [(set (match_operand:SI 0 "s_register_operand" "")
1420         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1421                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1422   ""
1423   "
1424   if (GET_CODE (operands[2]) == CONST_INT
1425       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1426     {
1427       emit_insn (gen_movsi (operands[0], const0_rtx));
1428       DONE;
1429     }
1432 (define_expand "rotlsi3"
1433   [(set (match_operand:SI 0 "s_register_operand" "")
1434         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1435                      (match_operand:SI 2 "reg_or_int_operand" "")))]
1436   ""
1437   "
1438   if (GET_CODE (operands[2]) == CONST_INT)
1439     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1440   else
1441     {
1442       rtx reg = gen_reg_rtx (SImode);
1443       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1444       operands[2] = reg;
1445     }
1448 (define_expand "rotrsi3"
1449   [(set (match_operand:SI 0 "s_register_operand" "")
1450         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1451                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1452   ""
1453   "
1454   if (GET_CODE (operands[2]) == CONST_INT
1455       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1456     operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1459 (define_insn "*shiftsi3"
1460   [(set (match_operand:SI 0 "s_register_operand" "=r")
1461         (match_operator:SI 3 "shift_operator"
1462          [(match_operand:SI 1 "s_register_operand" "r")
1463           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1464   ""
1465   "mov%?\\t%0, %1%S3")
1467 (define_insn "*shiftsi3_compare0"
1468   [(set (reg:CC_NOOV 24)
1469         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1470                           [(match_operand:SI 1 "s_register_operand" "r")
1471                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1472                          (const_int 0)))
1473    (set (match_operand:SI 0 "s_register_operand" "=r")
1474         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1475   ""
1476   "mov%?s\\t%0, %1%S3"
1477 [(set_attr "conds" "set")])
1479 (define_insn "*shiftsi3_compare0_scratch"
1480   [(set (reg:CC_NOOV 24)
1481         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1482                           [(match_operand:SI 1 "s_register_operand" "r")
1483                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1484                          (const_int 0)))
1485    (clobber (match_scratch:SI 0 "=r"))]
1486   ""
1487   "mov%?s\\t%0, %1%S3"
1488 [(set_attr "conds" "set")])
1490 (define_insn "*notsi_shiftsi"
1491   [(set (match_operand:SI 0 "s_register_operand" "=r")
1492         (not:SI (match_operator:SI 3 "shift_operator"
1493                  [(match_operand:SI 1 "s_register_operand" "r")
1494                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1495   ""
1496   "mvn%?\\t%0, %1%S3")
1498 (define_insn "*notsi_shiftsi_compare0"
1499   [(set (reg:CC_NOOV 24)
1500         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1501                           [(match_operand:SI 1 "s_register_operand" "r")
1502                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1503                          (const_int 0)))
1504    (set (match_operand:SI 0 "s_register_operand" "=r")
1505         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1506   ""
1507   "mvn%?s\\t%0, %1%S3"
1508 [(set_attr "conds" "set")])
1510 (define_insn "*not_shiftsi_compare0_scratch"
1511   [(set (reg:CC_NOOV 24)
1512         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1513                           [(match_operand:SI 1 "s_register_operand" "r")
1514                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1515                          (const_int 0)))
1516    (clobber (match_scratch:SI 0 "=r"))]
1517   ""
1518   "mvn%?s\\t%0, %1%S3"
1519 [(set_attr "conds" "set")])
1522 ;; Unary arithmetic insns
1524 (define_insn "negdi2"
1525   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1526         (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1527   ""
1528   "rsbs\\t%0, %1, #0\;rsc\\t%R0, %R1, #0"
1529 [(set_attr "conds" "clob")
1530  (set_attr "length" "8")])
1532 (define_insn "negsi2"
1533   [(set (match_operand:SI 0 "s_register_operand" "=r")
1534         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1535   ""
1536   "rsb%?\\t%0, %1, #0")
1538 (define_insn "negsf2"
1539   [(set (match_operand:SF 0 "s_register_operand" "=f")
1540         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1541   "TARGET_HARD_FLOAT"
1542   "mnf%?s\\t%0, %1"
1543 [(set_attr "type" "ffarith")])
1545 (define_insn "negdf2"
1546   [(set (match_operand:DF 0 "s_register_operand" "=f")
1547         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1548   "TARGET_HARD_FLOAT"
1549   "mnf%?d\\t%0, %1"
1550 [(set_attr "type" "ffarith")])
1552 (define_insn "*negdf_esfdf"
1553   [(set (match_operand:DF 0 "s_register_operand" "=f")
1554         (neg:DF (float_extend:DF
1555                  (match_operand:SF 1 "s_register_operand" "f"))))]
1556   "TARGET_HARD_FLOAT"
1557   "mnf%?d\\t%0, %1"
1558 [(set_attr "type" "ffarith")])
1560 (define_insn "negxf2"
1561   [(set (match_operand:XF 0 "s_register_operand" "=f")
1562         (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1563   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1564   "mnf%?e\\t%0, %1"
1565 [(set_attr "type" "ffarith")])
1567 ;; abssi2 doesn't really clobber the condition codes if a different register
1568 ;; is being set.  To keep things simple, assume during rtl manipulations that
1569 ;; it does, but tell the final scan operator the truth.  Similarly for
1570 ;; (neg (abs...))
1572 (define_insn "abssi2"
1573   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1574         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1575    (clobber (reg 24))]
1576   ""
1577   "@
1578    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1579    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1580 [(set_attr "conds" "clob,*")
1581  (set_attr "length" "8")])
1583 (define_insn "*neg_abssi2"
1584   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1585         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1586    (clobber (reg 24))]
1587   ""
1588   "@
1589    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1590    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1591 [(set_attr "conds" "clob,*")
1592  (set_attr "length" "8")])
1594 (define_insn "abssf2"
1595   [(set (match_operand:SF 0 "s_register_operand" "=f")
1596          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1597   "TARGET_HARD_FLOAT"
1598   "abs%?s\\t%0, %1"
1599 [(set_attr "type" "ffarith")])
1601 (define_insn "absdf2"
1602   [(set (match_operand:DF 0 "s_register_operand" "=f")
1603         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1604   "TARGET_HARD_FLOAT"
1605   "abs%?d\\t%0, %1"
1606 [(set_attr "type" "ffarith")])
1608 (define_insn "*absdf_esfdf"
1609   [(set (match_operand:DF 0 "s_register_operand" "=f")
1610         (abs:DF (float_extend:DF
1611                  (match_operand:SF 1 "s_register_operand" "f"))))]
1612   "TARGET_HARD_FLOAT"
1613   "abs%?d\\t%0, %1"
1614 [(set_attr "type" "ffarith")])
1616 (define_insn "absxf2"
1617   [(set (match_operand:XF 0 "s_register_operand" "=f")
1618         (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1619   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1620   "abs%?e\\t%0, %1"
1621 [(set_attr "type" "ffarith")])
1623 (define_insn "sqrtsf2"
1624   [(set (match_operand:SF 0 "s_register_operand" "=f")
1625         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1626   "TARGET_HARD_FLOAT"
1627   "sqt%?s\\t%0, %1"
1628 [(set_attr "type" "float_em")])
1630 (define_insn "sqrtdf2"
1631   [(set (match_operand:DF 0 "s_register_operand" "=f")
1632         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1633   "TARGET_HARD_FLOAT"
1634   "sqt%?d\\t%0, %1"
1635 [(set_attr "type" "float_em")])
1637 (define_insn "*sqrtdf_esfdf"
1638   [(set (match_operand:DF 0 "s_register_operand" "=f")
1639         (sqrt:DF (float_extend:DF
1640                   (match_operand:SF 1 "s_register_operand" "f"))))]
1641   "TARGET_HARD_FLOAT"
1642   "sqt%?d\\t%0, %1"
1643 [(set_attr "type" "float_em")])
1645 (define_insn "sqrtxf2"
1646   [(set (match_operand:XF 0 "s_register_operand" "=f")
1647         (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1648   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1649   "sqt%?e\\t%0, %1"
1650 [(set_attr "type" "float_em")])
1652 (define_insn "sinsf2"
1653   [(set (match_operand:SF 0 "s_register_operand" "=f")
1654         (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1655   "TARGET_HARD_FLOAT"
1656   "sin%?s\\t%0, %1"
1657 [(set_attr "type" "float_em")])
1659 (define_insn "sindf2"
1660   [(set (match_operand:DF 0 "s_register_operand" "=f")
1661         (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1662   "TARGET_HARD_FLOAT"
1663   "sin%?d\\t%0, %1"
1664 [(set_attr "type" "float_em")])
1666 (define_insn "*sindf_esfdf"
1667   [(set (match_operand:DF 0 "s_register_operand" "=f")
1668         (unspec:DF [(float_extend:DF
1669                      (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1670   "TARGET_HARD_FLOAT"
1671   "sin%?d\\t%0, %1"
1672 [(set_attr "type" "float_em")])
1674 (define_insn "sinxf2"
1675   [(set (match_operand:XF 0 "s_register_operand" "=f")
1676         (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1677   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1678   "sin%?e\\t%0, %1"
1679 [(set_attr "type" "float_em")])
1681 (define_insn "cossf2"
1682   [(set (match_operand:SF 0 "s_register_operand" "=f")
1683         (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
1684   "TARGET_HARD_FLOAT"
1685   "cos%?s\\t%0, %1"
1686 [(set_attr "type" "float_em")])
1688 (define_insn "cosdf2"
1689   [(set (match_operand:DF 0 "s_register_operand" "=f")
1690         (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
1691   "TARGET_HARD_FLOAT"
1692   "cos%?d\\t%0, %1"
1693 [(set_attr "type" "float_em")])
1695 (define_insn "*cosdf_esfdf"
1696   [(set (match_operand:DF 0 "s_register_operand" "=f")
1697         (unspec:DF [(float_extend:DF
1698                      (match_operand:SF 1 "s_register_operand" "f"))] 1))]
1699   "TARGET_HARD_FLOAT"
1700   "cos%?d\\t%0, %1"
1701 [(set_attr "type" "float_em")])
1703 (define_insn "cosxf2"
1704   [(set (match_operand:XF 0 "s_register_operand" "=f")
1705         (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
1706   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1707   "cos%?e\\t%0, %1"
1708 [(set_attr "type" "float_em")])
1710 (define_insn "one_cmpldi2"
1711   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1712         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1713   ""
1714   "mvn%?\\t%0, %1\;mvn%?\\t%R0, %R1"
1715 [(set_attr "length" "8")])
1717 (define_insn "one_cmplsi2"
1718   [(set (match_operand:SI 0 "s_register_operand" "=r")
1719         (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
1720   ""
1721   "mvn%?\\t%0, %1")
1723 (define_insn "*notsi_compare0"
1724   [(set (reg:CC_NOOV 24)
1725         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1726                          (const_int 0)))
1727    (set (match_operand:SI 0 "s_register_operand" "=r")
1728         (not:SI (match_dup 1)))]
1729   ""
1730   "mvn%?s\\t%0, %1"
1731 [(set_attr "conds" "set")])
1733 (define_insn "*notsi_compare0_scratch"
1734   [(set (reg:CC_NOOV 24)
1735         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1736                          (const_int 0)))
1737    (clobber (match_scratch:SI 0 "=r"))]
1738   ""
1739   "mvn%?s\\t%0, %1"
1740 [(set_attr "conds" "set")])
1742 ;; Fixed <--> Floating conversion insns
1744 (define_insn "floatsisf2"
1745   [(set (match_operand:SF 0 "s_register_operand" "=f")
1746         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
1747   "TARGET_HARD_FLOAT"
1748   "flt%?s\\t%0, %1"
1749 [(set_attr "type" "r_2_f")])
1751 (define_insn "floatsidf2"
1752   [(set (match_operand:DF 0 "s_register_operand" "=f")
1753         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
1754   "TARGET_HARD_FLOAT"
1755   "flt%?d\\t%0, %1"
1756 [(set_attr "type" "r_2_f")])
1758 (define_insn "floatsixf2"
1759   [(set (match_operand:XF 0 "s_register_operand" "=f")
1760         (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
1761   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1762   "flt%?e\\t%0, %1"
1763 [(set_attr "type" "r_2_f")])
1765 (define_insn "fix_truncsfsi2"
1766   [(set (match_operand:SI 0 "s_register_operand" "=r")
1767         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
1768   "TARGET_HARD_FLOAT"
1769   "fix%?z\\t%0, %1"
1770 [(set_attr "type" "f_2_r")])
1772 (define_insn "fix_truncdfsi2"
1773   [(set (match_operand:SI 0 "s_register_operand" "=r")
1774         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
1775   "TARGET_HARD_FLOAT"
1776   "fix%?z\\t%0, %1"
1777 [(set_attr "type" "f_2_r")])
1779 (define_insn "fix_truncxfsi2"
1780   [(set (match_operand:SI 0 "s_register_operand" "=r")
1781         (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
1782   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1783   "fix%?z\\t%0, %1"
1784 [(set_attr "type" "f_2_r")])
1786 ;; Truncation insns
1788 (define_insn "truncdfsf2"
1789   [(set (match_operand:SF 0 "s_register_operand" "=f")
1790         (float_truncate:SF
1791          (match_operand:DF 1 "s_register_operand" "f")))]
1792   "TARGET_HARD_FLOAT"
1793   "mvf%?s\\t%0, %1"
1794 [(set_attr "type" "ffarith")])
1796 (define_insn "truncxfsf2"
1797   [(set (match_operand:SF 0 "s_register_operand" "=f")
1798         (float_truncate:SF
1799          (match_operand:XF 1 "s_register_operand" "f")))]
1800   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1801   "mvf%?s\\t%0, %1"
1802 [(set_attr "type" "ffarith")])
1804 (define_insn "truncxfdf2"
1805   [(set (match_operand:DF 0 "s_register_operand" "=f")
1806         (float_truncate:DF
1807          (match_operand:XF 1 "s_register_operand" "f")))]
1808   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1809   "mvf%?d\\t%0, %1"
1810 [(set_attr "type" "ffarith")])
1812 ;; Zero and sign extension instructions.
1814 (define_insn "zero_extendsidi2"
1815   [(set (match_operand:DI 0 "s_register_operand" "=r")
1816         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
1817   ""
1818   "*
1819   if (REGNO (operands[1]) != REGNO (operands[0]))
1820     output_asm_insn (\"mov%?\\t%0, %1\", operands);
1821   return \"mov%?\\t%R0, #0\";
1823 [(set_attr "length" "8")])
1825 (define_insn "zero_extendqidi2"
1826   [(set (match_operand:DI 0 "s_register_operand" "=r,r")
1827         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1828   ""
1829   "@
1830    and%?\\t%0, %1, #255\;mov%?\\t%R0, #0
1831    ldr%?b\\t%0, %1\;mov%?\\t%R0, #0"
1832 [(set_attr "length" "8")
1833  (set_attr "type" "*,load")])
1835 (define_insn "extendsidi2"
1836   [(set (match_operand:DI 0 "s_register_operand" "=r")
1837         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
1838   ""
1839   "*
1840   if (REGNO (operands[1]) != REGNO (operands[0]))
1841     output_asm_insn (\"mov%?\\t%0, %1\", operands);
1842   return \"mov%?\\t%R0, %0, asr #31\";
1844 [(set_attr "length" "8")])
1846 (define_expand "zero_extendhisi2"
1847   [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
1848                                  (const_int 16)))
1849    (set (match_operand:SI 0 "s_register_operand" "")
1850         (lshiftrt:SI (match_dup 2) (const_int 16)))]
1851   ""
1852   "
1854   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
1855     {
1856       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1857                           gen_rtx (ZERO_EXTEND, SImode, operands[1])));
1858       DONE;
1859     }
1860   if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
1861     {
1862       emit_insn (gen_movhi_bytes (operands[0], operands[1]));
1863       DONE;
1864     }
1865   if (! s_register_operand (operands[1], HImode))
1866     operands[1] = copy_to_mode_reg (HImode, operands[1]);
1867   operands[1] = gen_lowpart (SImode, operands[1]);
1868   operands[2] = gen_reg_rtx (SImode); 
1871 (define_insn "*zero_extendhisi_insn"
1872   [(set (match_operand:SI 0 "s_register_operand" "=r")
1873         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1874   "arm_arch4"
1875   "ldr%?h\\t%0, %1"
1876 [(set_attr "type" "load")])
1878 (define_expand "zero_extendqisi2"
1879   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1880         (zero_extend:SI
1881          (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1882   ""
1883   "
1884   if (GET_CODE (operands[1]) != MEM)
1885     {
1886       emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
1887                              GEN_INT (255)));
1888       DONE;
1889     }
1892 (define_insn "*load_extendqisi"
1893   [(set (match_operand:SI 0 "s_register_operand" "=r")
1894         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
1895   ""
1896   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
1897 [(set_attr "type" "load")])
1899 (define_split
1900   [(set (match_operand:SI 0 "s_register_operand" "")
1901         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
1902    (clobber (match_operand:SI 2 "s_register_operand" ""))]
1903   "GET_CODE (operands[1]) != MEM"
1904   [(set (match_dup 2) (match_dup 1))
1905    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
1906   "")
1908 (define_insn "*compareqi_eq0"
1909   [(set (reg:CC_NOOV 24)
1910         (compare:CC_NOOV (match_operand:QI 0 "s_register_operand" "r")
1911                          (const_int 0)))]
1912   ""
1913   "tst\\t%0, #255"
1914 [(set_attr "conds" "set")])
1916 (define_expand "extendhisi2"
1917   [(set (match_dup 2)
1918         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
1919                    (const_int 16)))
1920    (set (match_operand:SI 0 "s_register_operand" "")
1921         (ashiftrt:SI (match_dup 2)
1922                      (const_int 16)))]
1923   ""
1924   "
1926   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
1927     {
1928       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1929                  gen_rtx (SIGN_EXTEND, SImode, operands[1])));
1930       DONE;
1931     }
1933   if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
1934     {
1935       emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
1936       DONE;
1937     }
1938   if (! s_register_operand (operands[1], HImode))
1939     operands[1] = copy_to_mode_reg (HImode, operands[1]);
1940   operands[1] = gen_lowpart (SImode, operands[1]);
1941   operands[2] = gen_reg_rtx (SImode);
1944 (define_expand "extendhisi2_mem"
1945   [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" ""))))
1946    (set (match_dup 3)
1947         (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
1948    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
1949    (set (match_operand:SI 0 "" "")
1950         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
1951   ""
1952   "
1953   operands[0] = gen_lowpart (SImode, operands[0]);
1954   operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
1955   operands[2] = gen_reg_rtx (SImode);
1956   operands[3] = gen_reg_rtx (SImode);
1957   operands[6] = gen_reg_rtx (SImode);
1959   if (BYTES_BIG_ENDIAN)
1960     {
1961       operands[4] = operands[2];
1962       operands[5] = operands[3];
1963     }
1964   else
1965     {
1966       operands[4] = operands[3];
1967       operands[5] = operands[2];
1968     }
1971 (define_insn "*extendhisi_insn"
1972   [(set (match_operand:SI 0 "s_register_operand" "=r")
1973         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1974   "arm_arch4"
1975   "ldr%?sh\\t%0, %1"
1976 [(set_attr "type" "load")])
1978 (define_expand "extendqihi2"
1979   [(set (match_dup 2)
1980         (ashift:SI (match_operand:QI 1 "general_operand" "")
1981                    (const_int 24)))
1982    (set (match_operand:HI 0 "s_register_operand" "")
1983         (ashiftrt:SI (match_dup 2)
1984                      (const_int 24)))]
1985   ""
1986   "
1988   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
1989     {
1990       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1991                           gen_rtx (SIGN_EXTEND, HImode, operands[1])));
1992       DONE;
1993     }
1994   if (! s_register_operand (operands[1], QImode))
1995     operands[1] = copy_to_mode_reg (QImode, operands[1]);
1996   operands[0] = gen_lowpart (SImode, operands[0]);
1997   operands[1] = gen_lowpart (SImode, operands[1]);
1998   operands[2] = gen_reg_rtx (SImode);
2001 (define_insn "*extendqihi_insn"
2002   [(set (match_operand:HI 0 "s_register_operand" "=r")
2003         (sign_extend:HI (match_operand:QI 1 "memory_operand" "o<>")))]
2004   "arm_arch4"
2005   "ldr%?sb\\t%0, %1"
2006 [(set_attr "type" "load")])
2008 (define_expand "extendqisi2"
2009   [(set (match_dup 2)
2010         (ashift:SI (match_operand:QI 1 "s_register_operand" "")
2011                    (const_int 24)))
2012    (set (match_operand:SI 0 "s_register_operand" "")
2013         (ashiftrt:SI (match_dup 2)
2014                      (const_int 24)))]
2015   ""
2016   "
2018   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2019     {
2020       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2021                           gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2022       DONE;
2023     }
2024   if (! s_register_operand (operands[1], QImode))
2025     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2026   operands[1] = gen_lowpart (SImode, operands[1]);
2027   operands[2] = gen_reg_rtx (SImode);
2030 (define_insn "*extendqisi_insn"
2031   [(set (match_operand:SI 0 "s_register_operand" "=r")
2032         (sign_extend:SI (match_operand:QI 1 "memory_operand" "o<>")))]
2033   "arm_arch4"
2034   "ldr%?sb\\t%0, %1"
2035 [(set_attr "type" "load")])
2037 (define_insn "extendsfdf2"
2038   [(set (match_operand:DF 0 "s_register_operand" "=f")
2039         (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2040   "TARGET_HARD_FLOAT"
2041   "mvf%?d\\t%0, %1"
2042 [(set_attr "type" "ffarith")])
2044 (define_insn "extendsfxf2"
2045   [(set (match_operand:XF 0 "s_register_operand" "=f")
2046         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2047   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2048   "mvf%?e\\t%0, %1"
2049 [(set_attr "type" "ffarith")])
2051 (define_insn "extenddfxf2"
2052   [(set (match_operand:XF 0 "s_register_operand" "=f")
2053         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2054   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2055   "mvf%?e\\t%0, %1"
2056 [(set_attr "type" "ffarith")])
2059 ;; Move insns (including loads and stores)
2061 ;; XXX Just some ideas about movti.
2062 ;; I don't think these are a good idea on the arm, there just aren't enough
2063 ;; registers
2064 ;;(define_expand "loadti"
2065 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
2066 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
2067 ;;  "" "")
2069 ;;(define_expand "storeti"
2070 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2071 ;;      (match_operand:TI 1 "s_register_operand" ""))]
2072 ;;  "" "")
2074 ;;(define_expand "movti"
2075 ;;  [(set (match_operand:TI 0 "general_operand" "")
2076 ;;      (match_operand:TI 1 "general_operand" ""))]
2077 ;;  ""
2078 ;;  "
2080 ;;  rtx insn;
2082 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2083 ;;    operands[1] = copy_to_reg (operands[1]);
2084 ;;  if (GET_CODE (operands[0]) == MEM)
2085 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2086 ;;  else if (GET_CODE (operands[1]) == MEM)
2087 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2088 ;;  else
2089 ;;    FAIL;
2091 ;;  emit_insn (insn);
2092 ;;  DONE;
2093 ;;}")
2095 ;; Recognise garbage generated above.
2097 ;;(define_insn ""
2098 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2099 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2100 ;;  ""
2101 ;;  "*
2102 ;;  {
2103 ;;    register mem = (which_alternative < 3);
2104 ;;    register char *template;
2106 ;;    operands[mem] = XEXP (operands[mem], 0);
2107 ;;    switch (which_alternative)
2108 ;;      {
2109 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2110 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
2111 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
2112 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
2113 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
2114 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
2115 ;;      }
2116 ;;    output_asm_insn (template, operands);
2117 ;;    return \"\";
2118 ;;  }")
2121 (define_insn "movdi"
2122   [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2123         (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2124   ""
2125   "*
2126   return (output_move_double (operands));
2128 [(set_attr "length" "8,8,8")
2129  (set_attr "type" "*,load,store2")])
2131 (define_expand "movsi"
2132   [(set (match_operand:SI 0 "general_operand" "")
2133         (match_operand:SI 1 "general_operand" ""))]
2134   ""
2135   "
2136   /* Everything except mem = const or mem = mem can be done easily */
2137   if (GET_CODE (operands[0]) == MEM)
2138     operands[1] = force_reg (SImode, operands[1]);
2139   if (GET_CODE (operands[1]) == CONST_INT
2140       && !(const_ok_for_arm (INTVAL (operands[1]))
2141            || const_ok_for_arm (~INTVAL (operands[1]))))
2142     {
2143       arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2144                           NULL_RTX,
2145                           (reload_in_progress || reload_completed ? 0
2146                            : preserve_subexpressions_p ()));
2147       DONE;
2148     }
2151 (define_insn "*movsi_insn"
2152   [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2153         (match_operand:SI 1 "general_operand"  "rI,K,mi,r"))]
2154   "register_operand (operands[0], SImode)
2155    || register_operand (operands[1], SImode)"
2156   "@
2157    mov%?\\t%0, %1
2158    mvn%?\\t%0, #%B1
2159    ldr%?\\t%0, %1
2160    str%?\\t%1, %0"
2161 [(set_attr "type" "*,*,load,store1")])
2163 (define_split
2164   [(set (match_operand:SI 0 "s_register_operand" "")
2165         (match_operand:SI 1 "const_int_operand" ""))]
2166   "! (const_ok_for_arm (INTVAL (operands[1]))
2167       || const_ok_for_arm (~INTVAL (operands[1])))"
2168   [(clobber (const_int 0))]
2169   "
2170   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2171                       NULL_RTX, 0);
2172   DONE;
2175 (define_expand "movaddr"
2176   [(set (match_operand:SI 0 "s_register_operand" "")
2177         (match_operand:DI 1 "address_operand" ""))]
2178   ""
2179   "")
2181 (define_insn "*movaddr_insn"
2182   [(set (match_operand:SI 0 "s_register_operand" "=r")
2183         (match_operand:DI 1 "address_operand" "p"))]
2184   "reload_completed
2185    && (GET_CODE (operands[1]) == LABEL_REF
2186        || (GET_CODE (operands[1]) == CONST
2187            && GET_CODE (XEXP (operands[1], 0)) == PLUS
2188            && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2189            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2190   "adr%?\\t%0, %a1")
2192 ;; If copying one reg to another we can set the condition codes according to
2193 ;; its value.  Such a move is common after a return from subroutine and the
2194 ;; result is being tested against zero.
2196 (define_insn "*movsi_compare0"
2197   [(set (reg:CC 24) (compare (match_operand:SI 1 "s_register_operand" "0,r")
2198                              (const_int 0)))
2199    (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2200   ""
2201   "@
2202    cmp%?\\t%0, #0
2203    sub%?s\\t%0, %1, #0"
2204 [(set_attr "conds" "set")])
2206 ;; Subroutine to store a half word from a register into memory.
2207 ;; Operand 0 is the source register (HImode)
2208 ;; Operand 1 is the destination address in a register (SImode)
2210 ;; In both this routine and the next, we must be careful not to spill
2211 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2212 ;; can generate unrecognizable rtl.
2214 (define_expand "storehi"
2215   [;; store the low byte
2216    (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3))
2217    ;; extract the high byte
2218    (set (match_dup 2)
2219         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2220    ;; store the high byte
2221    (set (mem:QI (match_dup 4))
2222         (subreg:QI (match_dup 2) 0))]   ;explicit subreg safe
2223   ""
2224   "
2226   enum rtx_code code = GET_CODE (operands[1]);
2228   if ((code == PLUS || code == MINUS)
2229       && (GET_CODE (XEXP (operands[1], 1)) == REG
2230           || GET_CODE (XEXP (operands[1], 0)) != REG))
2231     operands[1] = force_reg (SImode, operands[1]);
2232   operands[4] = plus_constant (operands[1], 1);
2233   operands[3] = gen_lowpart (QImode, operands[0]);
2234   operands[0] = gen_lowpart (SImode, operands[0]);
2235   operands[2] = gen_reg_rtx (SImode); 
2239 (define_expand "storehi_bigend"
2240   [(set (mem:QI (match_dup 4)) (match_dup 3))
2241    (set (match_dup 2)
2242         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2243    (set (mem:QI (match_operand 1 "" ""))
2244         (subreg:QI (match_dup 2) 0))]
2245   ""
2246   "
2248   enum rtx_code code = GET_CODE (operands[1]);
2249   if ((code == PLUS || code == MINUS)
2250       && (GET_CODE (XEXP (operands[1], 1)) == REG
2251           || GET_CODE (XEXP (operands[1], 0)) != REG))
2252     operands[1] = force_reg (SImode, operands[1]);
2254   operands[4] = plus_constant (operands[1], 1);
2255   operands[3] = gen_lowpart (QImode, operands[0]);
2256   operands[0] = gen_lowpart (SImode, operands[0]);
2257   operands[2] = gen_reg_rtx (SImode);
2261 ;; Subroutine to store a half word integer constant into memory.
2262 (define_expand "storeinthi"
2263   [(set (mem:QI (match_operand:SI 0 "" ""))
2264         (subreg:QI (match_operand 1 "" "") 0))
2265    (set (mem:QI (match_dup 3)) (subreg:QI (match_dup 2) 0))]
2266   ""
2267   "
2269   HOST_WIDE_INT value = INTVAL (operands[1]);
2270   enum rtx_code code = GET_CODE (operands[0]);
2272   if ((code == PLUS || code == MINUS)
2273       && (GET_CODE (XEXP (operands[0], 1)) == REG
2274           || GET_CODE (XEXP (operands[0], 0)) != REG))
2275   operands[0] = force_reg (SImode, operands[0]);
2277   operands[1] = gen_reg_rtx (SImode);
2278   if (BYTES_BIG_ENDIAN)
2279     {
2280       emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2281       if ((value & 255) == ((value >> 8) & 255))
2282         operands[2] = operands[1];
2283       else
2284         {
2285           operands[2] = gen_reg_rtx (SImode);
2286           emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2287         }
2288     }
2289   else
2290     {
2291       emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2292       if ((value & 255) == ((value >> 8) & 255))
2293         operands[2] = operands[1];
2294       else
2295         {
2296           operands[2] = gen_reg_rtx (SImode);
2297           emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2298         }
2299     }
2301   operands[3] = plus_constant (operands[0], 1);
2305 (define_expand "storehi_single_op"
2306   [(set (match_operand:HI 0 "memory_operand" "")
2307         (match_operand:HI 1 "general_operand" ""))]
2308   "arm_arch4"
2309   "
2310   if (! s_register_operand (operands[1], HImode))
2311     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2314 (define_expand "movhi"
2315   [(set (match_operand:HI 0 "general_operand" "")
2316         (match_operand:HI 1 "general_operand" ""))]
2317   ""
2318   "
2320   rtx insn;
2322   if (! (reload_in_progress || reload_completed))
2323     {
2324       if (GET_CODE (operands[0]) == MEM)
2325         {
2326           if (arm_arch4)
2327             {
2328               emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2329               DONE;
2330             }
2331           if (GET_CODE (operands[1]) == CONST_INT)
2332             emit_insn (gen_storeinthi (XEXP (operands[0], 0), operands[1]));
2333           else
2334             {
2335               if (GET_CODE (operands[1]) == MEM)
2336                 operands[1] = force_reg (HImode, operands[1]);
2337               if (BYTES_BIG_ENDIAN)
2338                 emit_insn (gen_storehi_bigend (operands[1],
2339                                                XEXP (operands[0], 0)));
2340               else
2341                 emit_insn (gen_storehi (operands[1], XEXP (operands[0], 0)));
2342             }
2343           DONE;
2344         }
2345       /* Sign extend a constant, and keep it in an SImode reg.  */
2346       else if (GET_CODE (operands[1]) == CONST_INT)
2347         {
2348           rtx reg = gen_reg_rtx (SImode);
2349           HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2351           /* If the constant is already valid, leave it alone.  */
2352           if (! const_ok_for_arm (val))
2353             {
2354               /* If setting all the top bits will make the constant 
2355                  loadable in a single instruction, then set them.  
2356                  Otherwise, sign extend the number.  */
2358               if (const_ok_for_arm (~ (val | ~0xffff)))
2359                 val |= ~0xffff;
2360               else if (val & 0x8000)
2361                 val |= ~0xffff;
2362             }
2364           emit_insn (gen_movsi (reg, GEN_INT (val)));
2365           operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
2366         }
2367       else if (! arm_arch4)
2368         {
2369           if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2370             {
2371               rtx reg = gen_reg_rtx (SImode);
2372               emit_insn (gen_movhi_bytes (reg, operands[1]));
2373               operands[1] = gen_lowpart (HImode, reg);
2374             }
2375           else if (BYTES_BIG_ENDIAN && GET_CODE (operands[1]) == MEM)
2376             {
2377               emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2378               DONE;
2379             }
2380         }
2381     }
2385 (define_expand "movhi_bytes"
2386   [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" ""))))
2387    (set (match_dup 3)
2388         (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
2389    (set (match_operand:SI 0 "" "")
2390          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
2391   ""
2392   "
2393   operands[0] = gen_lowpart (SImode, operands[0]);
2394   operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2395   operands[2] = gen_reg_rtx (SImode);
2396   operands[3] = gen_reg_rtx (SImode);
2398   if (BYTES_BIG_ENDIAN)
2399     {
2400       operands[4] = operands[2];
2401       operands[5] = operands[3];
2402     }
2403   else
2404     {
2405       operands[4] = operands[3];
2406       operands[5] = operands[2];
2407     }
2410 (define_expand "movhi_bigend"
2411   [(set (match_dup 2)
2412         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
2413                    (const_int 16)))
2414    (set (match_dup 3)
2415         (ashiftrt:SI (match_dup 2) (const_int 16)))
2416    (set (match_operand:HI 0 "s_register_operand" "")
2417         (subreg:HI (match_dup 3) 0))]
2418   ""
2419   "
2420   operands[2] = gen_reg_rtx (SImode);
2421   operands[3] = gen_reg_rtx (SImode);
2424 ;; Pattern to recognise insn generated default case above
2426 (define_insn "*movhi_insn_arch4"
2427   [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
2428         (match_operand:HI 1 "general_operand"  "rI,K,m,r"))]
2429   "arm_arch4
2430    && (GET_CODE (operands[1]) != CONST_INT
2431        || const_ok_for_arm (INTVAL (operands[1]))
2432        || const_ok_for_arm (~INTVAL (operands[1])))"
2433   "@
2434    mov%?\\t%0, %1\\t%@ movhi
2435    mvn%?\\t%0, #%B1\\t%@ movhi
2436    ldr%?h\\t%0, %1\\t%@ movhi
2437    str%?h\\t%1, %0\\t%@ movhi"
2438 [(set_attr "type" "*,*,load,store1")])
2440 (define_insn "*movhi_insn_littleend"
2441   [(set (match_operand:HI 0 "general_operand" "=r,r,r")
2442         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2443   "! arm_arch4
2444    && ! BYTES_BIG_ENDIAN
2445    && ! TARGET_SHORT_BY_BYTES
2446    && (GET_CODE (operands[1]) != CONST_INT
2447        || const_ok_for_arm (INTVAL (operands[1]))
2448        || const_ok_for_arm (~INTVAL (operands[1])))"
2449   "@
2450    mov%?\\t%0, %1\\t%@ movhi
2451    mvn%?\\t%0, #%B1\\t%@ movhi
2452    ldr%?\\t%0, %1\\t%@ movhi"
2453 [(set_attr "type" "*,*,load")])
2455 (define_insn "*movhi_insn_bigend"
2456   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
2457         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2458   "! arm_arch4
2459    && BYTES_BIG_ENDIAN
2460    && ! TARGET_SHORT_BY_BYTES
2461    && (GET_CODE (operands[1]) != CONST_INT
2462        || const_ok_for_arm (INTVAL (operands[1]))
2463        || const_ok_for_arm (~INTVAL (operands[1])))"
2464   "@
2465    mov%?\\t%0, %1\\t%@ movhi
2466    mvn%?\\t%0, #%B1\\t%@ movhi
2467    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
2468 [(set_attr "type" "*,*,load")
2469  (set_attr "length" "4,4,8")])
2471 (define_insn "*loadhi_si_bigend"
2472   [(set (match_operand:SI 0 "s_register_operand" "=r")
2473         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
2474                    (const_int 16)))]
2475   "BYTES_BIG_ENDIAN
2476    && ! TARGET_SHORT_BY_BYTES"
2477   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
2478 [(set_attr "type" "load")])
2480 (define_insn "*movhi_bytes"
2481   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
2482         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
2483   "TARGET_SHORT_BY_BYTES"
2484   "@
2485    mov%?\\t%0, %1\\t%@ movhi
2486    mvn%?\\t%0, #%B1\\t%@ movhi")
2489 (define_expand "reload_outhi"
2490   [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
2491               (match_operand:HI 1 "s_register_operand" "r")
2492               (match_operand:SI 2 "s_register_operand" "=&r")])]
2493   ""
2494   "
2495   arm_reload_out_hi (operands);
2496   DONE;
2499 (define_expand "reload_inhi"
2500   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
2501               (match_operand:HI 1 "reload_memory_operand" "o")
2502               (match_operand:SI 2 "s_register_operand" "=&r")])]
2503   "TARGET_SHORT_BY_BYTES"
2504   "
2505   arm_reload_in_hi (operands);
2506   DONE;
2509 (define_expand "movqi"
2510   [(set (match_operand:QI 0 "general_operand" "")
2511         (match_operand:QI 1 "general_operand" ""))]
2512   ""
2513   "
2514   /* Everything except mem = const or mem = mem can be done easily */
2516   if (!(reload_in_progress || reload_completed))
2517     {
2518       if (GET_CODE (operands[1]) == CONST_INT)
2519         {
2520           rtx reg = gen_reg_rtx (SImode);
2522           emit_insn (gen_movsi (reg, operands[1]));
2523           operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
2524         }
2525       if (GET_CODE (operands[0]) == MEM)
2526         operands[1] = force_reg (QImode, operands[1]);
2527     }
2531 (define_insn "*movqi_insn"
2532   [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
2533         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
2534   "register_operand (operands[0], QImode)
2535    || register_operand (operands[1], QImode)"
2536   "@
2537    mov%?\\t%0, %1
2538    mvn%?\\t%0, #%B1
2539    ldr%?b\\t%0, %1
2540    str%?b\\t%1, %0"
2541 [(set_attr "type" "*,*,load,store1")])
2543 (define_expand "movsf"
2544   [(set (match_operand:SF 0 "general_operand" "")
2545         (match_operand:SF 1 "general_operand" ""))]
2546   ""
2547   "
2548   if (GET_CODE (operands[0]) == MEM)
2549     operands[1] = force_reg (SFmode, operands[1]);
2552 (define_insn "*movsf_hard_insn"
2553   [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
2554         (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
2555   "TARGET_HARD_FLOAT
2556    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
2557   "@
2558    mvf%?s\\t%0, %1
2559    mnf%?s\\t%0, #%N1
2560    ldf%?s\\t%0, %1
2561    stf%?s\\t%1, %0
2562    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
2563    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
2564    mov%?\\t%0, %1
2565    ldr%?\\t%0, %1\\t%@ float
2566    str%?\\t%1, %0\\t%@ float"
2567 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
2568  (set_attr "type"
2569          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
2571 ;; Exactly the same as above, except that all `f' cases are deleted.
2572 ;; This is necessary to prevent reload from ever trying to use a `f' reg
2573 ;; when -msoft-float.
2575 (define_insn "*movsf_soft_insn"
2576   [(set (match_operand:SF 0 "general_operand" "=r,r,m")
2577         (match_operand:SF 1 "general_operand" "r,mE,r"))]
2578   "TARGET_SOFT_FLOAT
2579    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
2580   "@
2581    mov%?\\t%0, %1
2582    ldr%?\\t%0, %1\\t%@ float
2583    str%?\\t%1, %0\\t%@ float"
2584 [(set_attr "length" "4,4,4")
2585  (set_attr "type" "*,load,store1")])
2587 (define_expand "movdf"
2588   [(set (match_operand:DF 0 "general_operand" "")
2589         (match_operand:DF 1 "general_operand" ""))]
2590   ""
2591   "
2592   if (GET_CODE (operands[0]) == MEM)
2593     operands[1] = force_reg (DFmode, operands[1]);
2596 ;; Reloading a df mode value stored in integer regs to memory can require a
2597 ;; scratch reg.
2598 (define_expand "reload_outdf"
2599   [(match_operand:DF 0 "reload_memory_operand" "=o")
2600    (match_operand:DF 1 "s_register_operand" "r")
2601    (match_operand:SI 2 "s_register_operand" "=&r")]
2602   ""
2603   "
2605   enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
2607   if (code == REG)
2608     operands[2] = XEXP (operands[0], 0);
2609   else if (code == POST_INC || code == PRE_DEC)
2610     {
2611       operands[0] = gen_rtx (SUBREG, DImode, operands[0], 0);
2612       operands[1] = gen_rtx (SUBREG, DImode, operands[1], 0);
2613       emit_insn (gen_movdi (operands[0], operands[1]));
2614       DONE;
2615     }
2616   else if (code == PRE_INC)
2617     {
2618       rtx reg = XEXP (XEXP (operands[0], 0), 0);
2619       emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
2620       operands[2] = reg;
2621     }
2622   else if (code == POST_DEC)
2623     operands[2] = XEXP (XEXP (operands[0], 0), 0);
2624   else
2625     emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
2626                            XEXP (XEXP (operands[0], 0), 1)));
2628   emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DFmode, operands[2]),
2629                       operands[1]));
2631   if (code == POST_DEC)
2632     emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
2634   DONE;
2638 (define_insn "*movdf_hard_insn"
2639   [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
2640         (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
2641   "TARGET_HARD_FLOAT
2642    && (GET_CODE (operands[0]) != MEM
2643        || register_operand (operands[1], DFmode))"
2644   "*
2646   rtx ops[3];
2648   switch (which_alternative)
2649     {
2650     case 0: return \"ldm%?ia\\t%m1, {%0, %R0}\\t%@ double\";
2651     case 1: return \"stm%?ia\\t%m0, {%1, %R1}\\t%@ double\";
2652     case 2: case 3: case 4: return output_move_double (operands);
2653     case 5: return \"mvf%?d\\t%0, %1\";
2654     case 6: return \"mnf%?d\\t%0, #%N1\";
2655     case 7: return \"ldf%?d\\t%0, %1\";
2656     case 8: return \"stf%?d\\t%1, %0\";
2657     case 9: return output_mov_double_fpu_from_arm (operands);
2658     case 10: return output_mov_double_arm_from_fpu (operands);
2659     }
2662 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
2663  (set_attr "type"
2664 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
2666 ;; Software floating point version.  This is essentially the same as movdi.
2667 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
2668 ;; an `f' reg.
2670 (define_insn "*movdf_soft_insn"
2671   [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
2672         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
2673   "TARGET_SOFT_FLOAT"
2674   "* return output_move_double (operands);"
2675 [(set_attr "length" "8,8,8")
2676  (set_attr "type" "*,load,store2")])
2678 (define_expand "movxf"
2679   [(set (match_operand:XF 0 "general_operand" "")
2680         (match_operand:XF 1 "general_operand" ""))]
2681   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2682   "")
2684 ;; Even when the XFmode patterns aren't enabled, we enable this after
2685 ;; reloading so that we can push floating point registers in the prologue.
2687 (define_insn "*movxf_hard_insn"
2688   [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
2689         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
2690   "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
2691   "*
2692   switch (which_alternative)
2693     {
2694     case 0: return \"mvf%?e\\t%0, %1\";
2695     case 1: return \"mnf%?e\\t%0, #%N1\";
2696     case 2: return \"ldf%?e\\t%0, %1\";
2697     case 3: return \"stf%?e\\t%1, %0\";
2698     case 4: return output_mov_long_double_fpu_from_arm (operands);
2699     case 5: return output_mov_long_double_arm_from_fpu (operands);
2700     case 6: return output_mov_long_double_arm_from_arm (operands);
2701     }
2703 [(set_attr "length" "4,4,4,4,8,8,12")
2704  (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
2707 ;; load- and store-multiple insns
2708 ;; The arm can load/store any set of registers, provided that they are in
2709 ;; ascending order; but that is beyond GCC so stick with what it knows.
2711 (define_expand "load_multiple"
2712   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2713                           (match_operand:SI 1 "" ""))
2714                      (use (match_operand:SI 2 "" ""))])]
2715   ""
2716   "
2717   /* Support only fixed point registers */
2718   if (GET_CODE (operands[2]) != CONST_INT
2719       || INTVAL (operands[2]) > 14
2720       || INTVAL (operands[2]) < 2
2721       || GET_CODE (operands[1]) != MEM
2722       || GET_CODE (operands[0]) != REG
2723       || REGNO (operands[0]) > 14
2724       || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
2725     FAIL;
2727   operands[3]
2728             = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
2729                                      force_reg (SImode, XEXP (operands[1], 0)),
2730                                      TRUE, FALSE);
2733 ;; Load multiple with write-back
2735 (define_insn "*ldmsi_postinc"
2736   [(match_parallel 0 "load_multiple_operation"
2737                    [(set (match_operand:SI 1 "s_register_operand" "+r")
2738                          (plus:SI (match_dup 1)
2739                                   (match_operand:SI 2 "immediate_operand" "n")))
2740                     (set (match_operand:SI 3 "s_register_operand" "=r")
2741                          (mem:SI (match_dup 1)))])]
2742   "(INTVAL (operands[2])  == 4 * (XVECLEN (operands[0], 0) - 2))"
2743   "*
2745   rtx ops[3];
2746   int count = XVECLEN (operands[0], 0);
2748   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2749   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
2750   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
2752   output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
2753   return \"\";
2756 [(set_attr "type" "load")])
2758 ;; Ordinary load multiple
2760 (define_insn "*ldmsi"
2761   [(match_parallel 0 "load_multiple_operation"
2762                    [(set (match_operand:SI 1 "s_register_operand" "=r")
2763                          (match_operand:SI 2 "indirect_operand" "Q"))])]
2764   ""
2765   "*
2767   rtx ops[3];
2768   int count = XVECLEN (operands[0], 0);
2770   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2771   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
2772   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
2774   output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
2775   return \"\";
2778 [(set_attr "type" "load")])
2780 (define_expand "store_multiple"
2781   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2782                           (match_operand:SI 1 "" ""))
2783                      (use (match_operand:SI 2 "" ""))])]
2784   ""
2785   "
2786   /* Support only fixed point registers */
2787   if (GET_CODE (operands[2]) != CONST_INT
2788       || INTVAL (operands[2]) > 14
2789       || INTVAL (operands[2]) < 2
2790       || GET_CODE (operands[1]) != REG
2791       || GET_CODE (operands[0]) != MEM
2792       || REGNO (operands[1]) > 14
2793       || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
2794     FAIL;
2796   operands[3]
2797            = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
2798                                      force_reg (SImode, XEXP (operands[0], 0)),
2799                                      TRUE, FALSE);
2802 ;; Store multiple with write-back
2804 (define_insn "*stmsi_postinc"
2805   [(match_parallel 0 "store_multiple_operation"
2806                    [(set (match_operand:SI 1 "s_register_operand" "+r")
2807                          (plus:SI (match_dup 1)
2808                                   (match_operand:SI 2 "immediate_operand" "n")))
2809                     (set (mem:SI (match_dup 1))
2810                          (match_operand:SI 3 "s_register_operand" "r"))])]
2811   "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
2812   "*
2814   rtx ops[3];
2815   int count = XVECLEN (operands[0], 0);
2817   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2818   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
2819   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
2821   output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
2822   return \"\";
2825 [(set (attr "type")
2826       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2827                 (const_string "store2")
2828              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
2829                 (const_string "store3")]
2830           (const_string "store4")))])
2832 ;; Ordinary store multiple
2834 (define_insn "*stmsi"
2835   [(match_parallel 0 "store_multiple_operation"
2836                    [(set (match_operand:SI 2 "indirect_operand" "=Q")
2837                          (match_operand:SI 1 "s_register_operand" "r"))])]
2838   ""
2839   "*
2841   rtx ops[3];
2842   int count = XVECLEN (operands[0], 0);
2844   ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
2845   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
2846   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
2848   output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
2849   return \"\";
2852 [(set (attr "type")
2853       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
2854                 (const_string "store2")
2855              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2856                 (const_string "store3")]
2857           (const_string "store4")))])
2859 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
2860 ;; We could let this apply for blocks of less than this, but it clobbers so
2861 ;; many registers that there is then probably a better way.
2863 (define_expand "movstrqi"
2864   [(match_operand:BLK 0 "general_operand" "")
2865    (match_operand:BLK 1 "general_operand" "")
2866    (match_operand:SI 2 "const_int_operand" "")
2867    (match_operand:SI 3 "const_int_operand" "")]
2868   ""
2869   "
2870   if (arm_gen_movstrqi (operands))
2871     DONE;
2872   FAIL;
2876 ;; Comparison and test insns
2878 (define_expand "cmpsi"
2879   [(set (reg:CC 24)
2880         (compare:CC (match_operand:SI 0 "s_register_operand" "")
2881                     (match_operand:SI 1 "arm_add_operand" "")))]
2882   ""
2883   "
2885   arm_compare_op0 = operands[0];
2886   arm_compare_op1 = operands[1];
2887   arm_compare_fp = 0;
2888   DONE;
2892 (define_expand "cmpsf"
2893   [(set (reg:CC 24)
2894         (compare:CC (match_operand:SF 0 "s_register_operand" "")
2895                     (match_operand:SF 1 "fpu_rhs_operand" "")))]
2896   "TARGET_HARD_FLOAT"
2897   "
2899   arm_compare_op0 = operands[0];
2900   arm_compare_op1 = operands[1];
2901   arm_compare_fp = 1;
2902   DONE;
2906 (define_expand "cmpdf"
2907   [(set (reg:CC 24)
2908         (compare:CC (match_operand:DF 0 "s_register_operand" "")
2909                     (match_operand:DF 1 "fpu_rhs_operand" "")))]
2910   "TARGET_HARD_FLOAT"
2911   "
2913   arm_compare_op0 = operands[0];
2914   arm_compare_op1 = operands[1];
2915   arm_compare_fp = 1;
2916   DONE;
2920 (define_expand "cmpxf"
2921   [(set (reg:CC 24)
2922         (compare:CC (match_operand:XF 0 "s_register_operand" "")
2923                     (match_operand:XF 1 "fpu_rhs_operand" "")))]
2924   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2925   "
2927   arm_compare_op0 = operands[0];
2928   arm_compare_op1 = operands[1];
2929   arm_compare_fp = 1;
2930   DONE;
2934 (define_insn "*cmpsi_insn"
2935   [(set (match_operand 0 "cc_register" "")
2936         (compare (match_operand:SI 1 "s_register_operand" "r,r")
2937                  (match_operand:SI 2 "arm_add_operand" "rI,L")))]
2938   ""
2939   "@
2940    cmp%?\\t%1, %2
2941    cmn%?\\t%1, #%n2"
2942 [(set_attr "conds" "set")])
2944 (define_insn "*cmpsi_negsi"
2945   [(set (match_operand 0 "cc_register" "")
2946         (compare (match_operand:SI 1 "s_register_operand" "r")
2947                  (neg:SI (match_operand:SI 2 "s_register_operand" "r"))))]
2948   ""
2949   "cmn%?\\t%1, %2"
2950 [(set_attr "conds" "set")])
2952 (define_insn "*cmpsi_shiftsi"
2953   [(set (match_operand 0 "cc_register" "")
2954         (compare (match_operand:SI 1 "s_register_operand" "r")
2955                  (match_operator:SI 2 "shift_operator"
2956                   [(match_operand:SI 3 "s_register_operand" "r")
2957                    (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
2958   ""
2959   "cmp%?\\t%1, %3%S2"
2960 [(set_attr "conds" "set")])
2962 (define_insn "*cmpsi_neg_shiftsi"
2963   [(set (match_operand 0 "cc_register" "")
2964         (compare (match_operand:SI 1 "s_register_operand" "r")
2965                  (neg:SI (match_operator:SI 2 "shift_operator"
2966                           [(match_operand:SI 3 "s_register_operand" "r")
2967                            (match_operand:SI 4 "arm_rhs_operand" "rM")]))))]
2968   ""
2969   "cmn%?\\t%1, %3%S2"
2970 [(set_attr "conds" "set")])
2972 (define_insn "*cmpsf_insn"
2973   [(set (reg:CCFP 24)
2974         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
2975                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
2976   "TARGET_HARD_FLOAT"
2977   "@
2978    cmf%?\\t%0, %1
2979    cnf%?\\t%0, #%N1"
2980 [(set_attr "conds" "set")
2981  (set_attr "type" "f_2_r")])
2983 (define_insn "*cmpdf_insn"
2984   [(set (reg:CCFP 24)
2985         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
2986                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
2987   "TARGET_HARD_FLOAT"
2988   "@
2989    cmf%?\\t%0, %1
2990    cnf%?\\t%0, #%N1"
2991 [(set_attr "conds" "set")
2992  (set_attr "type" "f_2_r")])
2994 (define_insn "*cmpesfdf_df"
2995   [(set (reg:CCFP 24)
2996         (compare:CCFP (float_extend:DF
2997                        (match_operand:SF 0 "s_register_operand" "f,f"))
2998                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
2999   "TARGET_HARD_FLOAT"
3000   "@
3001    cmf%?\\t%0, %1
3002    cnf%?\\t%0, #%N1"
3003 [(set_attr "conds" "set")
3004  (set_attr "type" "f_2_r")])
3006 (define_insn "*cmpdf_esfdf"
3007   [(set (reg:CCFP 24)
3008         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3009                       (float_extend:DF
3010                        (match_operand:SF 1 "s_register_operand" "f"))))]
3011   "TARGET_HARD_FLOAT"
3012   "cmf%?\\t%0, %1"
3013 [(set_attr "conds" "set")
3014  (set_attr "type" "f_2_r")])
3016 (define_insn "*cmpxf_insn"
3017   [(set (reg:CCFP 24)
3018         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3019                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3020   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3021   "@
3022    cmf%?\\t%0, %1
3023    cnf%?\\t%0, #%N1"
3024 [(set_attr "conds" "set")
3025  (set_attr "type" "f_2_r")])
3027 (define_insn "*cmpsf_trap"
3028   [(set (reg:CCFPE 24)
3029         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3030                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3031   "TARGET_HARD_FLOAT"
3032   "@
3033    cmf%?e\\t%0, %1
3034    cnf%?e\\t%0, #%N1"
3035 [(set_attr "conds" "set")
3036  (set_attr "type" "f_2_r")])
3038 (define_insn "*cmpdf_trap"
3039   [(set (reg:CCFPE 24)
3040         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3041                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3042   "TARGET_HARD_FLOAT"
3043   "@
3044    cmf%?e\\t%0, %1
3045    cnf%?e\\t%0, #%N1"
3046 [(set_attr "conds" "set")
3047  (set_attr "type" "f_2_r")])
3049 (define_insn "*cmp_esfdf_df_trap"
3050   [(set (reg:CCFPE 24)
3051         (compare:CCFPE (float_extend:DF
3052                         (match_operand:SF 0 "s_register_operand" "f,f"))
3053                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3054   "TARGET_HARD_FLOAT"
3055   "@
3056    cmf%?e\\t%0, %1
3057    cnf%?e\\t%0, #%N1"
3058 [(set_attr "conds" "set")
3059  (set_attr "type" "f_2_r")])
3061 (define_insn "*cmp_df_esfdf_trap"
3062   [(set (reg:CCFPE 24)
3063         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3064                        (float_extend:DF
3065                         (match_operand:SF 1 "s_register_operand" "f"))))]
3066   "TARGET_HARD_FLOAT"
3067   "cmf%?e\\t%0, %1"
3068 [(set_attr "conds" "set")
3069  (set_attr "type" "f_2_r")])
3071 (define_insn "*cmpxf_trap"
3072   [(set (reg:CCFPE 24)
3073         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3074                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3075   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3076   "@
3077    cmf%?e\\t%0, %1
3078    cnf%?e\\t%0, #%N1"
3079 [(set_attr "conds" "set")
3080  (set_attr "type" "f_2_r")])
3082 ; This insn allows redundant compares to be removed by cse, nothing should
3083 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3084 ; is deleted later on. The match_dup will match the mode here, so that
3085 ; mode changes of the condition codes aren't lost by this even though we don't
3086 ; specify what they are.
3088 (define_insn "*delted_compare"
3089   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3090   ""
3091   "\\t%@ deleted compare"
3092 [(set_attr "conds" "set")
3093  (set_attr "length" "0")])
3096 ;; Conditional branch insns
3098 (define_expand "beq"
3099   [(set (pc)
3100         (if_then_else (eq (match_dup 1) (const_int 0))
3101                       (label_ref (match_operand 0 "" ""))
3102                       (pc)))]
3103   ""
3104   "
3106   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3107                                  arm_compare_fp);
3111 (define_expand "bne"
3112   [(set (pc)
3113         (if_then_else (ne (match_dup 1) (const_int 0))
3114                       (label_ref (match_operand 0 "" ""))
3115                       (pc)))]
3116   ""
3117   "
3119   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3120                                  arm_compare_fp);
3124 (define_expand "bgt"
3125   [(set (pc)
3126         (if_then_else (gt (match_dup 1) (const_int 0))
3127                       (label_ref (match_operand 0 "" ""))
3128                       (pc)))]
3129   ""
3130   "
3132   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3133                                  arm_compare_fp);
3137 (define_expand "ble"
3138   [(set (pc)
3139         (if_then_else (le (match_dup 1) (const_int 0))
3140                       (label_ref (match_operand 0 "" ""))
3141                       (pc)))]
3142   ""
3143   "
3145   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3146                                  arm_compare_fp);
3150 (define_expand "bge"
3151   [(set (pc)
3152         (if_then_else (ge (match_dup 1) (const_int 0))
3153                       (label_ref (match_operand 0 "" ""))
3154                       (pc)))]
3155   ""
3156   "
3158   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3159                                  arm_compare_fp);
3163 (define_expand "blt"
3164   [(set (pc)
3165         (if_then_else (lt (match_dup 1) (const_int 0))
3166                       (label_ref (match_operand 0 "" ""))
3167                       (pc)))]
3168   ""
3169   "
3171   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3172                                  arm_compare_fp);
3176 (define_expand "bgtu"
3177   [(set (pc)
3178         (if_then_else (gtu (match_dup 1) (const_int 0))
3179                       (label_ref (match_operand 0 "" ""))
3180                       (pc)))]
3181   ""
3182   "
3184   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3185                                  arm_compare_fp);
3189 (define_expand "bleu"
3190   [(set (pc)
3191         (if_then_else (leu (match_dup 1) (const_int 0))
3192                       (label_ref (match_operand 0 "" ""))
3193                       (pc)))]
3194   ""
3195   "
3197   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3198                                  arm_compare_fp);
3202 (define_expand "bgeu"
3203   [(set (pc)
3204         (if_then_else (geu (match_dup 1) (const_int 0))
3205                       (label_ref (match_operand 0 "" ""))
3206                       (pc)))]
3207   ""
3208   "
3210   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3211                                  arm_compare_fp);
3215 (define_expand "bltu"
3216   [(set (pc)
3217         (if_then_else (ltu (match_dup 1) (const_int 0))
3218                       (label_ref (match_operand 0 "" ""))
3219                       (pc)))]
3220   ""
3221   "
3223   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3224                                  arm_compare_fp);
3228 ;; patterns to match conditional branch insns
3230 (define_insn "*condbranch"
3231   [(set (pc)
3232         (if_then_else (match_operator 1 "comparison_operator"
3233                                         [(reg 24) (const_int 0)])
3234                       (label_ref (match_operand 0 "" ""))
3235                       (pc)))]
3236   ""
3237   "*
3239   extern int arm_ccfsm_state;
3241   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3242   {
3243     arm_ccfsm_state += 2;
3244     return \"\";
3245   }
3246   return \"b%d1\\t%l0\";
3248 [(set_attr "conds" "use")])
3250 (define_insn "*condbranch_reversed"
3251   [(set (pc)
3252         (if_then_else (match_operator 1 "comparison_operator"
3253                                         [(reg 24) (const_int 0)])
3254                       (pc)
3255                       (label_ref (match_operand 0 "" ""))))]
3256   "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
3257   "*
3259   extern int arm_ccfsm_state;
3261   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3262   {
3263     arm_ccfsm_state += 2;
3264     return \"\";
3265   }
3266   return \"b%D1\\t%l0\";
3268 [(set_attr "conds" "use")])
3271 ; scc insns
3273 (define_expand "seq"
3274   [(set (match_operand:SI 0 "s_register_operand" "=r")
3275         (eq:SI (match_dup 1) (const_int 0)))]
3276   ""
3277   "
3279   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3280                                  arm_compare_fp);
3284 (define_expand "sne"
3285   [(set (match_operand:SI 0 "s_register_operand" "=r")
3286         (ne:SI (match_dup 1) (const_int 0)))]
3287   ""
3288   "
3290   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3291                                  arm_compare_fp);
3295 (define_expand "sgt"
3296   [(set (match_operand:SI 0 "s_register_operand" "=r")
3297         (gt:SI (match_dup 1) (const_int 0)))]
3298   ""
3299   "
3301   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3302                                  arm_compare_fp);
3306 (define_expand "sle"
3307   [(set (match_operand:SI 0 "s_register_operand" "=r")
3308         (le:SI (match_dup 1) (const_int 0)))]
3309   ""
3310   "
3312   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3313                                  arm_compare_fp);
3317 (define_expand "sge"
3318   [(set (match_operand:SI 0 "s_register_operand" "=r")
3319         (ge:SI (match_dup 1) (const_int 0)))]
3320   ""
3321   "
3323   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3324                                  arm_compare_fp);
3328 (define_expand "slt"
3329   [(set (match_operand:SI 0 "s_register_operand" "=r")
3330         (lt:SI (match_dup 1) (const_int 0)))]
3331   ""
3332   "
3334   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3335                                  arm_compare_fp);
3339 (define_expand "sgtu"
3340   [(set (match_operand:SI 0 "s_register_operand" "=r")
3341         (gtu:SI (match_dup 1) (const_int 0)))]
3342   ""
3343   "
3345   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3346                                  arm_compare_fp);
3350 (define_expand "sleu"
3351   [(set (match_operand:SI 0 "s_register_operand" "=r")
3352         (leu:SI (match_dup 1) (const_int 0)))]
3353   ""
3354   "
3356   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3357                                  arm_compare_fp);
3361 (define_expand "sgeu"
3362   [(set (match_operand:SI 0 "s_register_operand" "=r")
3363         (geu:SI (match_dup 1) (const_int 0)))]
3364   ""
3365   "
3367   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3368                                  arm_compare_fp);
3372 (define_expand "sltu"
3373   [(set (match_operand:SI 0 "s_register_operand" "=r")
3374         (ltu:SI (match_dup 1) (const_int 0)))]
3375   ""
3376   "
3378   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3379                                  arm_compare_fp);
3383 (define_insn "*mov_scc"
3384   [(set (match_operand:SI 0 "s_register_operand" "=r")
3385         (match_operator:SI 1 "comparison_operator" [(reg 24) (const_int 0)]))]
3386   ""
3387   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
3388 [(set_attr "conds" "use")
3389  (set_attr "length" "8")])
3391 (define_insn "*mov_negscc"
3392   [(set (match_operand:SI 0 "s_register_operand" "=r")
3393         (neg:SI (match_operator:SI 1 "comparison_operator"
3394                  [(reg 24) (const_int 0)])))]
3395   ""
3396   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
3397 [(set_attr "conds" "use")
3398  (set_attr "length" "8")])
3400 (define_insn "*mov_notscc"
3401   [(set (match_operand:SI 0 "s_register_operand" "=r")
3402         (not:SI (match_operator:SI 1 "comparison_operator"
3403                  [(reg 24) (const_int 0)])))]
3404   ""
3405   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
3406 [(set_attr "conds" "use")
3407  (set_attr "length" "8")])
3410 ;; Conditional move insns
3412 (define_expand "movsicc"
3413   [(set (match_operand:SI 0 "register_operand" "")
3414         (if_then_else (match_operand 1 "comparison_operator" "")
3415                       (match_operand:SI 2 "arm_not_operand" "")
3416                       (match_operand:SI 3 "register_operand" "")))]
3417   ""
3418   "
3420   enum rtx_code code = GET_CODE (operands[1]);
3421   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3422                                arm_compare_fp);
3424   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3427 (define_expand "movsfcc"
3428   [(set (match_operand:SF 0 "register_operand" "")
3429         (if_then_else (match_operand 1 "comparison_operator" "")
3430                       (match_operand:SF 2 "nonmemory_operand" "")
3431                       (match_operand:SF 3 "register_operand" "")))]
3432   ""
3433   "
3435   enum rtx_code code = GET_CODE (operands[1]);
3436   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3437                                arm_compare_fp);
3439   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3442 (define_expand "movdfcc"
3443   [(set (match_operand:DF 0 "register_operand" "")
3444         (if_then_else (match_operand 1 "comparison_operator" "")
3445                       (match_operand:DF 2 "nonmemory_operand" "")
3446                       (match_operand:DF 3 "register_operand" "")))]
3447   "TARGET_HARD_FLOAT"
3448   "
3450   enum rtx_code code = GET_CODE (operands[1]);
3451   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3452                                arm_compare_fp);
3454   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3457 (define_insn "*movsicc_insn"
3458   [(set (match_operand:SI 0 "register_operand" "=r,r")
3459         (if_then_else (match_operator 1 "comparison_operator" 
3460                        [(reg 24) (const_int 0)])
3461                       (match_operand:SI 2 "arm_not_operand" "rI,K")
3462                       (match_operand:SI 3 "register_operand" "0,0")))]
3463   ""
3464   "@
3465    mov%d1\\t%0, %2
3466    mvn%d1\\t%0, #%B2"
3467   [(set_attr "type" "*,*")
3468    (set_attr "conds" "use,use")])
3470 (define_insn "*movsfcc_hard_insn"
3471   [(set (match_operand:SF 0 "register_operand" "=f")
3472         (if_then_else (match_operator 1 "comparison_operator" 
3473                        [(reg 24) (const_int 0)])
3474                       (match_operand:SF 2 "register_operand" "f")
3475                       (match_operand:SF 3 "register_operand" "0")))]
3476   "TARGET_HARD_FLOAT"
3477   "mvf%d1s\\t%0, %2"
3478   [(set_attr "type" "ffarith")
3479    (set_attr "conds" "use")])
3481 (define_insn "*movsfcc_soft_insn"
3482   [(set (match_operand:SF 0 "register_operand" "=r")
3483         (if_then_else (match_operator 1 "comparison_operator"
3484                        [(reg 24) (const_int 0)])
3485                       (match_operand:SF 2 "register_operand" "r")
3486                       (match_operand:SF 3 "register_operand" "0")))]
3487   "TARGET_SOFT_FLOAT"
3488   "mov%d1\\t%0, %2"
3489   [(set_attr "type" "*")
3490    (set_attr "conds" "use")])
3492 (define_insn "*movdfcc_insn"
3493   [(set (match_operand:DF 0 "register_operand" "=f")
3494         (if_then_else (match_operator 1 "comparison_operator"
3495                        [(reg 24) (const_int 0)])
3496                       (match_operand:DF 2 "register_operand" "f")
3497                       (match_operand:DF 3 "register_operand" "0")))]
3498   "TARGET_HARD_FLOAT"
3499   "mvf%d1d\\t%0, %2"
3500   [(set_attr "type" "ffarith")
3501    (set_attr "conds" "use")])
3503 ;; Jump and linkage insns
3505 (define_insn "jump"
3506   [(set (pc)
3507         (label_ref (match_operand 0 "" "")))]
3508   ""
3509   "*
3511   extern int arm_ccfsm_state;
3513   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3514   {
3515     arm_ccfsm_state += 2;
3516     return \"\";
3517   }
3518   return \"b%?\\t%l0\";
3521 (define_expand "call"
3522   [(parallel [(call (match_operand 0 "memory_operand" "")
3523                     (match_operand 1 "general_operand" ""))
3524               (clobber (reg:SI 14))])]
3525   ""
3526   "")
3528 (define_insn "*call_reg"
3529   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
3530          (match_operand 1 "" "g"))
3531    (clobber (reg:SI 14))]
3532   ""
3533   "*
3534   return output_call (operands);
3536 ;; length is worst case, normally it is only two
3537 [(set_attr "length" "12")
3538  (set_attr "type" "call")])
3540 (define_insn "*call_mem"
3541   [(call (mem:SI (match_operand 0 "memory_operand" "m"))
3542          (match_operand 1 "general_operand" "g"))
3543    (clobber (reg:SI 14))]
3544   ""
3545   "*
3546   return output_call_mem (operands);
3548 [(set_attr "length" "12")
3549  (set_attr "type" "call")])
3551 (define_expand "call_value"
3552   [(parallel [(set (match_operand 0 "" "=rf")
3553                    (call (match_operand 1 "memory_operand" "m")
3554                          (match_operand 2 "general_operand" "g")))
3555               (clobber (reg:SI 14))])]
3556   ""
3557   "")
3559 (define_insn "*call_value_reg"
3560   [(set (match_operand 0 "" "=rf")
3561         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
3562               (match_operand 2 "general_operand" "g")))
3563    (clobber (reg:SI 14))]
3564   ""
3565   "*
3566   return output_call (&operands[1]);
3568 [(set_attr "length" "12")
3569  (set_attr "type" "call")])
3571 (define_insn "*call_value_mem"
3572   [(set (match_operand 0 "" "=rf")
3573         (call (mem:SI (match_operand 1 "memory_operand" "m"))
3574         (match_operand 2 "general_operand" "g")))
3575    (clobber (reg:SI 14))]
3576   "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
3577   "*
3578   return output_call_mem (&operands[1]);
3580 [(set_attr "length" "12")
3581  (set_attr "type" "call")])
3583 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
3584 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
3586 (define_insn "*call_symbol"
3587   [(call (mem:SI (match_operand:SI 0 "" "X"))
3588          (match_operand:SI 1 "general_operand" "g"))
3589    (clobber (reg:SI 14))]
3590   "GET_CODE (operands[0]) == SYMBOL_REF"
3591   "bl%?\\t%a0"
3592 [(set_attr "type" "call")])
3594 (define_insn "*call_value_symbol"
3595   [(set (match_operand 0 "s_register_operand" "=rf")
3596         (call (mem:SI (match_operand:SI 1 "" "X"))
3597         (match_operand:SI 2 "general_operand" "g")))
3598    (clobber (reg:SI 14))]
3599   "GET_CODE(operands[1]) == SYMBOL_REF"
3600   "bl%?\\t%a1"
3601 [(set_attr "type" "call")])
3603 ;; Often the return insn will be the same as loading from memory, so set attr
3604 (define_insn "return"
3605   [(return)]
3606   "USE_RETURN_INSN"
3607   "*
3609   extern int arm_ccfsm_state;
3611   if (arm_ccfsm_state == 2)
3612   {
3613     arm_ccfsm_state += 2;
3614     return \"\";
3615   }
3616   return output_return_instruction (NULL, TRUE);
3618 [(set_attr "type" "load")])
3620 (define_insn "*cond_return"
3621   [(set (pc)
3622         (if_then_else (match_operator 0 "comparison_operator"
3623                        [(reg 24) (const_int 0)])
3624                       (return)
3625                       (pc)))]
3626   "USE_RETURN_INSN"
3627   "*
3629   extern int arm_ccfsm_state;
3631   if (arm_ccfsm_state == 2)
3632   {
3633     arm_ccfsm_state += 2;
3634     return \"\";
3635   }
3636   return output_return_instruction (operands[0], TRUE);
3638 [(set_attr "conds" "use")
3639  (set_attr "type" "load")])
3641 (define_insn "*cond_return_inverted"
3642   [(set (pc)
3643         (if_then_else (match_operator 0 "comparison_operator"
3644                        [(reg 24) (const_int 0)])
3645                       (pc)
3646                       (return)))]
3647   "USE_RETURN_INSN"
3648   "*
3650   extern int arm_ccfsm_state;
3652   if (arm_ccfsm_state == 2)
3653   {
3654     arm_ccfsm_state += 2;
3655     return \"\";
3656   }
3657   return output_return_instruction 
3658         (gen_rtx (reverse_condition (GET_CODE (operands[0])),
3659                   GET_MODE (operands[0]), XEXP (operands[0], 0),
3660                   XEXP (operands[0], 1)),
3661          TRUE);
3663 [(set_attr "conds" "use")
3664  (set_attr "type" "load")])
3666 ;; Call subroutine returning any type.
3668 (define_expand "untyped_call"
3669   [(parallel [(call (match_operand 0 "" "")
3670                     (const_int 0))
3671               (match_operand 1 "" "")
3672               (match_operand 2 "" "")])]
3673   ""
3674   "
3676   int i;
3678   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
3680   for (i = 0; i < XVECLEN (operands[2], 0); i++)
3681     {
3682       rtx set = XVECEXP (operands[2], 0, i);
3683       emit_move_insn (SET_DEST (set), SET_SRC (set));
3684     }
3686   /* The optimizer does not know that the call sets the function value
3687      registers we stored in the result block.  We avoid problems by
3688      claiming that all hard registers are used and clobbered at this
3689      point.  */
3690   emit_insn (gen_blockage ());
3692   DONE;
3695 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
3696 ;; all of memory.  This blocks insns from being moved across this point.
3698 (define_insn "blockage"
3699   [(unspec_volatile [(const_int 0)] 0)]
3700   ""
3701   ""
3702 [(set_attr "length" "0")
3703  (set_attr "type" "block")])
3705 (define_expand "casesi"
3706   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
3707    (match_operand:SI 1 "immediate_operand" "")  ; lower bound
3708    (match_operand:SI 2 "immediate_operand" "")  ; total range
3709    (match_operand:SI 3 "" "")                   ; table label
3710    (match_operand:SI 4 "" "")]                  ; Out of range label
3711   ""
3712   "
3714   rtx reg;
3715   if (operands[1] != const0_rtx)
3716     {
3717       reg = gen_reg_rtx (SImode);
3718       emit_insn (gen_addsi3 (reg, operands[0],
3719                              GEN_INT (-INTVAL (operands[1]))));
3720       operands[0] = reg;
3721     }
3723   if (! const_ok_for_arm (INTVAL (operands[2])))
3724     operands[2] = force_reg (SImode, operands[2]);
3726   emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
3727                                        operands[4]));
3728   DONE;
3731 (define_insn "casesi_internal"
3732   [(set (pc)
3733         (if_then_else
3734          (leu (match_operand:SI 0 "s_register_operand" "r")
3735               (match_operand:SI 1 "arm_rhs_operand" "rI"))
3736          (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
3737                           (label_ref (match_operand 2 "" ""))))
3738          (label_ref (match_operand 3 "" ""))))]
3739   ""
3740   "*
3741   if (flag_pic)
3742     return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
3743   return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
3745 [(set_attr "conds" "clob")
3746  (set_attr "length" "12")])
3748 (define_insn "indirect_jump"
3749   [(set (pc)
3750         (match_operand:SI 0 "s_register_operand" "r"))]
3751   ""
3752   "mov%?\\t%|pc, %0\\t%@ indirect jump")
3754 (define_insn "*load_indirect_jump"
3755   [(set (pc)
3756         (match_operand:SI 0 "memory_operand" "m"))]
3757   ""
3758   "ldr%?\\t%|pc, %0\\t%@ indirect jump"
3759 [(set_attr "type" "load")])
3761 ;; Misc insns
3763 (define_insn "nop"
3764   [(const_int 0)]
3765   ""
3766   "mov%?\\tr0, r0\\t%@ nop")
3768 ;; Patterns to allow combination of arithmetic, cond code and shifts
3770 (define_insn "*arith_shiftsi"
3771   [(set (match_operand:SI 0 "s_register_operand" "=r")
3772         (match_operator:SI 1 "shiftable_operator"
3773           [(match_operator:SI 3 "shift_operator"
3774              [(match_operand:SI 4 "s_register_operand" "r")
3775               (match_operand:SI 5 "reg_or_int_operand" "rI")])
3776            (match_operand:SI 2 "s_register_operand" "r")]))]
3777   ""
3778   "%i1%?\\t%0, %2, %4%S3")
3780 (define_insn "*arith_shiftsi_compare0"
3781   [(set (reg:CC_NOOV 24)
3782         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3783                           [(match_operator:SI 3 "shift_operator"
3784                             [(match_operand:SI 4 "s_register_operand" "r")
3785                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
3786                            (match_operand:SI 2 "s_register_operand" "r")])
3787                          (const_int 0)))
3788    (set (match_operand:SI 0 "s_register_operand" "=r")
3789         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
3790                          (match_dup 2)]))]
3791   ""
3792   "%i1%?s\\t%0, %2, %4%S3"
3793 [(set_attr "conds" "set")])
3795 (define_insn "*arith_shiftsi_compare0_scratch"
3796   [(set (reg:CC_NOOV 24)
3797         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3798                           [(match_operator:SI 3 "shift_operator"
3799                             [(match_operand:SI 4 "s_register_operand" "r")
3800                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
3801                            (match_operand:SI 2 "s_register_operand" "r")])
3802                          (const_int 0)))
3803    (clobber (match_scratch:SI 0 "=r"))]
3804   ""
3805   "%i1%?s\\t%0, %2, %4%S3"
3806 [(set_attr "conds" "set")])
3808 (define_insn "*sub_shiftsi"
3809   [(set (match_operand:SI 0 "s_register_operand" "=r")
3810         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3811                   (match_operator:SI 2 "shift_operator"
3812                    [(match_operand:SI 3 "s_register_operand" "r")
3813                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
3814   ""
3815   "sub%?\\t%0, %1, %3%S2")
3817 (define_insn "*sub_shiftsi_compare0"
3818   [(set (reg:CC_NOOV 24)
3819         (compare:CC_NOOV
3820          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3821                    (match_operator:SI 2 "shift_operator"
3822                     [(match_operand:SI 3 "s_register_operand" "r")
3823                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
3824          (const_int 0)))
3825    (set (match_operand:SI 0 "s_register_operand" "=r")
3826         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
3827                                                  (match_dup 4)])))]
3828   ""
3829   "sub%?s\\t%0, %1, %3%S2"
3830 [(set_attr "conds" "set")])
3832 (define_insn "*sub_shiftsi_compare0_scratch"
3833   [(set (reg:CC_NOOV 24)
3834         (compare:CC_NOOV
3835          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3836                    (match_operator:SI 2 "shift_operator"
3837                     [(match_operand:SI 3 "s_register_operand" "r")
3838                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
3839          (const_int 0)))
3840    (clobber (match_scratch:SI 0 "=r"))]
3841   ""
3842   "sub%?s\\t%0, %1, %3%S2"
3843 [(set_attr "conds" "set")])
3845 ;; These variants of the above insns can occur if the first operand is the
3846 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
3847 ;; seem to be a way around it.  Most of the predicates have to be null
3848 ;; because the format can be generated part way through reload, so
3849 ;; if we don't match it as soon as it becomes available, reload doesn't know
3850 ;; how to reload pseudos that haven't got hard registers; the constraints will
3851 ;; sort everything out.
3853 (define_insn "*reload_mulsi3"
3854   [(set (match_operand:SI 0 "" "=&r")
3855         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
3856                            [(match_operand:SI 3 "" "r")
3857                             (match_operand:SI 4 "" "rM")])
3858                           (match_operand:SI 2 "" "r"))
3859                  (match_operand:SI 1 "const_int_operand" "n")))]
3860   "reload_in_progress"
3861   "*
3862   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
3863   operands[2] = operands[1];
3864   operands[1] = operands[0];
3865   return output_add_immediate (operands);
3867 ; we have no idea how long the add_immediate is, it could be up to 4.
3868 [(set_attr "length" "20")])
3870 (define_insn "*relaod_mulsi_compare0"
3871   [(set (reg:CC_NOOV 24)
3872         (compare:CC_NOOV (plus:SI
3873                           (plus:SI 
3874                            (match_operator:SI 5 "shift_operator"
3875                             [(match_operand:SI 3 "" "r")
3876                              (match_operand:SI 4 "" "rM")])
3877                            (match_operand:SI 1 "" "r"))
3878                           (match_operand:SI 2 "const_int_operand" "n"))
3879                          (const_int 0)))
3880    (set (match_operand:SI 0 "" "=&r")
3881         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
3882                           (match_dup 1))
3883                  (match_dup 2)))]
3884   "reload_in_progress"
3885   "*
3886   output_add_immediate (operands);
3887   return \"add%?s\\t%0, %0, %3%S5\";
3889 [(set_attr "conds" "set")
3890  (set_attr "length" "20")])
3892 (define_insn "*reload_mulsi_compare0_scratch"
3893   [(set (reg:CC_NOOV 24)
3894         (compare:CC_NOOV (plus:SI
3895                           (plus:SI 
3896                            (match_operator:SI 5 "shift_operator"
3897                             [(match_operand:SI 3 "" "r")
3898                              (match_operand:SI 4 "" "rM")])
3899                            (match_operand:SI 1 "" "r"))
3900                           (match_operand:SI 2 "const_int_operand" "n"))
3901                          (const_int 0)))
3902    (clobber (match_scratch:SI 0 "=&r"))]
3903   "reload_in_progress"
3904   "*
3905   output_add_immediate (operands);
3906   return \"add%?s\\t%0, %0, %3%S5\";
3908 [(set_attr "conds" "set")
3909  (set_attr "length" "20")])
3911 ;; These are similar, but are needed when the mla pattern contains the
3912 ;; eliminated register as operand 3.
3914 (define_insn "*reload_muladdsi"
3915   [(set (match_operand:SI 0 "" "=&r,&r")
3916         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
3917                                    (match_operand:SI 2 "" "r,r"))
3918                           (match_operand:SI 3 "" "r,r"))
3919                  (match_operand:SI 4 "const_int_operand" "n,n")))]
3920   "reload_in_progress"
3921   "*
3922   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
3923   operands[2] = operands[4];
3924   operands[1] = operands[0];
3925   return output_add_immediate (operands);
3927 [(set_attr "length" "20")
3928  (set_attr "type" "mult")])
3930 (define_insn "*reload_muladdsi_compare0"
3931   [(set (reg:CC_NOOV 24)
3932         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
3933                                             (match_operand:SI 3 "" "r")
3934                                             (match_operand:SI 4 "" "r"))
3935                                            (match_operand:SI 1 "" "r"))
3936                                   (match_operand:SI 2 "const_int_operand" "n"))
3937                          (const_int 0)))
3938    (set (match_operand:SI 0 "" "=&r")
3939         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
3940                  (match_dup 2)))]
3941   "reload_in_progress"
3942   "*
3943   output_add_immediate (operands);
3944   output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
3945   return \"\";
3947 [(set_attr "length" "20")
3948  (set_attr "conds" "set")
3949  (set_attr "type" "mult")])
3951 (define_insn "*reload_muladdsi_compare0_scratch"
3952   [(set (reg:CC_NOOV 24)
3953         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
3954                                             (match_operand:SI 3 "" "r")
3955                                             (match_operand:SI 4 "" "r"))
3956                                            (match_operand:SI 1 "" "r"))
3957                                   (match_operand:SI 2 "const_int_operand" "n"))
3958                          (const_int 0)))
3959    (clobber (match_scratch:SI 0 "=&r"))]
3960   "reload_in_progress"
3961   "*
3962   output_add_immediate (operands);
3963   return \"mla%?s\\t%0, %3, %4, %0\";
3965 [(set_attr "length" "20")
3966  (set_attr "conds" "set")
3967  (set_attr "type" "mult")])
3971 (define_insn "*and_scc"
3972   [(set (match_operand:SI 0 "s_register_operand" "=r")
3973         (and:SI (match_operator 1 "comparison_operator"
3974                  [(match_operand 3 "reversible_cc_register" "") (const_int 0)])
3975                 (match_operand:SI 2 "s_register_operand" "r")))]
3976   ""
3977   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
3978 [(set_attr "conds" "use")
3979  (set_attr "length" "8")])
3981 (define_insn "*ior_scc"
3982   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3983         (ior:SI (match_operator 2 "comparison_operator"
3984                  [(reg 24) (const_int 0)])
3985                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
3986   ""
3987   "@
3988    orr%d2\\t%0, %1, #1
3989    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
3990 [(set_attr "conds" "use")
3991  (set_attr "length" "4,8")])
3993 (define_insn "*compare_scc"
3994   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3995         (match_operator 1 "comparison_operator"
3996          [(match_operand:SI 2 "s_register_operand" "r,r")
3997           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
3998    (clobber (reg 24))]
3999   ""
4000   "*
4001   if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4002     return \"mov\\t%0, %2, lsr #31\";
4004   if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4005     return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4007   if (GET_CODE (operands[1]) == NE)
4008     {
4009       if (which_alternative == 1)
4010         return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4011       return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4012     }
4013   if (which_alternative == 1)
4014     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4015   else
4016     output_asm_insn (\"cmp\\t%2, %3\", operands);
4017   return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4019 [(set_attr "conds" "clob")
4020  (set_attr "length" "12")])
4022 (define_insn "*ior_compare_compare"
4023   [(set (match_operand:SI 0 "s_register_operand" "=&r")
4024         (ior:SI (match_operator 1 "comparison_operator"
4025                  [(match_operand:SI 2 "s_register_operand" "r")
4026                   (match_operand:SI 3 "arm_rhs_operand" "rI")])
4027                 (match_operator 4 "comparison_operator"
4028                  [(match_operand:SI 5 "s_register_operand" "r")
4029                   (match_operand:SI 6 "arm_rhs_operand" "rI")])))
4030    (clobber (reg 24))]
4031   ""
4032   "*
4034   int dominant = comparison_dominates_p (GET_CODE (operands[4]),
4035                                          GET_CODE (operands[1]));
4037   output_asm_insn (dominant ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
4038                    operands);
4039   output_asm_insn (\"mov\\t%0, #0\", operands);
4040   if (GET_CODE (operands[1]) == GET_CODE (operands[4])
4041       || comparison_dominates_p (GET_CODE (operands[1]),
4042                                  GET_CODE (operands[4]))
4043       || dominant)
4044     output_asm_insn (dominant ? \"cmp%D4\\t%2, %3\" : \"cmp%D1\\t%5,%6\",
4045                      operands);
4046   else
4047     output_asm_insn (\"mov%d1\\t%0, #1\;cmp\\t%5, %6\", operands);
4048   return dominant ? \"mov%d1\\t%0, #1\" : \"mov%d4\\t%0, #1\";
4051 [(set_attr "conds" "clob")
4052 ; worst case length
4053  (set_attr "length" "20")])
4055 (define_split
4056   [(set (pc)
4057         (if_then_else
4058          (match_operator 5 "equality_operator"
4059           [(ior:SI (match_operator 6 "comparison_operator"
4060                     [(match_operand:SI 0 "s_register_operand" "")
4061                      (match_operand:SI 1 "arm_add_operand" "")])
4062                    (match_operator 7 "comparison_operator"
4063                     [(match_operand:SI 2 "s_register_operand" "")
4064                      (match_operand:SI 3 "arm_add_operand" "")]))
4065           (const_int 0)])
4066          (label_ref (match_operand 4 "" ""))
4067          (pc)))
4068    (clobber (reg 24))]
4069   "(GET_CODE (operands[6]) == GET_CODE (operands[7])
4070     || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[7]))
4071     || comparison_dominates_p (GET_CODE (operands[7]), GET_CODE (operands[6])))"
4072   [(set (reg:CC 24)
4073         (compare:CC (ior:CC (match_op_dup 6
4074                              [(match_dup 0) (match_dup 1)])
4075                             (match_op_dup 7
4076                              [(match_dup 2) (match_dup 3)]))
4077                     (const_int 0)))
4078    (set (pc)
4079         (if_then_else (match_op_dup 5 [(reg:CC 24) (const_int 0)])
4080                       (label_ref (match_dup 4))
4081                       (pc)))]
4082   "
4084   enum rtx_code code = comparison_dominates_p (GET_CODE (operands[6]),
4085                                                GET_CODE (operands[7]))
4086                        ? GET_CODE (operands[7]) : GET_CODE (operands[6]);
4088   if (GET_CODE (operands[5]) == NE)
4089     operands[5] = gen_rtx (code, CCmode,
4090                            XEXP (operands[5], 0), XEXP (operands[5], 1));
4091   else
4092     operands[5] = gen_rtx (reverse_condition (code), CCmode,
4093                            XEXP (operands[5], 0), XEXP (operands[5], 1));
4097 ;; Don't match these patterns if we can use a conditional compare, since they
4098 ;; tell the final prescan branch eliminator code that full branch inlining
4099 ;; can't be done.
4101 (define_insn "*impossible_cond_compare"
4102   [(set (pc)
4103         (if_then_else
4104          (ne (ior:SI (match_operator 5 "comparison_operator"
4105                       [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4106                        (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4107                      (match_operator 6 "comparison_operator"
4108                       [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4109                        (match_operand:SI 3 "arm_rhs_operand" "rI,rI,L,L")]))
4110              (const_int 0))
4111          (label_ref (match_operand 4 "" ""))
4112          (pc)))
4113    (clobber (reg 24))]
4114   "!(GET_CODE (operands[5]) == GET_CODE (operands[6])
4115      || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[6]))
4116      || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[5])))"
4117   "*
4119   extern int arm_ccfsm_state;
4121   if (which_alternative & 1)
4122     output_asm_insn (\"cmn\\t%0, #%n1\;b%d5\\t%l4\", operands);
4123   else
4124     output_asm_insn (\"cmp\\t%0, %1\;b%d5\\t%l4\", operands);
4126   if (which_alternative >= 2)
4127     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4128   else
4129     output_asm_insn (\"cmp\\t%2, %3\", operands);
4131   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4132   {
4133     arm_ccfsm_state += 2;
4134     return \"\";
4135   }
4136   return \"b%d6\\t%l4\";
4138 [(set_attr "conds" "jump_clob")
4139  (set_attr "length" "16")])
4141 (define_insn "*condition_compare_ior"
4142   [(set (reg:CC 24)
4143         (compare:CC
4144          (ior:CC (match_operator 4 "comparison_operator"
4145                   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4146                    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4147                  (match_operator 5 "comparison_operator"
4148                   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4149                    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
4150          (const_int 0)))]
4151   "(GET_CODE (operands[4]) == GET_CODE (operands[5])
4152     || comparison_dominates_p (GET_CODE (operands[4]), GET_CODE (operands[5]))
4153     || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))"
4154   "*
4155   if (comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))
4156     {
4157       if (which_alternative >= 2)
4158         output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4159       else
4160         output_asm_insn (\"cmp\\t%2, %3\", operands);
4162       if (which_alternative & 1)
4163         return \"cmn%D5\\t%0, #%n1\";
4164       return \"cmp%D5\\t%0, %1\";
4165     }
4167   if (which_alternative & 1)
4168     output_asm_insn (\"cmn\\t%0, #%n1\", operands);
4169   else
4170     output_asm_insn (\"cmp\\t%0, %1\", operands);
4172   if (which_alternative >= 2)
4173     return \"cmn%D4\\t%2, #%n3\";
4174   return \"cmp%D4\\t%2, %3\";
4176 [(set_attr "conds" "set")
4177  (set_attr "length" "8")])
4179 (define_insn "*cond_move"
4180   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4181         (if_then_else (match_operator 3 "equality_operator"
4182                        [(match_operator 4 "comparison_operator"
4183                          [(reg 24) (const_int 0)])
4184                         (const_int 0)])
4185                       (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4186                       (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4187   ""
4188   "*
4189   if (GET_CODE (operands[3]) == NE)
4190     {
4191       if (which_alternative != 1)
4192         output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4193       if (which_alternative != 0)
4194         output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4195       return \"\";
4196     }
4197   if (which_alternative != 0)
4198     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4199   if (which_alternative != 1)
4200     output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4201   return \"\";
4203 [(set_attr "conds" "use")
4204  (set_attr "length" "4,4,8")])
4206 (define_insn "*cond_arith"
4207   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4208         (match_operator:SI 5 "shiftable_operator" 
4209          [(match_operator:SI 4 "comparison_operator"
4210            [(match_operand:SI 2 "s_register_operand" "r,r")
4211             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4212           (match_operand:SI 1 "s_register_operand" "0,?r")]))
4213    (clobber (reg 24))]
4214   ""
4215   "*
4216   if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4217     return \"%i5\\t%0, %1, %2, lsr #31\";
4219   output_asm_insn (\"cmp\\t%2, %3\", operands);
4220   if (GET_CODE (operands[5]) == AND)
4221     output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4222   else if (GET_CODE (operands[5]) == MINUS)
4223     output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4224   else if (which_alternative != 0)
4225     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4226   return \"%i5%d4\\t%0, %1, #1\";
4228 [(set_attr "conds" "clob")
4229  (set_attr "length" "12")])
4231 (define_insn "*cond_sub"
4232   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4233         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4234                   (match_operator:SI 4 "comparison_operator"
4235                    [(match_operand:SI 2 "s_register_operand" "r,r")
4236                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4237    (clobber (reg 24))]
4238   ""
4239   "*
4240   output_asm_insn (\"cmp\\t%2, %3\", operands);
4241   if (which_alternative != 0)
4242     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4243   return \"sub%d4\\t%0, %1, #1\";
4245 [(set_attr "conds" "clob")
4246  (set_attr "length" "8,12")])
4248 (define_insn "*and_scc_scc"
4249   [(set (match_operand:SI 0 "s_register_operand" "=&r")
4250         (and:SI (match_operator 1 "comparison_operator"
4251                  [(match_operand:SI 2 "s_register_operand" "r")
4252                   (match_operand:SI 3 "arm_rhs_operand" "rI")])
4253                 (match_operator 4 "comparison_operator"
4254                  [(match_operand:SI 5 "s_register_operand" "r")
4255                   (match_operand:SI 6 "arm_rhs_operand" "rI")])))
4256    (clobber (reg 24))]
4257   ""
4258   "*
4260   int dominant =
4261         comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
4262                                 reverse_condition (GET_CODE (operands[4])))
4263         ? 1 
4264         : comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
4265                                   reverse_condition (GET_CODE (operands[1])))
4266         ? 2 : 0;
4267   output_asm_insn (dominant == 2 ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
4268                        operands);
4269   output_asm_insn (\"mov\\t%0, #1\", operands);
4270   if (GET_CODE (operands[1]) == GET_CODE (operands[4]) || dominant)
4271     {
4272       output_asm_insn (dominant == 2 ? \"cmp%d4\\t%2, %3\"
4273                            : \"cmp%d1\\t%5, %6\", operands);
4274     }
4275   else
4276     {
4277       output_asm_insn (\"mov%D1\\t%0, #0\", operands);
4278       output_asm_insn (\"cmp\\t%5, %6\", operands);
4279     }
4280   return dominant == 2 ? \"mov%D1\\t%0, #0\" : \"mov%D4\\t%0, #0\";
4283 [(set_attr "conds" "clob")
4284  (set_attr "length" "20")])
4286 (define_split
4287   [(set (pc)
4288         (if_then_else (match_operator 1 "equality_operator"
4289                        [(and:SI (match_operator 2 "comparison_operator"
4290                                  [(match_operand:SI 3 "s_register_operand" "")
4291                                   (match_operand:SI 4 "arm_add_operand" "")])
4292                                 (match_operator 0 "comparison_operator"
4293                                  [(match_operand:SI 5 "s_register_operand" "")
4294                                   (match_operand:SI 6 "arm_add_operand" "")]))
4295                         (const_int 0)])
4296                       (label_ref (match_operand 7 "" ""))
4297                       (pc)))
4298    (clobber (reg 24))]
4299   "(GET_CODE (operands[2]) == GET_CODE (operands[0])
4300     || comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
4301                                reverse_condition (GET_CODE (operands[0])))
4302     || comparison_dominates_p (reverse_condition (GET_CODE (operands[0])),
4303                                reverse_condition (GET_CODE (operands[2]))))"
4304   [(set (reg:CC 24)
4305         (compare:CC (ior:CC (match_op_dup 2
4306                              [(match_dup 3) (match_dup 4)])
4307                             (match_op_dup 0
4308                              [(match_dup 5) (match_dup 6)]))
4309                     (const_int 0)))
4310    (set (pc)
4311         (if_then_else (match_op_dup 1 [(reg:CC 24) (const_int 0)])
4312                       (label_ref (match_dup 7))
4313                       (pc)))]
4314   "
4316   /* Use DeMorgans law to convert this into an IOR of the inverse conditions 
4317      This is safe since we only do it for integer comparisons. */
4318   enum rtx_code code = 
4319         comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
4320                                 reverse_condition (GET_CODE (operands[0])))
4321         ? GET_CODE (operands[0]) : GET_CODE (operands[2]);
4323   operands[2] = gen_rtx (reverse_condition (GET_CODE (operands[2])),
4324                          GET_MODE (operands[2]), operands[3], operands[4]);
4325   operands[0] = gen_rtx (reverse_condition (GET_CODE (operands[0])),
4326                          GET_MODE (operands[0]), operands[5], operands[6]);
4327   if (GET_CODE (operands[1]) == NE)
4328     operands[1] = gen_rtx (code, CCmode,
4329                            XEXP (operands[1], 0), XEXP (operands[1], 1));
4330   else
4331     operands[1] = gen_rtx (reverse_condition (code), CCmode,
4332                            XEXP (operands[1], 0), XEXP (operands[1], 1));
4336 ;; Don't match these patterns if we can use a conditional compare, since they
4337 ;; tell the final prescan branch eliminator code that full branch inlining
4338 ;; can't be done.
4340 (define_insn "*impossible_cond_branch_and"
4341   [(set (pc)
4342         (if_then_else
4343          (eq (and:SI (match_operator 1 "comparison_operator"
4344                       [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4345                        (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L")])
4346                      (match_operator 4 "comparison_operator"
4347                       [(match_operand:SI 5 "s_register_operand" "r,r,r,r")
4348                        (match_operand:SI 6 "arm_rhs_operand" "rI,rI,L,L")]))
4349              (const_int 0))
4350          (label_ref (match_operand 0 "" ""))
4351          (pc)))
4352    (clobber (reg 24))]
4353   "!(GET_CODE (operands[1]) == GET_CODE (operands[4])
4354      || comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
4355                                 reverse_condition (GET_CODE (operands[4])))
4356      || comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
4357                                 reverse_condition (GET_CODE (operands[1]))))"
4358   "*
4360   extern int arm_ccfsm_state;
4362   if (which_alternative & 1)
4363     output_asm_insn (\"cmn\\t%2, #%n3\;b%D1\\t%l0\", operands);
4364   else
4365     output_asm_insn (\"cmp\\t%2, %3\;b%D1\\t%l0\", operands);
4367   if (which_alternative >= 2)
4368     output_asm_insn (\"cmn\\t%5, #%n6\", operands);
4369   else
4370     output_asm_insn (\"cmp\\t%5, %6\", operands);
4372   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4373   {
4374     arm_ccfsm_state += 2;
4375     return \"\";
4376   }
4377   return \"b%D4\\t%l0\";
4379 [(set_attr "conds" "jump_clob")
4380  (set_attr "length" "16")])
4382 (define_insn "*negscc"
4383   [(set (match_operand:SI 0 "s_register_operand" "=r")
4384         (neg:SI (match_operator 3 "comparison_operator"
4385                  [(match_operand:SI 1 "s_register_operand" "r")
4386                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4387    (clobber (reg 24))]
4388   ""
4389   "*
4390   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4391     return \"mov\\t%0, %1, asr #31\";
4393   if (GET_CODE (operands[3]) == NE)
4394     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4396   if (GET_CODE (operands[3]) == GT)
4397     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4399   output_asm_insn (\"cmp\\t%1, %2\", operands);
4400   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4401   return \"mvn%d3\\t%0, #0\";
4403 [(set_attr "conds" "clob")
4404  (set_attr "length" "12")])
4406 (define_insn "movcond"
4407   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4408         (if_then_else:SI
4409          (match_operator 5 "comparison_operator"
4410           [(match_operand:SI 3 "s_register_operand" "r,r,r")
4411            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4412          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4413          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4414    (clobber (reg 24))]
4415   ""
4416   "*
4417   if (GET_CODE (operands[5]) == LT
4418       && (operands[4] == const0_rtx))
4419     {
4420       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4421         {
4422           if (operands[2] == const0_rtx)
4423             return \"and\\t%0, %1, %3, asr #31\";
4424           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4425         }
4426       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4427         {
4428           if (operands[1] == const0_rtx)
4429             return \"bic\\t%0, %2, %3, asr #31\";
4430           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4431         }
4432       /* The only case that falls through to here is when both ops 1 & 2
4433          are constants */
4434     }
4436   if (GET_CODE (operands[5]) == GE
4437       && (operands[4] == const0_rtx))
4438     {
4439       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4440         {
4441           if (operands[2] == const0_rtx)
4442             return \"bic\\t%0, %1, %3, asr #31\";
4443           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4444         }
4445       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4446         {
4447           if (operands[1] == const0_rtx)
4448             return \"and\\t%0, %2, %3, asr #31\";
4449           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4450         }
4451       /* The only case that falls through to here is when both ops 1 & 2
4452          are constants */
4453     }
4454   if (GET_CODE (operands[4]) == CONST_INT
4455       && !const_ok_for_arm (INTVAL (operands[4])))
4456     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4457   else
4458     output_asm_insn (\"cmp\\t%3, %4\", operands);
4459   if (which_alternative != 0)
4460     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4461   if (which_alternative != 1)
4462     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4463   return \"\";
4465 [(set_attr "conds" "clob")
4466  (set_attr "length" "8,8,12")])
4468 (define_insn "*ifcompare_arith_arith"
4469   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4470         (if_then_else:SI (match_operator 9 "comparison_operator"
4471                           [(match_operand:SI 5 "s_register_operand" "r,r")
4472                            (match_operand:SI 6 "arm_add_operand" "rI,L")])
4473                          (match_operator:SI 8 "shiftable_operator"
4474                           [(match_operand:SI 1 "s_register_operand" "r,r")
4475                            (match_operand:SI 2 "arm_rhs_operand" "rI,rI")])
4476                          (match_operator:SI 7 "shiftable_operator"
4477                           [(match_operand:SI 3 "s_register_operand" "r,r")
4478                            (match_operand:SI 4 "arm_rhs_operand" "rI,rI")])))
4479    (clobber (reg 24))]
4480   ""
4481   "@
4482    cmp\\t%5, %6\;%I8%d9\\t%0, %1, %2\;%I7%D9\\t%0, %3, %4
4483    cmn\\t%5, #%n6\;%I8%d9\\t%0, %1, %2\;%I7%D9\\t%0, %3, %4"
4484 [(set_attr "conds" "clob")
4485  (set_attr "length" "12")])
4487 (define_insn "*ifcompare_arith_move"
4488   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4489         (if_then_else:SI (match_operator 6 "comparison_operator"
4490                           [(match_operand:SI 2 "s_register_operand" "r,r")
4491                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
4492                          (match_operator:SI 7 "shiftable_operator"
4493                           [(match_operand:SI 4 "s_register_operand" "r,r")
4494                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
4495                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4496    (clobber (reg 24))]
4497   ""
4498   "*
4499   /* If we have an operation where (op x 0) is the identity operation and
4500      the conditional operator is LT or GE and we are comparing against zero and
4501      everything is in registers then we can do this in two instructions */
4502   if (operands[3] == const0_rtx
4503       && GET_CODE (operands[7]) != AND
4504       && GET_CODE (operands[5]) == REG
4505       && GET_CODE (operands[1]) == REG 
4506       && REGNO (operands[1]) == REGNO (operands[4])
4507       && REGNO (operands[4]) != REGNO (operands[0]))
4508     {
4509       if (GET_CODE (operands[6]) == LT)
4510         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4511       else if (GET_CODE (operands[6]) == GE)
4512         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4513     }
4514   if (GET_CODE (operands[3]) == CONST_INT
4515       && !const_ok_for_arm (INTVAL (operands[3])))
4516     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4517   else
4518     output_asm_insn (\"cmp\\t%2, %3\", operands);
4519   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
4520   if (which_alternative != 0)
4521     {
4522       if (GET_CODE (operands[1]) == MEM)
4523         return \"ldr%D6\\t%0, %1\";
4524       else
4525         return \"mov%D6\\t%0, %1\";
4526     }
4527   return \"\";
4529 [(set_attr "conds" "clob")
4530  (set_attr "length" "8,12")])
4532 (define_insn "*ifcompare_move_arith"
4533   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4534         (if_then_else:SI (match_operator 6 "comparison_operator"
4535                           [(match_operand:SI 4 "s_register_operand" "r,r")
4536                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4537                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4538                          (match_operator:SI 7 "shiftable_operator"
4539                           [(match_operand:SI 2 "s_register_operand" "r,r")
4540                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4541    (clobber (reg 24))]
4542   ""
4543   "*
4544   /* If we have an operation where (op x 0) is the identity operation and
4545      the conditional operator is LT or GE and we are comparing against zero and
4546      everything is in registers then we can do this in two instructions */
4547   if (operands[5] == const0_rtx
4548       && GET_CODE (operands[7]) != AND
4549       && GET_CODE (operands[3]) == REG
4550       && GET_CODE (operands[1]) == REG 
4551       && REGNO (operands[1]) == REGNO (operands[2])
4552       && REGNO (operands[2]) != REGNO (operands[0]))
4553     {
4554       if (GET_CODE (operands[6]) == GE)
4555         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4556       else if (GET_CODE (operands[6]) == LT)
4557         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4558     }
4560   if (GET_CODE (operands[5]) == CONST_INT
4561       && !const_ok_for_arm (INTVAL (operands[5])))
4562     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4563   else
4564     output_asm_insn (\"cmp\\t%4, %5\", operands);
4566   if (which_alternative != 0)
4567     {
4568       if (GET_CODE (operands[1]) == MEM)
4569         output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4570       else
4571         output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4572     }
4573   return \"%I7%D6\\t%0, %2, %3\";
4575 [(set_attr "conds" "clob")
4576  (set_attr "length" "8,12")])
4578 (define_insn "*ifcompare_plus_move"
4579   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4580         (if_then_else:SI (match_operator 6 "comparison_operator"
4581                           [(match_operand:SI 4 "s_register_operand" "r,r")
4582                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4583                          (plus:SI
4584                           (match_operand:SI 2 "s_register_operand" "r,r")
4585                           (match_operand:SI 3 "arm_add_operand" "rL,rL"))
4586                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4587    (clobber (reg 24))]
4588   ""
4589   "*
4591   if (GET_CODE (operands[5]) == CONST_INT
4592       && !const_ok_for_arm (INTVAL (operands[5])))
4593     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4594   else
4595     output_asm_insn (\"cmp\\t%4, %5\", operands);
4596   if (GET_CODE (operands[3]) == CONST_INT
4597       && !const_ok_for_arm (INTVAL (operands[3])))
4598     output_asm_insn (\"sub%d6\\t%0, %2, #%n3\", operands);
4599   else
4600     output_asm_insn (\"add%d6\\t%0, %2, %3\", operands);
4601   if (which_alternative != 0)
4602     {
4603       if (GET_CODE (operands[1]) == MEM)
4604         output_asm_insn (\"ldr%D6\\t%0, %1\", operands);
4605       else
4606         output_asm_insn (\"mov%D6\\t%0, %1\", operands);
4607     }
4608   return \"\";
4611 [(set_attr "conds" "clob")
4612  (set_attr "length" "8,12")])
4614 (define_insn "*ifcompare_move_plus"
4615   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4616         (if_then_else:SI (match_operator 6 "comparison_operator"
4617                           [(match_operand:SI 4 "s_register_operand" "r,r")
4618                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4619                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4620                          (plus:SI
4621                           (match_operand:SI 2 "s_register_operand" "r,r")
4622                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4623    (clobber (reg 24))]
4624   ""
4625   "*
4627   if (GET_CODE (operands[5]) == CONST_INT
4628       && !const_ok_for_arm (INTVAL (operands[5])))
4629     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4630   else
4631     output_asm_insn (\"cmp\\t%4, %5\", operands);
4632   if (GET_CODE (operands[3]) == CONST_INT
4633       && !const_ok_for_arm (INTVAL (operands[3])))
4634     output_asm_insn (\"sub%D6\\t%0, %2, #%n3\", operands);
4635   else
4636     output_asm_insn (\"add%D6\\t%0, %2, %3\", operands);
4637   if (which_alternative != 0)
4638     {
4639       if (GET_CODE (operands[6]) == MEM)
4640         output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4641       else
4642         output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4643     }
4644   return \"\";
4647 [(set_attr "conds" "clob")
4648  (set_attr "length" "8,12")])
4650 (define_insn "ifcompare_move_not"
4651   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4652         (if_then_else:SI (match_operator 5 "comparison_operator"
4653                           [(match_operand:SI 3 "s_register_operand" "r,r")
4654                            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
4655                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4656                          (not:SI
4657                           (match_operand:SI 2 "s_register_operand" "r,r"))))
4658    (clobber (reg 24))]
4659   ""
4660   "#"
4661 [(set_attr "conds" "clob")
4662  (set_attr "length" "8,12")])
4664 (define_insn "*ifcompare_not_move"
4665   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4666         (if_then_else:SI 
4667          (match_operator 5 "comparison_operator"
4668           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4669            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4670          (not:SI
4671           (match_operand:SI 2 "s_register_operand" "r,r,r,r"))
4672          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4673    (clobber (reg 24))]
4674   ""
4675   "@
4676    cmp\\t%3, %4\;mvn%d5\\t%0, %2
4677    cmn\\t%3, #%n4\;mvn%d5\\t%0, %2
4678    cmp\\t%3, %4\;mov%D5\\t%0, %1\;mvn%d5\\t%0, %2
4679    cmn\\t%3, #%n4\;mov%D5\\t%0, %1\;mvn%d5\\t%0, %2"
4680 [(set_attr "conds" "clob")
4681  (set_attr "length" "8,8,12,12")])
4683 (define_insn "*ifcompare_shift_move"
4684   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4685         (if_then_else:SI
4686          (match_operator 6 "comparison_operator"
4687           [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
4688            (match_operand:SI 5 "arm_add_operand" "rI,L,rI,L")])
4689          (match_operator:SI 7 "shift_operator"
4690           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4691            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM,rM")])
4692          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4693    (clobber (reg 24))]
4694   ""
4695   "@
4696    cmp\\t%4, %5\;mov%d6\\t%0, %2%S7
4697    cmn\\t%4, #%n5\;mov%d6\\t%0, %2%S7
4698    cmp\\t%4, %5\;mov%D6\\t%0, %1\;mov%d6\\t%0, %2%S7
4699    cmn\\t%4, #%n5\;mov%D6\\t%0, %1\;mov%d6\\t%0, %2%S7"
4700 [(set_attr "conds" "clob")
4701  (set_attr "length" "8,8,12,12")])
4703 (define_insn "ifcompare_move_shift"
4704   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4705         (if_then_else:SI
4706          (match_operator 6 "comparison_operator"
4707           [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
4708            (match_operand:SI 5 "arm_add_operand" "rI,L,rI,L")])
4709          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4710          (match_operator:SI 7 "shift_operator"
4711           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4712            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM,rM")])))
4713    (clobber (reg 24))]
4714   ""
4715   "@
4716    cmp\\t%4, %5\;mov%D6\\t%0, %2%S7
4717    cmn\\t%4, #%n5\;mov%D6\\t%0, %2%S7
4718    cmp\\t%4, %5\;mov%d6\\t%0, %1\;mov%D6\\t%0, %2%S7
4719    cmn\\t%4, #%n5\;mov%d6\\t%0, %1\;mov%D6\\t%0, %2%S7"
4720 [(set_attr "conds" "clob")
4721  (set_attr "length" "8,8,12,12")])
4723 (define_insn "*ifcompare_shift_shift"
4724   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4725         (if_then_else:SI
4726          (match_operator 7 "comparison_operator"
4727           [(match_operand:SI 5 "s_register_operand" "r,r")
4728            (match_operand:SI 6 "arm_add_operand" "rI,L")])
4729          (match_operator:SI 8 "shift_operator"
4730           [(match_operand:SI 1 "s_register_operand" "r,r")
4731            (match_operand:SI 2 "arm_rhs_operand" "rM,rM")])
4732          (match_operator:SI 9 "shift_operator"
4733           [(match_operand:SI 3 "s_register_operand" "r,r")
4734            (match_operand:SI 4 "arm_rhs_operand" "rI,rI")])))
4735    (clobber (reg 24))]
4736   ""
4737   "@
4738    cmp\\t%5, %6\;mov%d7\\t%0, %1%S8\;mov%D7\\t%0, %3%S9
4739    cmn\\t%5, #%n6\;mov%d7\\t%0, %1%S8\;mov%D7\\t%0, %3%S9"
4740 [(set_attr "conds" "clob")
4741  (set_attr "length" "12")])
4743 (define_insn "*ifcompare_not_arith"
4744   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4745         (if_then_else:SI
4746          (match_operator 6 "comparison_operator"
4747           [(match_operand:SI 4 "s_register_operand" "r,r")
4748            (match_operand:SI 5 "arm_add_operand" "rI,L")])
4749          (not:SI (match_operand:SI 1 "s_register_operand" "r,r"))
4750          (match_operator:SI 7 "shiftable_operator"
4751           [(match_operand:SI 2 "s_register_operand" "r,r")
4752            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4753    (clobber (reg 24))]
4754   ""
4755   "@
4756    cmp\\t%4, %5\;mvn%d6\\t%0, %1\;%I7%D6\\t%0, %2, %3
4757    cmn\\t%4, #%n5\;mvn%d6\\t%0, %1\;%I7%D6\\t%0, %2, %3"
4758 [(set_attr "conds" "clob")
4759  (set_attr "length" "12")])
4761 (define_insn "*if_compare_arith_not"
4762   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4763         (if_then_else:SI
4764          (match_operator 6 "comparison_operator"
4765           [(match_operand:SI 4 "s_register_operand" "r,r")
4766            (match_operand:SI 5 "arm_add_operand" "rI,L")])
4767          (match_operator:SI 7 "shiftable_operator"
4768           [(match_operand:SI 2 "s_register_operand" "r,r")
4769            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4770          (not:SI (match_operand:SI 1 "s_register_operand" "r,r"))))
4771    (clobber (reg 24))]
4772   ""
4773   "@
4774    cmp\\t%4, %5\;mvn%D6\\t%0, %1\;%I7%d6\\t%0, %2, %3
4775    cmn\\t%4, #%n5\;mvn%D6\\t%0, %1\;%I7%d6\\t%0, %2, %3"
4776 [(set_attr "conds" "clob")
4777  (set_attr "length" "12")])
4779 (define_insn "*ifcompare_neg_move"
4780   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4781         (if_then_else:SI
4782          (match_operator 5 "comparison_operator"
4783           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4784            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4785          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r"))
4786          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4787    (clobber (reg:CC 24))]
4788   ""
4789   "@
4790    cmp\\t%3, %4\;rsb%d5\\t%0, %2, #0
4791    cmn\\t%3, #%n4\;rsb%d5\\t%0, %2, #0
4792    cmp\\t%3, %4\;mov%D5\\t%0, %1\;rsb%d5\\t%0, %2, #0
4793    cmn\\t%3, #%n4\;mov%D5\\t%0, %1\;rsb%d5\\t%0, %2, #0"
4794 [(set_attr "conds" "clob")
4795  (set_attr "length" "8,8,12,12")])
4797 (define_insn "*ifcompare_move_neg"
4798   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4799         (if_then_else:SI
4800          (match_operator 5 "comparison_operator"
4801           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4802            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4803          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4804          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r"))))
4805    (clobber (reg:CC 24))]
4806   ""
4807   "@
4808    cmp\\t%3, %4\;rsb%D5\\t%0, %2, #0
4809    cmn\\t%3, #%n4\;rsb%D5\\t%0, %2, #0
4810    cmp\\t%3, %4\;mov%d5\\t%0, %1\;rsb%D5\\t%0, %2, #0
4811    cmn\\t%3, #%n4\;mov%d5\\t%0, %1\;rsb%D5\\t%0, %2, #0"
4812 [(set_attr "conds" "clob")
4813  (set_attr "length" "8,8,12,12")])
4815 (define_insn "*arith_adjacentmem"
4816   [(set (match_operand:SI 0 "s_register_operand" "=r")
4817         (match_operator:SI 1 "shiftable_operator"
4818          [(match_operand:SI 2 "memory_operand" "m")
4819           (match_operand:SI 3 "memory_operand" "m")]))
4820    (clobber (match_scratch:SI 4 "=r"))]
4821   "adjacent_mem_locations (operands[2], operands[3])"
4822   "*
4824   rtx ldm[3];
4825   rtx arith[4];
4826   int val1 = 0, val2 = 0;
4828   if (REGNO (operands[0]) > REGNO (operands[4]))
4829     {
4830       ldm[1] = operands[4];
4831       ldm[2] = operands[0];
4832     }
4833   else
4834     {
4835       ldm[1] = operands[0];
4836       ldm[2] = operands[4];
4837     }
4838   if (GET_CODE (XEXP (operands[2], 0)) != REG)
4839     val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
4840   if (GET_CODE (XEXP (operands[3], 0)) != REG)
4841     val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
4842   arith[0] = operands[0];
4843   arith[3] = operands[1];
4844   if (val1 < val2)
4845     {
4846       arith[1] = ldm[1];
4847       arith[2] = ldm[2];
4848     }
4849   else
4850     {
4851       arith[1] = ldm[2];
4852       arith[2] = ldm[1];
4853     }
4854   if (val1 && val2)
4855     {
4856       rtx ops[3];
4857       ldm[0] = ops[0] = operands[4];
4858       ops[1] = XEXP (XEXP (operands[2], 0), 0);
4859       ops[2] = XEXP (XEXP (operands[2], 0), 1);
4860       output_add_immediate (ops);
4861       if (val1 < val2)
4862         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4863       else
4864         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4865     }
4866   else if (val1)
4867     {
4868       ldm[0] = XEXP (operands[3], 0);
4869       if (val1 < val2)
4870         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4871       else
4872         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4873     }
4874   else
4875     {
4876       ldm[0] = XEXP (operands[2], 0);
4877       if (val1 < val2)
4878         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4879       else
4880         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4881     }
4882   output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
4883   return \"\";
4886 [(set_attr "length" "12")
4887  (set_attr "type" "load")])
4889 ;; the arm can support extended pre-inc instructions
4891 ;; In all these cases, we use operands 0 and 1 for the register being
4892 ;; incremented because those are the operands that local-alloc will
4893 ;; tie and these are the pair most likely to be tieable (and the ones
4894 ;; that will benefit the most).
4896 ;; We reject the frame pointer if it occurs anywhere in these patterns since
4897 ;; elimination will cause too many headaches.
4899 (define_insn "*strqi_preinc"
4900   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4901                          (match_operand:SI 2 "index_operand" "rJ")))
4902         (match_operand:QI 3 "s_register_operand" "r"))
4903    (set (match_operand:SI 0 "s_register_operand" "=r")
4904         (plus:SI (match_dup 1) (match_dup 2)))]
4905   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4906    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4907    && (GET_CODE (operands[2]) != REG
4908        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4909   "str%?b\\t%3, [%0, %2]!"
4910 [(set_attr "type" "store1")])
4912 (define_insn "*strqi_predec"
4913   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4914                           (match_operand:SI 2 "s_register_operand" "r")))
4915         (match_operand:QI 3 "s_register_operand" "r"))
4916    (set (match_operand:SI 0 "s_register_operand" "=r")
4917         (minus:SI (match_dup 1) (match_dup 2)))]
4918   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4919    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4920    && (GET_CODE (operands[2]) != REG
4921        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4922   "str%?b\\t%3, [%0, -%2]!"
4923 [(set_attr "type" "store1")])
4925 (define_insn "*loadqi_preinc"
4926   [(set (match_operand:QI 3 "s_register_operand" "=r")
4927         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4928                          (match_operand:SI 2 "index_operand" "rJ"))))
4929    (set (match_operand:SI 0 "s_register_operand" "=r")
4930         (plus:SI (match_dup 1) (match_dup 2)))]
4931   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4932    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4933    && (GET_CODE (operands[2]) != REG
4934        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4935   "ldr%?b\\t%3, [%0, %2]!"
4936 [(set_attr "type" "load")])
4938 (define_insn "*loadqi_predec"
4939   [(set (match_operand:QI 3 "s_register_operand" "=r")
4940         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4941                           (match_operand:SI 2 "s_register_operand" "r"))))
4942    (set (match_operand:SI 0 "s_register_operand" "=r")
4943         (minus:SI (match_dup 1) (match_dup 2)))]
4944   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4945    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4946    && (GET_CODE (operands[2]) != REG
4947        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4948   "ldr%?b\\t%3, [%0, -%2]!"
4949 [(set_attr "type" "load")])
4951 (define_insn "*loadqisi_preinc"
4952   [(set (match_operand:SI 3 "s_register_operand" "=r")
4953         (zero_extend:SI
4954          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4955                           (match_operand:SI 2 "index_operand" "rJ")))))
4956    (set (match_operand:SI 0 "s_register_operand" "=r")
4957         (plus:SI (match_dup 1) (match_dup 2)))]
4958   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4959    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4960    && (GET_CODE (operands[2]) != REG
4961        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4962   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
4963 [(set_attr "type" "load")])
4965 (define_insn "*loadqisi_predec"
4966   [(set (match_operand:SI 3 "s_register_operand" "=r")
4967         (zero_extend:SI
4968          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4969                            (match_operand:SI 2 "s_register_operand" "r")))))
4970    (set (match_operand:SI 0 "s_register_operand" "=r")
4971         (minus:SI (match_dup 1) (match_dup 2)))]
4972   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4973    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4974    && (GET_CODE (operands[2]) != REG
4975        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4976   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
4977 [(set_attr "type" "load")])
4979 (define_insn "*strsi_preinc"
4980   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4981                          (match_operand:SI 2 "index_operand" "rJ")))
4982         (match_operand:SI 3 "s_register_operand" "r"))
4983    (set (match_operand:SI 0 "s_register_operand" "=r")
4984         (plus:SI (match_dup 1) (match_dup 2)))]
4985   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4986    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4987    && (GET_CODE (operands[2]) != REG
4988        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4989   "str%?\\t%3, [%0, %2]!"
4990 [(set_attr "type" "store1")])
4992 (define_insn "*strqi_predec"
4993   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4994                           (match_operand:SI 2 "s_register_operand" "r")))
4995         (match_operand:SI 3 "s_register_operand" "r"))
4996    (set (match_operand:SI 0 "s_register_operand" "=r")
4997         (minus:SI (match_dup 1) (match_dup 2)))]
4998   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4999    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5000    && (GET_CODE (operands[2]) != REG
5001        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5002   "str%?\\t%3, [%0, -%2]!"
5003 [(set_attr "type" "store1")])
5005 (define_insn "*loadsi_preinc"
5006   [(set (match_operand:SI 3 "s_register_operand" "=r")
5007         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5008                          (match_operand:SI 2 "index_operand" "rJ"))))
5009    (set (match_operand:SI 0 "s_register_operand" "=r")
5010         (plus:SI (match_dup 1) (match_dup 2)))]
5011   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5012    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5013    && (GET_CODE (operands[2]) != REG
5014        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5015   "ldr%?\\t%3, [%0, %2]!"
5016 [(set_attr "type" "load")])
5018 (define_insn "*loadsi_predec"
5019   [(set (match_operand:SI 3 "s_register_operand" "=r")
5020         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5021                           (match_operand:SI 2 "s_register_operand" "r"))))
5022    (set (match_operand:SI 0 "s_register_operand" "=r")
5023         (minus:SI (match_dup 1) (match_dup 2)))]
5024   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5025    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5026    && (GET_CODE (operands[2]) != REG
5027        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5028   "ldr%?\\t%3, [%0, -%2]!"
5029 [(set_attr "type" "load")])
5031 (define_insn "*loadhi_preinc"
5032   [(set (match_operand:HI 3 "s_register_operand" "=r")
5033         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5034                          (match_operand:SI 2 "index_operand" "rJ"))))
5035    (set (match_operand:SI 0 "s_register_operand" "=r")
5036         (plus:SI (match_dup 1) (match_dup 2)))]
5037   "(! BYTES_BIG_ENDIAN)
5038    && ! TARGET_SHORT_BY_BYTES
5039    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5040    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5041    && (GET_CODE (operands[2]) != REG
5042        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5043   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5044 [(set_attr "type" "load")])
5046 (define_insn "*loadhi_predec"
5047   [(set (match_operand:HI 3 "s_register_operand" "=r")
5048         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5049                           (match_operand:SI 2 "s_register_operand" "r"))))
5050    (set (match_operand:SI 0 "s_register_operand" "=r")
5051         (minus:SI (match_dup 1) (match_dup 2)))]
5052   "(!BYTES_BIG_ENDIAN)
5053    && ! TARGET_SHORT_BY_BYTES
5054    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5055    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5056    && (GET_CODE (operands[2]) != REG
5057        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5058   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5059 [(set_attr "type" "load")])
5061 (define_insn "*strqi_shiftpreinc"
5062   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5063                           [(match_operand:SI 3 "s_register_operand" "r")
5064                            (match_operand:SI 4 "const_shift_operand" "n")])
5065                          (match_operand:SI 1 "s_register_operand" "0")))
5066         (match_operand:QI 5 "s_register_operand" "r"))
5067    (set (match_operand:SI 0 "s_register_operand" "=r")
5068         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5069                  (match_dup 1)))]
5070   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5071    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5072    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5073   "str%?b\\t%5, [%0, %3%S2]!"
5074 [(set_attr "type" "store1")])
5076 (define_insn "*strqi_shiftpredec"
5077   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5078                           (match_operator:SI 2 "shift_operator"
5079                            [(match_operand:SI 3 "s_register_operand" "r")
5080                             (match_operand:SI 4 "const_shift_operand" "n")])))
5081         (match_operand:QI 5 "s_register_operand" "r"))
5082    (set (match_operand:SI 0 "s_register_operand" "=r")
5083         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5084                                                  (match_dup 4)])))]
5085   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5086    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5087    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5088   "str%?b\\t%5, [%0, -%3%S2]!"
5089 [(set_attr "type" "store1")])
5091 (define_insn "*loadqi_shiftpreinc"
5092   [(set (match_operand:QI 5 "s_register_operand" "=r")
5093         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5094                           [(match_operand:SI 3 "s_register_operand" "r")
5095                            (match_operand:SI 4 "const_shift_operand" "n")])
5096                          (match_operand:SI 1 "s_register_operand" "0"))))
5097    (set (match_operand:SI 0 "s_register_operand" "=r")
5098         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5099                  (match_dup 1)))]
5100   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5101    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5102    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5103   "ldr%?b\\t%5, [%0, %3%S2]!"
5104 [(set_attr "type" "load")])
5106 (define_insn "*loadqi_shiftpredec"
5107   [(set (match_operand:QI 5 "s_register_operand" "=r")
5108         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5109                           (match_operator:SI 2 "shift_operator"
5110                            [(match_operand:SI 3 "s_register_operand" "r")
5111                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5112    (set (match_operand:SI 0 "s_register_operand" "=r")
5113         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5114                                                  (match_dup 4)])))]
5115   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5116    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5117    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5118   "ldr%?b\\t%5, [%0, -%3%S2]!"
5119 [(set_attr "type" "load")])
5121 (define_insn "*strsi_shiftpreinc"
5122   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5123                           [(match_operand:SI 3 "s_register_operand" "r")
5124                            (match_operand:SI 4 "const_shift_operand" "n")])
5125                          (match_operand:SI 1 "s_register_operand" "0")))
5126         (match_operand:SI 5 "s_register_operand" "r"))
5127    (set (match_operand:SI 0 "s_register_operand" "=r")
5128         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5129                  (match_dup 1)))]
5130   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5131    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5132    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5133   "str%?\\t%5, [%0, %3%S2]!"
5134 [(set_attr "type" "store1")])
5136 (define_insn "*strsi_shiftpredec"
5137   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5138                           (match_operator:SI 2 "shift_operator"
5139                            [(match_operand:SI 3 "s_register_operand" "r")
5140                             (match_operand:SI 4 "const_shift_operand" "n")])))
5141         (match_operand:SI 5 "s_register_operand" "r"))
5142    (set (match_operand:SI 0 "s_register_operand" "=r")
5143         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5144                                                  (match_dup 4)])))]
5145   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5146    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5147    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5148   "str%?\\t%5, [%0, -%3%S2]!"
5149 [(set_attr "type" "store1")])
5151 (define_insn "*loadqi_shiftpreinc"
5152   [(set (match_operand:SI 5 "s_register_operand" "=r")
5153         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5154                           [(match_operand:SI 3 "s_register_operand" "r")
5155                            (match_operand:SI 4 "const_shift_operand" "n")])
5156                          (match_operand:SI 1 "s_register_operand" "0"))))
5157    (set (match_operand:SI 0 "s_register_operand" "=r")
5158         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5159                  (match_dup 1)))]
5160   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5161    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5162    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5163   "ldr%?\\t%5, [%0, %3%S2]!"
5164 [(set_attr "type" "load")])
5166 (define_insn "*loadqi_shiftpredec"
5167   [(set (match_operand:SI 5 "s_register_operand" "=r")
5168         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5169                           (match_operator:SI 2 "shift_operator"
5170                            [(match_operand:SI 3 "s_register_operand" "r")
5171                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5172    (set (match_operand:SI 0 "s_register_operand" "=r")
5173         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5174                                                  (match_dup 4)])))]
5175   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5176    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5177    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5178   "ldr%?\\t%5, [%0, -%3%S2]!"
5179 [(set_attr "type" "load")])
5181 (define_insn "*loadhi_shiftpreinc"
5182   [(set (match_operand:HI 5 "s_register_operand" "=r")
5183         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5184                           [(match_operand:SI 3 "s_register_operand" "r")
5185                            (match_operand:SI 4 "const_shift_operand" "n")])
5186                          (match_operand:SI 1 "s_register_operand" "0"))))
5187    (set (match_operand:SI 0 "s_register_operand" "=r")
5188         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5189                  (match_dup 1)))]
5190   "(! BYTES_BIG_ENDIAN)
5191    && ! TARGET_SHORT_BY_BYTES
5192    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5193    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5194    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5195   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5196 [(set_attr "type" "load")])
5198 (define_insn "*loadhi_shiftpredec"
5199   [(set (match_operand:HI 5 "s_register_operand" "=r")
5200         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5201                           (match_operator:SI 2 "shift_operator"
5202                            [(match_operand:SI 3 "s_register_operand" "r")
5203                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5204    (set (match_operand:SI 0 "s_register_operand" "=r")
5205         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5206                                                  (match_dup 4)])))]
5207   "(! BYTES_BIG_ENDIAN)
5208    && ! TARGET_SHORT_BY_BYTES
5209    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5210    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5211    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5212   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5213 [(set_attr "type" "load")])
5215 ; It can also support extended post-inc expressions, but combine doesn't
5216 ; try these....
5217 ; It doesn't seem worth adding peepholes for anything but the most common
5218 ; cases since, unlike combine, the increment must immediately follow the load
5219 ; for this pattern to match.
5220 ; When loading we must watch to see that the base register isn't trampled by
5221 ; the load.  In such cases this isn't a post-inc expression.
5223 (define_peephole
5224   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5225         (match_operand:QI 2 "s_register_operand" "r"))
5226    (set (match_dup 0)
5227         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5228   ""
5229   "str%?b\\t%2, [%0], %1")
5231 (define_peephole
5232   [(set (match_operand:QI 0 "s_register_operand" "=r")
5233         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5234    (set (match_dup 1)
5235         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5236   "REGNO(operands[0]) != REGNO(operands[1])
5237    && (GET_CODE (operands[2]) != REG
5238        || REGNO(operands[0]) != REGNO (operands[2]))"
5239   "ldr%?b\\t%0, [%1], %2")
5241 (define_peephole
5242   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5243         (match_operand:SI 2 "s_register_operand" "r"))
5244    (set (match_dup 0)
5245         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5246   ""
5247   "str%?\\t%2, [%0], %1")
5249 (define_peephole
5250   [(set (match_operand:HI 0 "s_register_operand" "=r")
5251         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5252    (set (match_dup 1)
5253         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5254   "(! BYTES_BIG_ENDIAN)
5255    && ! TARGET_SHORT_BY_BYTES
5256    && REGNO(operands[0]) != REGNO(operands[1])
5257    && (GET_CODE (operands[2]) != REG
5258        || REGNO(operands[0]) != REGNO (operands[2]))"
5259   "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5261 (define_peephole
5262   [(set (match_operand:SI 0 "s_register_operand" "=r")
5263         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5264    (set (match_dup 1)
5265         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5266   "REGNO(operands[0]) != REGNO(operands[1])
5267    && (GET_CODE (operands[2]) != REG
5268        || REGNO(operands[0]) != REGNO (operands[2]))"
5269   "ldr%?\\t%0, [%1], %2")
5271 (define_peephole
5272   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5273                          (match_operand:SI 1 "index_operand" "rJ")))
5274         (match_operand:QI 2 "s_register_operand" "r"))
5275    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5276   ""
5277   "str%?b\\t%2, [%0, %1]!")
5279 (define_peephole
5280   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5281                           [(match_operand:SI 0 "s_register_operand" "r")
5282                            (match_operand:SI 1 "const_int_operand" "n")])
5283                          (match_operand:SI 2 "s_register_operand" "+r")))
5284         (match_operand:QI 3 "s_register_operand" "r"))
5285    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5286                                (match_dup 2)))]
5287   ""
5288   "str%?b\\t%3, [%2, %0%S4]!")
5290 ; This pattern is never tried by combine, so do it as a peephole
5292 (define_peephole
5293   [(set (match_operand:SI 0 "s_register_operand" "=r")
5294         (match_operand:SI 1 "s_register_operand" "r"))
5295    (set (match_operand 2 "cc_register" "")
5296         (compare (match_dup 1) (const_int 0)))]
5297   ""
5298   "sub%?s\\t%0, %1, #0"
5299 [(set_attr "conds" "set")])
5301 ; Peepholes to spot possible load- and store-multiples, if the ordering is
5302 ; reversed, check that the memory references aren't volatile.
5304 (define_peephole
5305   [(set (match_operand:SI 0 "s_register_operand" "=r")
5306         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5307                          (const_int 12))))
5308    (set (match_operand:SI 2 "s_register_operand" "=r")
5309         (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5310    (set (match_operand:SI 3 "s_register_operand" "=r")
5311         (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5312    (set (match_operand:SI 4 "s_register_operand" "=r")
5313         (mem:SI (match_dup 1)))]
5314   "REGNO (operands[0]) > REGNO (operands[2])
5315    && REGNO (operands[2]) > REGNO (operands[3])
5316    && REGNO (operands[3]) > REGNO (operands[4])
5317    && !(REGNO (operands[1]) == REGNO (operands[0])
5318        || REGNO (operands[1]) == REGNO (operands[2])
5319        || REGNO (operands[1]) == REGNO (operands[3])
5320        || REGNO (operands[1]) == REGNO (operands[4]))
5321    && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5322    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
5323    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5324                                          (prev_nonnote_insn (insn)))))
5325    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5326                                          (prev_nonnote_insn 
5327                                           (prev_nonnote_insn (insn))))))"
5328   "ldm%?ia\\t%1, {%4, %3, %2, %0}\\t%@ phole ldm")
5330 (define_peephole
5331   [(set (match_operand:SI 0 "s_register_operand" "=r")
5332         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5333                          (const_int 8))))
5334    (set (match_operand:SI 2 "s_register_operand" "=r")
5335         (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5336    (set (match_operand:SI 3 "s_register_operand" "=r")
5337         (mem:SI (match_dup 1)))]
5338   "REGNO (operands[0]) >  REGNO (operands[2])
5339    && REGNO (operands[2]) > REGNO (operands[3])
5340    && !(REGNO (operands[1]) == REGNO (operands[0])
5341        || REGNO (operands[1]) == REGNO (operands[2])
5342        || REGNO (operands[1]) == REGNO (operands[3]))
5343    && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5344    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
5345    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5346                                          (prev_nonnote_insn (insn)))))"
5347   "ldm%?ia\\t%1, {%3, %2, %0}\\t%@ phole ldm")
5349 (define_peephole
5350   [(set (match_operand:SI 0 "s_register_operand" "=r")
5351         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5352                          (const_int 4))))
5353    (set (match_operand:SI 2 "s_register_operand" "=r")
5354         (mem:SI (match_dup 1)))]
5355   "REGNO (operands[0]) > REGNO (operands[2])
5356    && !(REGNO (operands[1]) == REGNO (operands[0])
5357        || REGNO (operands[1]) == REGNO (operands[2]))
5358    && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5359    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))"
5360   "ldm%?ia\\t%1, {%2, %0}\\t%@ phole ldm")
5362 (define_peephole
5363   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5364                          (const_int 12)))
5365         (match_operand:SI 0 "s_register_operand" "r"))
5366    (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5367         (match_operand:SI 2 "s_register_operand" "r"))
5368    (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5369         (match_operand:SI 3 "s_register_operand" "r"))
5370    (set (mem:SI (match_dup 1))
5371         (match_operand:SI 4 "s_register_operand" "r"))]
5372   "REGNO (operands[0]) >  REGNO (operands[2])
5373    && REGNO (operands[2]) > REGNO (operands[3])
5374    && REGNO (operands[3]) > REGNO (operands[4])
5375    && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5376    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5377    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5378                                           (prev_nonnote_insn (insn)))))
5379    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5380                                           (prev_nonnote_insn 
5381                                            (prev_nonnote_insn (insn))))))"
5382   "stm%?ia\\t%1, {%4, %3, %2, %0}\\t%@ phole stm")
5384 (define_peephole
5385   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5386                          (const_int 8)))
5387         (match_operand:SI 0 "s_register_operand" "r"))
5388    (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5389         (match_operand:SI 2 "s_register_operand" "r"))
5390    (set (mem:SI (match_dup 1))
5391         (match_operand:SI 3 "s_register_operand" "r"))]
5392   "REGNO (operands[0]) >  REGNO (operands[2])
5393    && REGNO (operands[2]) > REGNO (operands[3])
5394    && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5395    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5396    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5397                                           (prev_nonnote_insn (insn)))))"
5398   "stm%?ia\\t%1, {%3, %2, %0}\\t%@ phole stm")
5400 (define_peephole
5401   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5402                          (const_int 4)))
5403         (match_operand:SI 0 "s_register_operand" "r"))
5404    (set (mem:SI (match_dup 1))
5405         (match_operand:SI 2 "s_register_operand" "r"))]
5406   "REGNO (operands[0]) >  REGNO (operands[2])
5407    && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5408    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))"
5409   "stm%?ia\\t%1, {%2, %0}\\t%@ phole stm")
5411 ;; A call followed by return can be replaced by restoring the regs and
5412 ;; jumping to the subroutine, provided we aren't passing the address of
5413 ;; any of our local variables.  If we call alloca then this is unsafe
5414 ;; since restoring the frame frees the memory, which is not what we want.
5415 ;; Sometimes the return might have been targeted by the final prescan:
5416 ;; if so then emit a proper return insn as well.
5417 ;; Unfortunately, if the frame pointer is required, we don't know if the
5418 ;; current function has any implicit stack pointer adjustments that will 
5419 ;; be restored by the return: we can't therefore do a tail call.
5420 ;; Another unfortunate that we can't handle is if current_function_args_size
5421 ;; is non-zero: in this case elimination of the argument pointer assumed
5422 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5423 ;; calculations.
5425 (define_peephole
5426   [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5427                           (match_operand:SI 1 "general_operand" "g"))
5428                     (clobber (reg:SI 14))])
5429    (return)]
5430   "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN
5431     && !get_frame_size () && !current_function_calls_alloca
5432     && !frame_pointer_needed && !current_function_args_size)"
5433   "*
5435   extern rtx arm_target_insn;
5436   extern int arm_ccfsm_state, arm_current_cc;
5438   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5439   {
5440     arm_current_cc ^= 1;
5441     output_return_instruction (NULL, TRUE);
5442     arm_ccfsm_state = 0;
5443     arm_target_insn = NULL;
5444   }
5446   output_return_instruction (NULL, FALSE);
5447   return \"b%?\\t%a0\";
5449 [(set_attr "type" "call")
5450  (set_attr "length" "8")])
5452 (define_peephole
5453   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5454                    (call (mem:SI (match_operand:SI 1 "" "X"))
5455                          (match_operand:SI 2 "general_operand" "g")))
5456               (clobber (reg:SI 14))])
5457    (return)]
5458   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5459     && !get_frame_size () && !current_function_calls_alloca
5460     && !frame_pointer_needed && !current_function_args_size)"
5461   "*
5463   extern rtx arm_target_insn;
5464   extern int arm_ccfsm_state, arm_current_cc;
5466   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5467   {
5468     arm_current_cc ^= 1;
5469     output_return_instruction (NULL, TRUE);
5470     arm_ccfsm_state = 0;
5471     arm_target_insn = NULL;
5472   }
5474   output_return_instruction (NULL, FALSE);
5475   return \"b%?\\t%a1\";
5477 [(set_attr "type" "call")
5478  (set_attr "length" "8")])
5480 ;; As above but when this function is not void, we must be returning the
5481 ;; result of the called subroutine.
5483 (define_peephole
5484   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5485                    (call (mem:SI (match_operand:SI 1 "" "X"))
5486                          (match_operand:SI 2 "general_operand" "g")))
5487               (clobber (reg:SI 14))])
5488    (use (match_dup 0))
5489    (return)]
5490   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5491     && !get_frame_size () && !current_function_calls_alloca
5492     && !frame_pointer_needed && !current_function_args_size)"
5493   "*
5495   extern rtx arm_target_insn;
5496   extern int arm_ccfsm_state, arm_current_cc;
5498   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5499   {
5500     arm_current_cc ^= 1;
5501     output_return_instruction (NULL, TRUE);
5502     arm_ccfsm_state = 0;
5503     arm_target_insn = NULL;
5504   }
5506   output_return_instruction (NULL, FALSE);
5507   return \"b%?\\t%a1\";
5509 [(set_attr "type" "call")
5510  (set_attr "length" "8")])
5512 ;; If calling a subroutine and then jumping back to somewhere else, but not
5513 ;; too far away, then we can set the link register with the branch address
5514 ;; and jump direct to the subroutine.  On return from the subroutine
5515 ;; execution continues at the branch; this avoids a prefetch stall.
5516 ;; We use the length attribute (via short_branch ()) to establish whether or
5517 ;; not this is possible, this is the same as the sparc does.
5519 (define_peephole
5520   [(parallel[(call (mem:SI (match_operand:SI 0 "" "X"))
5521                    (match_operand:SI 1 "general_operand" "g"))
5522              (clobber (reg:SI 14))])
5523    (set (pc)
5524         (label_ref (match_operand 2 "" "")))]
5525   "0 && GET_CODE (operands[0]) == SYMBOL_REF 
5526    && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
5527    && arm_insn_not_targeted (insn)"
5528   "*
5530   int backward = arm_backwards_branch (INSN_UID (insn),
5531                                        INSN_UID (operands[2]));
5533 #if 0
5534   /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
5535    * above, leaving it out means that the code will still run on an arm 2 or 3
5536    */
5537   if (TARGET_6)
5538     {
5539       if (backward)
5540         output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l2)\", operands);
5541       else
5542         output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l2 - . -8)\", operands);
5543     }
5544   else
5545 #endif
5546     {
5547       output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands);
5548       if (backward)
5549         output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l2)\", operands);
5550       else
5551         output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l2 - . -4)\", operands);
5552     }
5553   return \"b%?\\t%a0\";
5555 [(set_attr "type" "call")
5556  (set (attr "length")
5557       (if_then_else (eq_attr "prog_mode" "prog32")
5558                     (const_int 8)
5559                     (const_int 12)))])
5561 (define_peephole
5562   [(parallel[(set (match_operand:SI 0 "s_register_operand" "=r")
5563                   (call (mem:SI (match_operand:SI 1 "" "X"))
5564                         (match_operand:SI 2 "general_operand" "g")))
5565              (clobber (reg:SI 14))])
5566    (set (pc)
5567         (label_ref (match_operand 3 "" "")))]
5568   "0 && GET_CODE (operands[0]) == SYMBOL_REF
5569    && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
5570    && arm_insn_not_targeted (insn)"
5571   "*
5573   int backward = arm_backwards_branch (INSN_UID (insn),
5574                                        INSN_UID (operands[3]));
5576 #if 0
5577   /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
5578    * above, leaving it out means that the code will still run on an arm 2 or 3
5579    */
5580   if (TARGET_6)
5581     {
5582       if (backward)
5583         output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l3)\", operands);
5584       else
5585         output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l3 - . -8)\", operands);
5586     }
5587   else
5588 #endif
5589     {
5590       output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands);
5591       if (backward)
5592         output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l3)\", operands);
5593       else
5594         output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l3 - . -4)\", operands);
5595     }
5596   return \"b%?\\t%a1\";
5598 [(set_attr "type" "call")
5599  (set (attr "length")
5600       (if_then_else (eq_attr "prog_mode" "prog32")
5601                     (const_int 8)
5602                     (const_int 12)))])
5604 (define_split
5605   [(set (pc)
5606         (if_then_else (match_operator 0 "comparison_operator"
5607                        [(match_operator:SI 1 "shift_operator"
5608                          [(match_operand:SI 2 "s_register_operand" "r")
5609                           (match_operand:SI 3 "reg_or_int_operand" "rM")])
5610                         (match_operand:SI 4 "s_register_operand" "r")])
5611                       (label_ref (match_operand 5 "" ""))
5612                       (pc)))
5613    (clobber (reg 24))]
5614   ""
5615   [(set (reg:CC 24)
5616         (compare:CC (match_dup 4)
5617                     (match_op_dup 1 [(match_dup 2) (match_dup 3)])))
5618    (set (pc)
5619         (if_then_else (match_op_dup 0 [(reg 24) (const_int 0)])
5620                       (label_ref (match_dup 5))
5621                       (pc)))]
5622   "
5623   operands[0] = gen_rtx (swap_condition (GET_CODE (operands[0])), VOIDmode,
5624                          operands[1], operands[2]);
5627 (define_split
5628   [(set (match_operand:SI 0 "s_register_operand" "")
5629         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
5630                        (const_int 0))
5631                 (neg:SI (match_operator:SI 2 "comparison_operator"
5632                          [(match_operand:SI 3 "s_register_operand" "")
5633                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
5634    (clobber (match_operand:SI 5 "s_register_operand" ""))]
5635   ""
5636   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
5637    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5638                               (match_dup 5)))]
5639   "")
5641 ;; This pattern can be used because cc_noov mode implies that the following
5642 ;; branch will be an equality (EQ or NE), so the sign extension is not
5643 ;; needed.  Combine doesn't eliminate these because by the time it sees the
5644 ;; branch it no-longer knows that the data came from memory.
5646 (define_insn "*loadqi_compare"
5647   [(set (reg:CC_NOOV 24)
5648         (compare:CC_NOOV
5649          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "m") 0)
5650                     (const_int 24))
5651          (match_operand 1 "immediate_operand" "I")))
5652    (clobber (match_scratch:SI 2 "=r"))]
5653   "((unsigned long) INTVAL (operands[1]))
5654    == (((unsigned long) INTVAL (operands[1])) >> 24) << 24"
5655   "*
5656   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
5657   output_asm_insn (\"ldr%?b\\t%2, %0\", operands);
5658   output_asm_insn (\"cmp%?\\t%2, %1\", operands);
5659   return \"\";
5661 [(set_attr "conds" "set")
5662  (set_attr "length" "8")
5663  (set_attr "type" "load")])
5665 (define_expand "prologue"
5666   [(clobber (const_int 0))]
5667   ""
5668   "
5669   arm_expand_prologue ();
5670   DONE;
5673 ;; This split is only used during output to reduce the number of patterns
5674 ;; that need assembler instructions adding to them.  We allowed the setting
5675 ;; of the conditions to be implicit during rtl generation so that
5676 ;; the conditional compare patterns would work.  However this conflicts to
5677 ;; some extend with the conditional data operations, so we have to split them
5678 ;; up again here.
5680 (define_split
5681   [(set (match_operand:SI 0 "s_register_operand" "")
5682         (if_then_else:SI (match_operator 1 "comparison_operator"
5683                           [(match_operand 2 "" "") (match_operand 3 "" "")])
5684                          (match_operand 4 "" "")
5685                          (match_operand 5 "" "")))
5686    (clobber (reg 24))]
5687   "reload_completed"
5688   [(set (match_dup 6) (match_dup 7))
5689    (set (match_dup 0) 
5690         (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
5691                          (match_dup 4)
5692                          (match_dup 5)))]
5693   "
5695   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
5696                                            operands[3]);
5698   operands[6] = gen_rtx (REG, mode, 24);
5699   operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
5704 (define_insn "*cond_move_not"
5705   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5706         (if_then_else:SI (match_operator 4 "comparison_operator"
5707                           [(match_operand 3 "reversible_cc_register" "")
5708                            (const_int 0)])
5709                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5710                          (not:SI
5711                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
5712   ""
5713   "@
5714    mvn%D4\\t%0, %2
5715    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
5716 [(set_attr "conds" "use")
5717  (set_attr "length" "4,8")])
5719 ;; The next two patterns occur when an AND operation is followed by a
5720 ;; scc insn sequence 
5722 (define_insn "*sign_extract_onebit"
5723   [(set (match_operand:SI 0 "s_register_operand" "=r")
5724         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5725                          (const_int 1)
5726                          (match_operand:SI 2 "immediate_operand" "n")))]
5727   ""
5728   "*
5729   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5730   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
5731   return \"mvnne\\t%0, #0\";
5733 [(set_attr "conds" "clob")
5734  (set_attr "length" "8")])
5736 (define_insn "*not_signextract_onebit"
5737   [(set (match_operand:SI 0 "s_register_operand" "=r")
5738         (not:SI
5739          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5740                           (const_int 1)
5741                           (match_operand:SI 2 "immediate_operand" "n"))))]
5742   ""
5743   "*
5744   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5745   output_asm_insn (\"tst\\t%1, %2\", operands);
5746   output_asm_insn (\"mvneq\\t%0, #0\", operands);
5747   return \"movne\\t%0, #0\";
5749 [(set_attr "conds" "clob")
5750  (set_attr "length" "12")])
5752 ;; Push multiple registers to the stack.  The first register is in the
5753 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
5754 ;; expressions.
5755 (define_insn "*push_multi"
5756   [(match_parallel 2 "multi_register_push"
5757     [(set (match_operand:BLK 0 "memory_operand" "=m")
5758           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
5759   ""
5760   "*
5762   char pattern[100];
5763   int i;
5764   extern int lr_save_eliminated;
5766   if (lr_save_eliminated)
5767     {
5768       if (XVECLEN (operands[2], 0) > 1)
5769         abort ();
5770       return \"\";
5771     }
5772   strcpy (pattern, \"stmfd\\t%m0!, {%1\");
5773   for (i = 1; i < XVECLEN (operands[2], 0); i++)
5774     {
5775       strcat (pattern, \", %|\");
5776       strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
5777                                               0))]);
5778     }
5779   strcat (pattern, \"}\");
5780   output_asm_insn (pattern, operands);
5781   return \"\";
5783 [(set_attr "type" "store4")])
5785 ;; Special patterns for dealing with the constant pool
5787 (define_insn "consttable_4"
5788   [(unspec_volatile [(match_operand 0 "" "")] 2)]
5789   ""
5790   "*
5792   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
5793     {
5794     case MODE_FLOAT:
5795     {
5796       union real_extract u;
5797       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
5798       assemble_real (u.d, GET_MODE (operands[0]));
5799       break;
5800     }
5801     default:
5802       assemble_integer (operands[0], 4, 1);
5803       break;
5804     }
5805   return \"\";
5807 [(set_attr "length" "4")])
5809 (define_insn "consttable_8"
5810   [(unspec_volatile [(match_operand 0 "" "")] 3)]
5811   ""
5812   "*
5814   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
5815     {
5816     case MODE_FLOAT:
5817     {
5818       union real_extract u;
5819       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
5820       assemble_real (u.d, GET_MODE (operands[0]));
5821       break;
5822     }
5823     default:
5824       assemble_integer (operands[0], 8, 1);
5825       break;
5826     }
5827   return \"\";
5829 [(set_attr "length" "8")])
5831 (define_insn "consttable_end"
5832   [(unspec_volatile [(const_int 0)] 4)]
5833   ""
5834   "*
5835   text_section ();
5836   return \"\";
5839 (define_insn "align_4"
5840   [(unspec_volatile [(const_int 0)] 5)]
5841   ""
5842   "*
5843   readonly_data_section ();
5844   assemble_align (32);
5845   return \"\";