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