OSDN Git Service

(PREDICATE_CODES): Add reversible_cc_register.
[pf3gnuchains/gcc-fork.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 "s_register_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 { operands[1] = gen_lowpart (SImode, operands[1]);
1779   operands[2] = gen_reg_rtx (SImode); 
1780 }")
1781
1782 (define_expand "zero_extendqisi2"
1783   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1784         (zero_extend:SI
1785          (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1786   ""
1787   "
1788   if (GET_CODE (operands[1]) != MEM)
1789     {
1790       emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
1791                              GEN_INT (255)));
1792       DONE;
1793     }
1794 ")
1795
1796 (define_insn ""
1797   [(set (match_operand:SI 0 "s_register_operand" "=r")
1798         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
1799   ""
1800   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
1801 [(set_attr "type" "load")])
1802
1803 (define_split
1804   [(set (match_operand:SI 0 "s_register_operand" "")
1805         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
1806    (clobber (match_operand:SI 2 "s_register_operand" ""))]
1807   "GET_CODE (operands[1]) != MEM"
1808   [(set (match_dup 2) (match_dup 1))
1809    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
1810   "")
1811
1812 (define_insn ""
1813   [(set (reg:CC_NOOV 24)
1814         (compare:CC_NOOV (match_operand:QI 0 "s_register_operand" "r")
1815                          (const_int 0)))]
1816   ""
1817   "tst\\t%0, #255"
1818 [(set_attr "conds" "set")])
1819
1820 (define_expand "extendhisi2"
1821   [(set (match_dup 2)
1822         (ashift:SI (match_operand:HI 1 "s_register_operand" "")
1823                    (const_int 16)))
1824    (set (match_operand:SI 0 "s_register_operand" "")
1825         (ashiftrt:SI (match_dup 2)
1826                      (const_int 16)))]
1827   ""
1828   "
1829 { operands[1] = gen_lowpart (SImode, operands[1]);
1830   operands[2] = gen_reg_rtx (SImode); }")
1831
1832 (define_expand "extendqihi2"
1833   [(set (match_dup 2)
1834         (ashift:SI (match_operand:QI 1 "s_register_operand" "")
1835                    (const_int 24)))
1836    (set (match_operand:HI 0 "s_register_operand" "")
1837         (ashiftrt:SI (match_dup 2)
1838                      (const_int 24)))]
1839   ""
1840   "
1841 { operands[0] = gen_lowpart (SImode, operands[0]);
1842   operands[1] = gen_lowpart (SImode, operands[1]);
1843   operands[2] = gen_reg_rtx (SImode); }")
1844
1845 (define_expand "extendqisi2"
1846   [(set (match_dup 2)
1847         (ashift:SI (match_operand:QI 1 "s_register_operand" "")
1848                    (const_int 24)))
1849    (set (match_operand:SI 0 "s_register_operand" "")
1850         (ashiftrt:SI (match_dup 2)
1851                      (const_int 24)))]
1852   ""
1853   "
1854 { operands[1] = gen_lowpart (SImode, operands[1]);
1855   operands[2] = gen_reg_rtx (SImode); }")
1856
1857 (define_insn "extendsfdf2"
1858   [(set (match_operand:DF 0 "s_register_operand" "=f")
1859         (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
1860   ""
1861   "mvf%?d\\t%0, %1"
1862 [(set_attr "type" "ffarith")])
1863
1864 (define_insn "extendsfxf2"
1865   [(set (match_operand:XF 0 "s_register_operand" "=f")
1866         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
1867   "ENABLE_XF_PATTERNS"
1868   "mvf%?e\\t%0, %1"
1869 [(set_attr "type" "ffarith")])
1870
1871 (define_insn "extenddfxf2"
1872   [(set (match_operand:XF 0 "s_register_operand" "=f")
1873         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
1874   "ENABLE_XF_PATTERNS"
1875   "mvf%?e\\t%0, %1"
1876 [(set_attr "type" "ffarith")])
1877
1878 \f
1879 ;; Move insns (including loads and stores)
1880
1881 ;; XXX Just some ideas about movti.
1882 ;; I don't think these are a good idea on the arm, there just aren't enough
1883 ;; registers
1884 ;;(define_expand "loadti"
1885 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
1886 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
1887 ;;  "" "")
1888
1889 ;;(define_expand "storeti"
1890 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
1891 ;;      (match_operand:TI 1 "s_register_operand" ""))]
1892 ;;  "" "")
1893
1894 ;;(define_expand "movti"
1895 ;;  [(set (match_operand:TI 0 "general_operand" "")
1896 ;;      (match_operand:TI 1 "general_operand" ""))]
1897 ;;  ""
1898 ;;  "
1899 ;;{
1900 ;;  rtx insn;
1901 ;;
1902 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
1903 ;;    operands[1] = copy_to_reg (operands[1]);
1904 ;;  if (GET_CODE (operands[0]) == MEM)
1905 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
1906 ;;  else if (GET_CODE (operands[1]) == MEM)
1907 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
1908 ;;  else
1909 ;;    FAIL;
1910 ;;
1911 ;;  emit_insn (insn);
1912 ;;  DONE;
1913 ;;}")
1914
1915 ;; Recognise garbage generated above.
1916
1917 ;;(define_insn ""
1918 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
1919 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
1920 ;;  ""
1921 ;;  "*
1922 ;;  {
1923 ;;    register mem = (which_alternative < 3);
1924 ;;    register char *template;
1925 ;;
1926 ;;    operands[mem] = XEXP (operands[mem], 0);
1927 ;;    switch (which_alternative)
1928 ;;      {
1929 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
1930 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
1931 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
1932 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
1933 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
1934 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
1935 ;;      }
1936 ;;    output_asm_insn (template, operands);
1937 ;;    return \"\";
1938 ;;  }")
1939
1940
1941 (define_insn "movdi"
1942   [(set (match_operand:DI 0 "di_operand" "=r,r,r,o<>,r")
1943         (match_operand:DI 1 "di_operand" "rIK,n,o<>,r,F"))]
1944   ""
1945   "*
1946   return (output_move_double (operands));
1947 "
1948 [(set_attr "length" "8,32,8,8,32")
1949  (set_attr "type" "*,*,load,store2,*")])
1950
1951 (define_expand "movsi"
1952   [(set (match_operand:SI 0 "general_operand" "")
1953         (match_operand:SI 1 "general_operand" ""))]
1954   ""
1955   "
1956   /* Everything except mem = const or mem = mem can be done easily */
1957   if (GET_CODE (operands[0]) == MEM)
1958     operands[1] = force_reg (SImode, operands[1]);
1959   if (GET_CODE (operands[1]) == CONST_INT
1960       && !(const_ok_for_arm (INTVAL (operands[1]))
1961            || const_ok_for_arm (~INTVAL (operands[1]))))
1962     {
1963       arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
1964                           NULL_RTX,
1965                           (reload_in_progress || reload_completed ? 0
1966                            : preserve_subexpressions_p ()));
1967       DONE;
1968     }
1969 ")
1970
1971 (define_insn ""
1972   [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,m,r,r")
1973         (match_operand:SI 1 "general_operand"  "R,m,K,rI,r,S,?n"))]
1974   "(register_operand (operands[0], SImode)
1975     && (GET_CODE (operands[1]) != SYMBOL_REF
1976         || CONSTANT_ADDRESS_P (operands[1])))
1977    || register_operand (operands[1], SImode)"
1978   "*
1979   switch (which_alternative)
1980     {
1981     case 0:
1982       /* NB Calling get_attr_length may cause the insn to be re-extracted... */
1983       if (get_attr_length (insn) == 8)
1984         {
1985           /* ... so modify the operands here.  */
1986           operands[1] = XEXP (operands[1], 0);
1987           output_asm_insn (\"sub%?\\t%0, %|pc, #(8 + . - %a1) & ~4095\",
1988                            operands);
1989           output_asm_insn (\"ldr%?\\t%0, [%0, #- ((4 + . - %a1) & 4095)]\",
1990                            operands);
1991         }
1992       else
1993         {
1994           /* ... and here.  */
1995           operands[1] = XEXP (operands[1], 0);
1996           output_asm_insn (\"ldr%?\\t%0, [%|pc, %1 - . - 8]\", operands);
1997         }
1998       return \"\";
1999
2000     case 1:
2001       if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
2002           &&  CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
2003         abort ();
2004       return \"ldr%?\\t%0, %1\";
2005
2006     case 3:
2007       return \"mov%?\\t%0, %1\";
2008     case 2:
2009       return \"mvn%?\\t%0, #%B1\";
2010     case 4:
2011       return \"str%?\\t%1, %0\";
2012     case 5:
2013       return output_load_symbol (insn, operands);
2014     case 6:
2015       return \"#\";
2016     }
2017 "
2018 [(set (attr "length")
2019       (cond [(eq_attr "alternative" "0")
2020              (if_then_else
2021               (gt (minus 
2022                    (pc)
2023                    (symbol_ref "const_pool_offset (XEXP (operands[1], 0))"))
2024                   (const_int 4087))
2025               (const_int 8)
2026               (const_int 4))
2027              (ior (eq_attr "alternative" "5")
2028                   (eq_attr "alternative" "6")) (const_int 16)]
2029             (const_int 4)))
2030  (set_attr "type" "load,load,*,*,store1,*,*")])
2031
2032 (define_split
2033   [(set (match_operand:SI 0 "s_register_operand" "")
2034         (match_operand:SI 1 "const_int_operand" ""))]
2035   "! (const_ok_for_arm (INTVAL (operands[1]))
2036       || const_ok_for_arm (~INTVAL (operands[1])))"
2037   [(clobber (const_int 0))]
2038   "
2039   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2040                       NULL_RTX, 0);
2041   DONE;
2042 ")
2043
2044 ;; If copying one reg to another we can set the condition codes according to
2045 ;; its value.  Such a move is common after a return from subroutine and the
2046 ;; result is being tested against zero.
2047
2048 (define_insn ""
2049   [(set (reg:CC 24) (compare (match_operand:SI 1 "s_register_operand" "0,r")
2050                              (const_int 0)))
2051    (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2052   ""
2053   "@
2054    cmp%?\\t%0, #0
2055    sub%?s\\t%0, %1, #0"
2056 [(set_attr "conds" "set")])
2057
2058 ;; Subroutine to store a half word from a register into memory.
2059 ;; Operand 0 is the source register (HImode)
2060 ;; Operand 1 is the destination address in a register (SImode)
2061
2062 ;; In both this routine and the next, we must be careful not to spill
2063 ;; a memory address of reg+large_const into a seperate PLUS insn, since this
2064 ;; can generate unrecognizable rtl.
2065
2066 (define_expand "storehi"
2067   [;; store the low byte
2068    (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3))
2069    ;; extract the high byte
2070    (set (match_dup 2)
2071         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2072    ;; store the high byte
2073    (set (mem:QI (match_dup 4))
2074         (subreg:QI (match_dup 2) 0))]   ;explicit subreg safe
2075   ""
2076   "
2077 {
2078   enum rtx_code code = GET_CODE (operands[1]);
2079
2080   if ((code == PLUS || code == MINUS)
2081       && (GET_CODE (XEXP (operands[1], 1)) == REG
2082           || GET_CODE (XEXP (operands[1], 0)) != REG))
2083     operands[1] = force_reg (SImode, operands[1]);
2084   operands[4] = plus_constant (operands[1], 1);
2085   operands[3] = gen_lowpart (QImode, operands[0]);
2086   operands[0] = gen_lowpart (SImode, operands[0]);
2087   operands[2] = gen_reg_rtx (SImode); 
2088 }
2089 ")
2090
2091 (define_expand "storehi_bigend"
2092   [(set (mem:QI (match_dup 4)) (match_dup 3))
2093    (set (match_dup 2)
2094         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2095    (set (mem:QI (match_operand 1 "" ""))
2096         (subreg:QI (match_dup 2) 0))]
2097   ""
2098   "
2099 {
2100   enum rtx_code code = GET_CODE (operands[1]);
2101   if ((code == PLUS || code == MINUS)
2102       && (GET_CODE (XEXP (operands[1], 1)) == REG
2103           || GET_CODE (XEXP (operands[1], 0)) != REG))
2104     operands[1] = force_reg (SImode, operands[1]);
2105
2106   operands[4] = plus_constant (operands[1], 1);
2107   operands[3] = gen_lowpart (QImode, operands[0]);
2108   operands[0] = gen_lowpart (SImode, operands[0]);
2109   operands[2] = gen_reg_rtx (SImode);
2110 }
2111 ")
2112
2113 ;; Subroutine to store a half word integer constant into memory.
2114 (define_expand "storeinthi"
2115   [(set (mem:QI (match_operand:SI 0 "" ""))
2116         (subreg:QI (match_operand 1 "" "") 0))
2117    (set (mem:QI (match_dup 3)) (subreg:QI (match_dup 2) 0))]
2118   ""
2119   "
2120 {
2121   HOST_WIDE_INT value = INTVAL (operands[1]);
2122   enum rtx_code code = GET_CODE (operands[0]);
2123
2124   if ((code == PLUS || code == MINUS)
2125       && (GET_CODE (XEXP (operands[0], 1)) == REG
2126           || GET_CODE (XEXP (operands[0], 0)) != REG))
2127   operands[0] = force_reg (SImode, operands[0]);
2128
2129   operands[1] = gen_reg_rtx (SImode);
2130   if (BYTES_BIG_ENDIAN)
2131     {
2132       emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2133       if ((value & 255) == ((value >> 8) & 255))
2134         operands[2] = operands[1];
2135       else
2136         {
2137           operands[2] = gen_reg_rtx (SImode);
2138           emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2139         }
2140     }
2141   else
2142     {
2143       emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2144       if ((value & 255) == ((value >> 8) & 255))
2145         operands[2] = operands[1];
2146       else
2147         {
2148           operands[2] = gen_reg_rtx (SImode);
2149           emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2150         }
2151     }
2152
2153   operands[3] = plus_constant (operands[0], 1);
2154 }
2155 ")
2156
2157 (define_expand "movhi"
2158   [(set (match_operand:HI 0 "general_operand" "")
2159         (match_operand:HI 1 "general_operand" ""))]
2160   ""
2161   "
2162 {
2163   rtx insn;
2164
2165   if (! (reload_in_progress || reload_completed))
2166     {
2167       if (GET_CODE (operands[0]) == MEM)
2168         {
2169           if (GET_CODE (operands[1]) == CONST_INT)
2170             emit_insn (gen_storeinthi (XEXP (operands[0], 0), operands[1]));
2171           else
2172             {
2173               if (GET_CODE (operands[1]) == MEM)
2174                 operands[1] = force_reg (HImode, operands[1]);
2175               if (BYTES_BIG_ENDIAN)
2176                 emit_insn (gen_storehi_bigend (operands[1],
2177                                                XEXP (operands[0], 0)));
2178               else
2179                 emit_insn (gen_storehi (operands[1], XEXP (operands[0], 0)));
2180             }
2181           DONE;
2182         }
2183       /* Sign extend a constant, and keep it in an SImode reg.  */
2184       else if (GET_CODE (operands[1]) == CONST_INT)
2185         {
2186           rtx reg = gen_reg_rtx (SImode);
2187           HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2188
2189           /* If the constant is already valid, leave it alone.  */
2190           if (! const_ok_for_arm (val))
2191             {
2192               /* If setting all the top bits will make the constant 
2193                  loadable in a single instruction, then set them.  
2194                  Otherwise, sign extend the number.  */
2195
2196               if (const_ok_for_arm (~ (val | ~0xffff)))
2197                 val |= ~0xffff;
2198               else if (val & 0x8000)
2199                 val |= ~0xffff;
2200             }
2201
2202           emit_insn (gen_movsi (reg, GEN_INT (val)));
2203           operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
2204         }
2205       else if (BYTES_BIG_ENDIAN && GET_CODE (operands[1]) == MEM)
2206         {
2207           emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2208           DONE;
2209         }
2210     }
2211 }
2212 ")
2213
2214 (define_expand "movhi_bigend"
2215   [(set (match_dup 2)
2216         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
2217                    (const_int 16)))
2218    (set (match_dup 3)
2219         (ashiftrt:SI (match_dup 2) (const_int 16)))
2220    (set (match_operand:HI 0 "s_register_operand" "")
2221         (subreg:HI (match_dup 3) 0))]
2222   ""
2223   "
2224   operands[2] = gen_reg_rtx (SImode);
2225   operands[3] = gen_reg_rtx (SImode);
2226 ")
2227
2228 ;; Pattern to recognise insn generated default case above
2229
2230 (define_insn ""
2231   [(set (match_operand:HI 0 "general_operand" "=r,r,r")
2232         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2233   "(! BYTES_BIG_ENDIAN)
2234    && (GET_CODE (operands[1]) != CONST_INT
2235        || const_ok_for_arm (INTVAL (operands[1]))
2236        || const_ok_for_arm (~INTVAL (operands[1])))"
2237   "@
2238    mov%?\\t%0, %1\\t%@ movhi
2239    mvn%?\\t%0, #%B1\\t%@ movhi
2240    ldr%?\\t%0, %1\\t%@ movhi"
2241 [(set_attr "type" "*,*,load")])
2242
2243 (define_insn ""
2244   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
2245         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2246   "BYTES_BIG_ENDIAN
2247    && (GET_CODE (operands[1]) != CONST_INT
2248        || const_ok_for_arm (INTVAL (operands[1]))
2249        || const_ok_for_arm (~INTVAL (operands[1])))"
2250   "@
2251    mov%?\\t%0, %1\\t%@ movhi
2252    mvn%?\\t%0, #%B1\\t%@ movhi
2253    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
2254 [(set_attr "type" "*,*,load")
2255  (set_attr "length" "4,4,8")])
2256
2257 (define_insn ""
2258   [(set (match_operand:SI 0 "s_register_operand" "=r")
2259         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
2260                    (const_int 16)))]
2261   "BYTES_BIG_ENDIAN"
2262   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
2263 [(set_attr "type" "load")])
2264
2265 (define_expand "reload_outhi"
2266   [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
2267               (match_operand:HI 1 "s_register_operand" "r")
2268               (match_operand:SI 2 "s_register_operand" "=&r")])]
2269   ""
2270   "
2271   arm_reload_out_hi (operands);
2272   DONE;
2273 ")
2274
2275 (define_expand "movqi"
2276   [(set (match_operand:QI 0 "general_operand" "")
2277         (match_operand:QI 1 "general_operand" ""))]
2278   ""
2279   "
2280   /* Everything except mem = const or mem = mem can be done easily */
2281
2282   if (!(reload_in_progress || reload_completed))
2283     {
2284       if (GET_CODE (operands[1]) == CONST_INT)
2285         {
2286           rtx reg = gen_reg_rtx (SImode);
2287
2288           emit_insn (gen_movsi (reg, operands[1]));
2289           operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
2290         }
2291       if (GET_CODE (operands[0]) == MEM)
2292         operands[1] = force_reg (QImode, operands[1]);
2293     }
2294 ")
2295
2296
2297 (define_insn ""
2298   [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
2299         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
2300   "register_operand (operands[0], QImode)
2301    || register_operand (operands[1], QImode)"
2302   "@
2303    mov%?\\t%0, %1
2304    mvn%?\\t%0, #%B1
2305    ldr%?b\\t%0, %1
2306    str%?b\\t%1, %0"
2307 [(set_attr "type" "*,*,load,store1")])
2308
2309 (define_expand "movsf"
2310   [(set (match_operand:SF 0 "general_operand" "")
2311         (match_operand:SF 1 "general_operand" ""))]
2312   ""
2313   "
2314   if (GET_CODE (operands[1]) == CONST_DOUBLE
2315       && ((GET_CODE (operands[0]) == REG
2316            && REGNO (operands[0]) < 16)
2317           || ! (const_double_rtx_ok_for_fpu (operands[1])
2318                 || neg_const_double_rtx_ok_for_fpu (operands[1]))))
2319     {
2320       extern int optimize;
2321       rtx mem = force_const_mem (SFmode, operands[1]);
2322       rtx addr = gen_reg_rtx (SImode);
2323       if (optimize == 0)
2324         {
2325           rtx ptr = force_const_mem (SImode, XEXP (mem, 0));
2326           emit_insn (gen_movsi (addr, ptr));
2327         }
2328       else
2329         emit_insn (gen_movsi (addr, XEXP (mem, 0)));
2330       operands[1] = gen_rtx (MEM, SFmode, addr);
2331     }
2332   if (GET_CODE (operands[0]) == MEM)
2333     operands[1] = force_reg (SFmode, operands[1]);
2334 ")
2335
2336 (define_insn ""
2337   [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
2338         (match_operand:SF 1 "general_operand" "fG,H,m,f,r,f,r,m,r"))]
2339   "GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode)"
2340   "@
2341    mvf%?s\\t%0, %1
2342    mnf%?s\\t%0, #%N1
2343    ldf%?s\\t%0, %1
2344    stf%?s\\t%1, %0
2345    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
2346    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
2347    mov%?\\t%0, %1
2348    ldr%?\\t%0, %1\\t%@ float
2349    str%?\\t%1, %0\\t%@ float"
2350 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
2351  (set_attr "type"
2352          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
2353
2354 (define_expand "movdf"
2355   [(set (match_operand:DF 0 "general_operand" "")
2356         (match_operand:DF 1 "general_operand" ""))]
2357   ""
2358   "
2359   if (GET_CODE (operands[1]) == CONST_DOUBLE
2360       && ((GET_CODE (operands[0]) == REG
2361            && REGNO (operands[0]) < 16)
2362           || ! (const_double_rtx_ok_for_fpu (operands[1])
2363                 || neg_const_double_rtx_ok_for_fpu (operands[1]))))
2364     {
2365       extern int optimize;
2366       rtx mem = force_const_mem (DFmode, operands[1]);
2367       rtx addr = gen_reg_rtx (SImode);
2368       if (optimize == 0)
2369         {
2370           rtx ptr = force_const_mem (SImode, XEXP (mem, 0));
2371           emit_insn (gen_movsi (addr, ptr));
2372         }
2373       else
2374         emit_insn (gen_movsi (addr, XEXP (mem, 0)));
2375       operands[1] = gen_rtx (MEM, DFmode, addr);
2376     }
2377   if (GET_CODE (operands[0]) == MEM)
2378     operands[1] = force_reg (DFmode, operands[1]);
2379 ")
2380
2381 ;; Reloading a df mode value stored in integer regs to memory can require a
2382 ;; scratch reg.
2383 (define_expand "reload_outdf"
2384   [(match_operand:DF 0 "reload_memory_operand" "=o")
2385    (match_operand:DF 1 "s_register_operand" "r")
2386    (match_operand:SI 2 "s_register_operand" "=&r")]
2387   ""
2388   "
2389   emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
2390                          XEXP (XEXP (operands[0], 0), 1)));
2391   emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DFmode, operands[2]),
2392                       operands[1]));
2393   DONE;
2394 ")
2395
2396 (define_insn ""
2397   [(set (match_operand:DF 0 "general_operand" "=r,Q#m,r,f,f,f,f,m,!f,!r,r")
2398         (match_operand:DF 1 "general_operand" 
2399                 "Q,r,?o,?f,!G,!H,m,f,r,f,??r"))]
2400   "GET_CODE (operands[0]) != MEM || register_operand (operands[1], DFmode)"
2401   "*
2402 {
2403   rtx ops[3];
2404
2405   switch (which_alternative)
2406     {
2407     case 0:
2408       return \"ldm%?ia\\t%m1, {%0, %R0}\\t%@ double\";
2409
2410     case 1:
2411       return \"stm%?ia\\t%m0, {%1, %R1}\\t%@ double\";
2412
2413     case 2:
2414       ops[0] = operands[0];
2415       ops[1] = XEXP (XEXP (operands[1], 0), 0);
2416       ops[2] = XEXP (XEXP (operands[1], 0), 1);
2417       if (!INTVAL (ops[2]) || const_ok_for_arm (INTVAL (ops[2])))
2418         output_asm_insn (\"add%?\\t%0, %1, %2\", ops);
2419       else
2420         output_asm_insn (\"sub%?\\t%0, %1, #%n2\", ops);
2421       return \"ldm%?ia\\t%0, {%0, %R0}\\t%@ double\";
2422
2423     case 3:
2424     case 4:
2425       return \"mvf%?d\\t%0, %1\";
2426
2427     case 5: return \"mnf%?d\\t%0, #%N1\";
2428     case 6: return \"ldf%?d\\t%0, %1\";
2429     case 7: return \"stf%?d\\t%1, %0\";
2430     case 8: return output_mov_double_fpu_from_arm (operands);
2431     case 9: return output_mov_double_arm_from_fpu (operands);
2432     case 10: return output_move_double (operands);
2433     }
2434 }
2435 "
2436 [(set_attr "length" "4,4,8,4,4,4,4,4,8,8,8")
2437  (set_attr "type" 
2438 "load,store2,load,ffarith,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
2439
2440 (define_expand "movxf"
2441   [(set (match_operand:XF 0 "general_operand" "")
2442         (match_operand:XF 1 "general_operand" ""))]
2443   "ENABLE_XF_PATTERNS"
2444   "")
2445
2446 ;; Even when the XFmode patterns aren't enabled, we enable this after
2447 ;; reloading so that we can push floating point registers in the prologue.
2448
2449 (define_insn ""
2450   [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
2451         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
2452   "ENABLE_XF_PATTERNS || reload_completed"
2453   "*
2454   switch (which_alternative)
2455     {
2456     case 0: return \"mvf%?e\\t%0, %1\";
2457     case 1: return \"mnf%?e\\t%0, #%N1\";
2458     case 2: return \"ldf%?e\\t%0, %1\";
2459     case 3: return \"stf%?e\\t%1, %0\";
2460     case 4: return output_mov_long_double_fpu_from_arm (operands);
2461     case 5: return output_mov_long_double_arm_from_fpu (operands);
2462     case 6: return output_mov_long_double_arm_from_arm (operands);
2463     }
2464 "
2465 [(set_attr "length" "4,4,4,4,8,8,12")
2466  (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
2467 \f
2468
2469 ;; load- and store-multiple insns
2470 ;; The arm can load/store any set of registers, provided that they are in
2471 ;; ascending order; but that is beyond GCC so stick with what it knows.
2472
2473 (define_expand "load_multiple"
2474   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2475                           (match_operand:SI 1 "" ""))
2476                      (use (match_operand:SI 2 "" ""))])]
2477   ""
2478   "
2479   /* Support only fixed point registers */
2480   if (GET_CODE (operands[2]) != CONST_INT
2481       || INTVAL (operands[2]) > 14
2482       || INTVAL (operands[2]) < 2
2483       || GET_CODE (operands[1]) != MEM
2484       || GET_CODE (operands[0]) != REG
2485       || REGNO (operands[0]) > 14
2486       || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
2487     FAIL;
2488
2489   operands[3]
2490             = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
2491                                      force_reg (SImode, XEXP (operands[1], 0)),
2492                                      TRUE, FALSE);
2493 ")
2494
2495 ;; Load multiple with write-back
2496
2497 (define_insn ""
2498   [(match_parallel 0 "load_multiple_operation"
2499                    [(set (match_operand:SI 1 "s_register_operand" "+r")
2500                          (plus:SI (match_dup 1)
2501                                   (match_operand:SI 2 "immediate_operand" "n")))
2502                     (set (match_operand:SI 3 "s_register_operand" "=r")
2503                          (mem:SI (match_dup 1)))])]
2504   "(INTVAL (operands[2])  == 4 * (XVECLEN (operands[0], 0) - 2))"
2505   "*
2506 {
2507   rtx ops[3];
2508   int count = XVECLEN (operands[0], 0);
2509
2510   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2511   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
2512   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
2513
2514   output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
2515   return \"\";
2516 }
2517 "
2518 [(set_attr "type" "load")])
2519
2520 ;; Ordinary load multiple
2521
2522 (define_insn ""
2523   [(match_parallel 0 "load_multiple_operation"
2524                    [(set (match_operand:SI 1 "s_register_operand" "=r")
2525                          (match_operand:SI 2 "indirect_operand" "Q"))])]
2526   ""
2527   "*
2528 {
2529   rtx ops[3];
2530   int count = XVECLEN (operands[0], 0);
2531
2532   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2533   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
2534   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
2535
2536   output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
2537   return \"\";
2538 }
2539 "
2540 [(set_attr "type" "load")])
2541
2542 (define_expand "store_multiple"
2543   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2544                           (match_operand:SI 1 "" ""))
2545                      (use (match_operand:SI 2 "" ""))])]
2546   ""
2547   "
2548   /* Support only fixed point registers */
2549   if (GET_CODE (operands[2]) != CONST_INT
2550       || INTVAL (operands[2]) > 14
2551       || INTVAL (operands[2]) < 2
2552       || GET_CODE (operands[1]) != REG
2553       || GET_CODE (operands[0]) != MEM
2554       || REGNO (operands[1]) > 14
2555       || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
2556     FAIL;
2557
2558   operands[3]
2559            = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
2560                                      force_reg (SImode, XEXP (operands[0], 0)),
2561                                      TRUE, FALSE);
2562 ")
2563
2564 ;; Store multiple with write-back
2565
2566 (define_insn ""
2567   [(match_parallel 0 "store_multiple_operation"
2568                    [(set (match_operand:SI 1 "s_register_operand" "+r")
2569                          (plus:SI (match_dup 1)
2570                                   (match_operand:SI 2 "immediate_operand" "n")))
2571                     (set (mem:SI (match_dup 1))
2572                          (match_operand:SI 3 "s_register_operand" "r"))])]
2573   "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
2574   "*
2575 {
2576   rtx ops[3];
2577   int count = XVECLEN (operands[0], 0);
2578
2579   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2580   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
2581   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
2582
2583   output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
2584   return \"\";
2585 }
2586 "
2587 [(set (attr "type")
2588       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2589                 (const_string "store2")
2590              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
2591                 (const_string "store3")]
2592           (const_string "store4")))])
2593
2594 ;; Ordinary store multiple
2595
2596 (define_insn ""
2597   [(match_parallel 0 "store_multiple_operation"
2598                    [(set (match_operand:SI 2 "indirect_operand" "=Q")
2599                          (match_operand:SI 1 "s_register_operand" "r"))])]
2600   ""
2601   "*
2602 {
2603   rtx ops[3];
2604   int count = XVECLEN (operands[0], 0);
2605
2606   ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
2607   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
2608   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
2609
2610   output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
2611   return \"\";
2612 }
2613 "
2614 [(set (attr "type")
2615       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
2616                 (const_string "store2")
2617              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2618                 (const_string "store3")]
2619           (const_string "store4")))])
2620
2621 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
2622 ;; We could let this apply for blocks of less than this, but it clobbers so
2623 ;; many registers that there is then probably a better way.
2624
2625 (define_expand "movstrqi"
2626   [(match_operand:BLK 0 "general_operand" "")
2627    (match_operand:BLK 1 "general_operand" "")
2628    (match_operand:SI 2 "const_int_operand" "")
2629    (match_operand:SI 3 "const_int_operand" "")]
2630   ""
2631   "
2632   if (arm_gen_movstrqi (operands))
2633     DONE;
2634   FAIL;
2635 ")
2636 \f
2637
2638 ;; Comparison and test insns
2639
2640 (define_expand "cmpsi"
2641   [(set (reg:CC 24)
2642         (compare:CC (match_operand:SI 0 "s_register_operand" "")
2643                     (match_operand:SI 1 "arm_add_operand" "")))]
2644   ""
2645   "
2646 {
2647   arm_compare_op0 = operands[0];
2648   arm_compare_op1 = operands[1];
2649   arm_compare_fp = 0;
2650   DONE;
2651 }
2652 ")
2653
2654 (define_expand "cmpsf"
2655   [(set (reg:CC 24)
2656         (compare:CC (match_operand:SF 0 "s_register_operand" "")
2657                     (match_operand:SF 1 "fpu_rhs_operand" "")))]
2658   ""
2659   "
2660 {
2661   arm_compare_op0 = operands[0];
2662   arm_compare_op1 = operands[1];
2663   arm_compare_fp = 1;
2664   DONE;
2665 }
2666 ")
2667
2668 (define_expand "cmpdf"
2669   [(set (reg:CC 24)
2670         (compare:CC (match_operand:DF 0 "s_register_operand" "")
2671                     (match_operand:DF 1 "fpu_rhs_operand" "")))]
2672   ""
2673   "
2674 {
2675   arm_compare_op0 = operands[0];
2676   arm_compare_op1 = operands[1];
2677   arm_compare_fp = 1;
2678   DONE;
2679 }
2680 ")
2681
2682 (define_expand "cmpxf"
2683   [(set (reg:CC 24)
2684         (compare:CC (match_operand:XF 0 "s_register_operand" "")
2685                     (match_operand:XF 1 "fpu_rhs_operand" "")))]
2686   "ENABLE_XF_PATTERNS"
2687   "
2688 {
2689   arm_compare_op0 = operands[0];
2690   arm_compare_op1 = operands[1];
2691   arm_compare_fp = 1;
2692   DONE;
2693 }
2694 ")
2695
2696 (define_insn ""
2697   [(set (match_operand 0 "cc_register" "")
2698         (compare (match_operand:SI 1 "s_register_operand" "r,r")
2699                  (match_operand:SI 2 "arm_add_operand" "rI,L")))]
2700   ""
2701   "@
2702    cmp%?\\t%1, %2
2703    cmn%?\\t%1, #%n2"
2704 [(set_attr "conds" "set")])
2705
2706 (define_insn ""
2707   [(set (match_operand 0 "cc_register" "")
2708         (compare (match_operand:SI 1 "s_register_operand" "r")
2709                  (neg:SI (match_operand:SI 2 "s_register_operand" "r"))))]
2710   ""
2711   "cmn%?\\t%1, %2"
2712 [(set_attr "conds" "set")])
2713
2714 (define_insn ""
2715   [(set (match_operand 0 "cc_register" "")
2716         (compare (match_operand:SI 1 "s_register_operand" "r")
2717                  (match_operator:SI 2 "shift_operator"
2718                   [(match_operand:SI 3 "s_register_operand" "r")
2719                    (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
2720   ""
2721   "cmp%?\\t%1, %3%S2"
2722 [(set_attr "conds" "set")])
2723
2724 (define_insn ""
2725   [(set (match_operand 0 "cc_register" "")
2726         (compare (match_operand:SI 1 "s_register_operand" "r")
2727                  (neg:SI (match_operator:SI 2 "shift_operator"
2728                           [(match_operand:SI 3 "s_register_operand" "r")
2729                            (match_operand:SI 4 "arm_rhs_operand" "rM")]))))]
2730   ""
2731   "cmn%?\\t%1, %3%S2"
2732 [(set_attr "conds" "set")])
2733
2734 (define_insn ""
2735   [(set (reg:CCFP 24)
2736         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
2737                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
2738   ""
2739   "@
2740    cmf%?\\t%0, %1
2741    cnf%?\\t%0, #%N1"
2742 [(set_attr "conds" "set")
2743  (set_attr "type" "f_2_r")])
2744
2745 (define_insn ""
2746   [(set (reg:CCFP 24)
2747         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
2748                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
2749   ""
2750   "@
2751    cmf%?\\t%0, %1
2752    cnf%?\\t%0, #%N1"
2753 [(set_attr "conds" "set")
2754  (set_attr "type" "f_2_r")])
2755
2756 (define_insn ""
2757   [(set (reg:CCFP 24)
2758         (compare:CCFP (float_extend:DF
2759                        (match_operand:SF 0 "s_register_operand" "f,f"))
2760                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
2761   ""
2762   "@
2763    cmf%?\\t%0, %1
2764    cnf%?\\t%0, #%N1"
2765 [(set_attr "conds" "set")
2766  (set_attr "type" "f_2_r")])
2767
2768 (define_insn ""
2769   [(set (reg:CCFP 24)
2770         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
2771                       (float_extend:DF
2772                        (match_operand:SF 1 "s_register_operand" "f"))))]
2773   ""
2774   "cmf%?\\t%0, %1"
2775 [(set_attr "conds" "set")
2776  (set_attr "type" "f_2_r")])
2777
2778 (define_insn ""
2779   [(set (reg:CCFP 24)
2780         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
2781                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
2782   "ENABLE_XF_PATTERNS"
2783   "@
2784    cmf%?\\t%0, %1
2785    cnf%?\\t%0, #%N1"
2786 [(set_attr "conds" "set")
2787  (set_attr "type" "f_2_r")])
2788
2789 (define_insn ""
2790   [(set (reg:CCFPE 24)
2791         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
2792                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
2793   ""
2794   "@
2795    cmf%?\\t%0, %1
2796    cnf%?\\t%0, #%N1"
2797 [(set_attr "conds" "set")
2798  (set_attr "type" "f_2_r")])
2799
2800 (define_insn ""
2801   [(set (reg:CCFPE 24)
2802         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
2803                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
2804   ""
2805   "@
2806    cmf%?e\\t%0, %1
2807    cnf%?e\\t%0, #%N1"
2808 [(set_attr "conds" "set")
2809  (set_attr "type" "f_2_r")])
2810
2811 (define_insn ""
2812   [(set (reg:CCFPE 24)
2813         (compare:CCFPE (float_extend:DF
2814                         (match_operand:SF 0 "s_register_operand" "f,f"))
2815                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
2816   ""
2817   "@
2818    cmf%?e\\t%0, %1
2819    cnf%?e\\t%0, #%N1"
2820 [(set_attr "conds" "set")
2821  (set_attr "type" "f_2_r")])
2822
2823 (define_insn ""
2824   [(set (reg:CCFPE 24)
2825         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
2826                        (float_extend:DF
2827                         (match_operand:SF 1 "s_register_operand" "f"))))]
2828   ""
2829   "cmf%?e\\t%0, %1"
2830 [(set_attr "conds" "set")
2831  (set_attr "type" "f_2_r")])
2832
2833 (define_insn ""
2834   [(set (reg:CCFPE 24)
2835         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
2836                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
2837   "ENABLE_XF_PATTERNS"
2838   "@
2839    cmf%?e\\t%0, %1
2840    cnf%?e\\t%0, #%N1"
2841 [(set_attr "conds" "set")
2842  (set_attr "type" "f_2_r")])
2843
2844 ; This insn allows redundant compares to be removed by cse, nothing should
2845 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
2846 ; is deleted later on. The match_dup will match the mode here, so that
2847 ; mode changes of the condition codes aren't lost by this even though we don't
2848 ; specify what they are.
2849
2850 (define_insn ""
2851   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
2852   ""
2853   "\\t%@ deleted compare"
2854 [(set_attr "conds" "set")
2855  (set_attr "length" "0")])
2856
2857 \f
2858 ;; Conditional branch insns
2859
2860 (define_expand "beq"
2861   [(set (pc)
2862         (if_then_else (eq (match_dup 1) (const_int 0))
2863                       (label_ref (match_operand 0 "" ""))
2864                       (pc)))]
2865   ""
2866   "
2867 {
2868   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
2869                                  arm_compare_fp);
2870 }
2871 ")
2872
2873 (define_expand "bne"
2874   [(set (pc)
2875         (if_then_else (ne (match_dup 1) (const_int 0))
2876                       (label_ref (match_operand 0 "" ""))
2877                       (pc)))]
2878   ""
2879   "
2880 {
2881   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
2882                                  arm_compare_fp);
2883 }
2884 ")
2885
2886 (define_expand "bgt"
2887   [(set (pc)
2888         (if_then_else (gt (match_dup 1) (const_int 0))
2889                       (label_ref (match_operand 0 "" ""))
2890                       (pc)))]
2891   ""
2892   "
2893 {
2894   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
2895                                  arm_compare_fp);
2896 }
2897 ")
2898
2899 (define_expand "ble"
2900   [(set (pc)
2901         (if_then_else (le (match_dup 1) (const_int 0))
2902                       (label_ref (match_operand 0 "" ""))
2903                       (pc)))]
2904   ""
2905   "
2906 {
2907   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
2908                                  arm_compare_fp);
2909 }
2910 ")
2911
2912 (define_expand "bge"
2913   [(set (pc)
2914         (if_then_else (ge (match_dup 1) (const_int 0))
2915                       (label_ref (match_operand 0 "" ""))
2916                       (pc)))]
2917   ""
2918   "
2919 {
2920   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
2921                                  arm_compare_fp);
2922 }
2923 ")
2924
2925 (define_expand "blt"
2926   [(set (pc)
2927         (if_then_else (lt (match_dup 1) (const_int 0))
2928                       (label_ref (match_operand 0 "" ""))
2929                       (pc)))]
2930   ""
2931   "
2932 {
2933   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
2934                                  arm_compare_fp);
2935 }
2936 ")
2937
2938 (define_expand "bgtu"
2939   [(set (pc)
2940         (if_then_else (gtu (match_dup 1) (const_int 0))
2941                       (label_ref (match_operand 0 "" ""))
2942                       (pc)))]
2943   ""
2944   "
2945 {
2946   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
2947                                  arm_compare_fp);
2948 }
2949 ")
2950
2951 (define_expand "bleu"
2952   [(set (pc)
2953         (if_then_else (leu (match_dup 1) (const_int 0))
2954                       (label_ref (match_operand 0 "" ""))
2955                       (pc)))]
2956   ""
2957   "
2958 {
2959   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
2960                                  arm_compare_fp);
2961 }
2962 ")
2963
2964 (define_expand "bgeu"
2965   [(set (pc)
2966         (if_then_else (geu (match_dup 1) (const_int 0))
2967                       (label_ref (match_operand 0 "" ""))
2968                       (pc)))]
2969   ""
2970   "
2971 {
2972   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
2973                                  arm_compare_fp);
2974 }
2975 ")
2976
2977 (define_expand "bltu"
2978   [(set (pc)
2979         (if_then_else (ltu (match_dup 1) (const_int 0))
2980                       (label_ref (match_operand 0 "" ""))
2981                       (pc)))]
2982   ""
2983   "
2984 {
2985   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
2986                                  arm_compare_fp);
2987 }
2988 ")
2989
2990 ;; patterns to match conditional branch insns
2991
2992 (define_insn ""
2993   [(set (pc)
2994         (if_then_else (match_operator 1 "comparison_operator"
2995                                         [(reg 24) (const_int 0)])
2996                       (label_ref (match_operand 0 "" ""))
2997                       (pc)))]
2998   ""
2999   "*
3000 {
3001   extern int arm_ccfsm_state;
3002
3003   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3004   {
3005     arm_ccfsm_state += 2;
3006     return \"\";
3007   }
3008   return \"b%d1\\t%l0\";
3009 }"
3010 [(set_attr "conds" "use")])
3011
3012 (define_insn ""
3013   [(set (pc)
3014         (if_then_else (match_operator 1 "comparison_operator"
3015                                         [(reg 24) (const_int 0)])
3016                       (pc)
3017                       (label_ref (match_operand 0 "" ""))))]
3018   "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
3019   "*
3020 {
3021   extern int arm_ccfsm_state;
3022
3023   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3024   {
3025     arm_ccfsm_state += 2;
3026     return \"\";
3027   }
3028   return \"b%D1\\t%l0\";
3029 }"
3030 [(set_attr "conds" "use")])
3031 \f
3032
3033 ; scc insns
3034
3035 (define_expand "seq"
3036   [(set (match_operand:SI 0 "s_register_operand" "=r")
3037         (eq:SI (match_dup 1) (const_int 0)))]
3038   ""
3039   "
3040 {
3041   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3042                                  arm_compare_fp);
3043 }
3044 ")
3045
3046 (define_expand "sne"
3047   [(set (match_operand:SI 0 "s_register_operand" "=r")
3048         (ne:SI (match_dup 1) (const_int 0)))]
3049   ""
3050   "
3051 {
3052   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3053                                  arm_compare_fp);
3054 }
3055 ")
3056
3057 (define_expand "sgt"
3058   [(set (match_operand:SI 0 "s_register_operand" "=r")
3059         (gt:SI (match_dup 1) (const_int 0)))]
3060   ""
3061   "
3062 {
3063   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3064                                  arm_compare_fp);
3065 }
3066 ")
3067
3068 (define_expand "sle"
3069   [(set (match_operand:SI 0 "s_register_operand" "=r")
3070         (le:SI (match_dup 1) (const_int 0)))]
3071   ""
3072   "
3073 {
3074   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3075                                  arm_compare_fp);
3076 }
3077 ")
3078
3079 (define_expand "sge"
3080   [(set (match_operand:SI 0 "s_register_operand" "=r")
3081         (ge:SI (match_dup 1) (const_int 0)))]
3082   ""
3083   "
3084 {
3085   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3086                                  arm_compare_fp);
3087 }
3088 ")
3089
3090 (define_expand "slt"
3091   [(set (match_operand:SI 0 "s_register_operand" "=r")
3092         (lt:SI (match_dup 1) (const_int 0)))]
3093   ""
3094   "
3095 {
3096   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3097                                  arm_compare_fp);
3098 }
3099 ")
3100
3101 (define_expand "sgtu"
3102   [(set (match_operand:SI 0 "s_register_operand" "=r")
3103         (gtu:SI (match_dup 1) (const_int 0)))]
3104   ""
3105   "
3106 {
3107   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3108                                  arm_compare_fp);
3109 }
3110 ")
3111
3112 (define_expand "sleu"
3113   [(set (match_operand:SI 0 "s_register_operand" "=r")
3114         (leu:SI (match_dup 1) (const_int 0)))]
3115   ""
3116   "
3117 {
3118   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3119                                  arm_compare_fp);
3120 }
3121 ")
3122
3123 (define_expand "sgeu"
3124   [(set (match_operand:SI 0 "s_register_operand" "=r")
3125         (geu:SI (match_dup 1) (const_int 0)))]
3126   ""
3127   "
3128 {
3129   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3130                                  arm_compare_fp);
3131 }
3132 ")
3133
3134 (define_expand "sltu"
3135   [(set (match_operand:SI 0 "s_register_operand" "=r")
3136         (ltu:SI (match_dup 1) (const_int 0)))]
3137   ""
3138   "
3139 {
3140   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3141                                  arm_compare_fp);
3142 }
3143 ")
3144
3145 (define_insn ""
3146   [(set (match_operand:SI 0 "s_register_operand" "=r")
3147         (match_operator:SI 1 "comparison_operator" [(reg 24) (const_int 0)]))]
3148   ""
3149   "mov%d1\\t%0, #1\;mov%D1\\t%0, #0"
3150 [(set_attr "conds" "use")
3151  (set_attr "length" "8")])
3152
3153 (define_insn ""
3154   [(set (match_operand:SI 0 "s_register_operand" "=r")
3155         (neg:SI (match_operator:SI 1 "comparison_operator"
3156                  [(reg 24) (const_int 0)])))]
3157   ""
3158   "mvn%d1\\t%0, #0\;mov%D1\\t%0, #0"
3159 [(set_attr "conds" "use")
3160  (set_attr "length" "8")])
3161
3162 (define_insn ""
3163   [(set (match_operand:SI 0 "s_register_operand" "=r")
3164         (not:SI (match_operator:SI 1 "comparison_operator"
3165                  [(reg 24) (const_int 0)])))]
3166   ""
3167   "mvn%d1\\t%0, #1\;mov%D1\\t%0, #0"
3168 [(set_attr "conds" "use")
3169  (set_attr "length" "8")])
3170
3171 \f
3172 ;; Jump and linkage insns
3173
3174 (define_insn "jump"
3175   [(set (pc)
3176         (label_ref (match_operand 0 "" "")))]
3177   ""
3178   "*
3179 {
3180   extern int arm_ccfsm_state;
3181
3182   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3183   {
3184     arm_ccfsm_state += 2;
3185     return \"\";
3186   }
3187   return \"b%?\\t%l0\";
3188 }")
3189
3190 (define_expand "call"
3191   [(parallel [(call (match_operand 0 "memory_operand" "")
3192                     (match_operand 1 "general_operand" ""))
3193               (clobber (reg:SI 14))])]
3194   ""
3195   "")
3196
3197 (define_insn ""
3198   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
3199          (match_operand 1 "" "g"))
3200    (clobber (reg:SI 14))]
3201   ""
3202   "*
3203   return output_call (operands);
3204 "
3205 [(set (attr "conds")
3206       (if_then_else (eq_attr "cpu" "arm6")
3207                     (const_string "clob")
3208                     (const_string "nocond")))
3209 ;; length is worst case, normally it is only two
3210  (set_attr "length" "12")
3211  (set_attr "type" "call")])
3212
3213 (define_insn ""
3214   [(call (mem:SI (match_operand 0 "memory_operand" "m"))
3215          (match_operand 1 "general_operand" "g"))
3216    (clobber (reg:SI 14))]
3217   ""
3218   "*
3219   return output_call_mem (operands);
3220 "
3221 [(set (attr "conds")
3222       (if_then_else (eq_attr "cpu" "arm6")
3223                     (const_string "clob")
3224                     (const_string "nocond")))
3225  (set_attr "length" "12")
3226  (set_attr "type" "call")])
3227
3228 (define_expand "call_value"
3229   [(parallel [(set (match_operand 0 "" "=rf")
3230                    (call (match_operand 1 "memory_operand" "m")
3231                          (match_operand 2 "general_operand" "g")))
3232               (clobber (reg:SI 14))])]
3233   ""
3234   "")
3235
3236 (define_insn ""
3237   [(set (match_operand 0 "" "=rf")
3238         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
3239               (match_operand 2 "general_operand" "g")))
3240    (clobber (reg:SI 14))]
3241   ""
3242   "*
3243   return output_call (&operands[1]);
3244 "
3245 [(set (attr "conds")
3246       (if_then_else (eq_attr "cpu" "arm6")
3247                     (const_string "clob")
3248                     (const_string "nocond")))
3249  (set_attr "length" "12")
3250  (set_attr "type" "call")])
3251
3252 (define_insn ""
3253   [(set (match_operand 0 "" "=rf")
3254         (call (mem:SI (match_operand 1 "memory_operand" "m"))
3255         (match_operand 2 "general_operand" "g")))
3256    (clobber (reg:SI 14))]
3257   "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
3258   "*
3259   return output_call_mem (&operands[1]);
3260 "
3261 [(set (attr "conds")
3262       (if_then_else (eq_attr "cpu" "arm6")
3263                     (const_string "clob")
3264                     (const_string "nocond")))
3265  (set_attr "length" "12")
3266  (set_attr "type" "call")])
3267
3268 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
3269 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
3270
3271 (define_insn ""
3272   [(call (mem:SI (match_operand:SI 0 "" "i"))
3273          (match_operand:SI 1 "general_operand" "g"))
3274    (clobber (reg:SI 14))]
3275   "GET_CODE (operands[0]) == SYMBOL_REF"
3276   "bl%?\\t%a0"
3277 [(set (attr "conds")
3278       (if_then_else (eq_attr "cpu" "arm6")
3279                     (const_string "clob")
3280                     (const_string "nocond")))
3281  (set_attr "type" "call")])
3282
3283 (define_insn ""
3284   [(set (match_operand 0 "s_register_operand" "=rf")
3285         (call (mem:SI (match_operand:SI 1 "" "i"))
3286         (match_operand:SI 2 "general_operand" "g")))
3287    (clobber (reg:SI 14))]
3288   "GET_CODE(operands[1]) == SYMBOL_REF"
3289   "bl%?\\t%a1"
3290 [(set (attr "conds")
3291       (if_then_else (eq_attr "cpu" "arm6")
3292                     (const_string "clob")
3293                     (const_string "nocond")))
3294  (set_attr "type" "call")])
3295
3296 ;; Often the return insn will be the same as loading from memory, so set attr
3297 (define_insn "return"
3298   [(return)]
3299   "USE_RETURN_INSN"
3300   "*
3301 {
3302   extern int arm_ccfsm_state;
3303
3304   if (arm_ccfsm_state == 2)
3305   {
3306     arm_ccfsm_state += 2;
3307     return \"\";
3308   }
3309   return output_return_instruction (NULL, TRUE);
3310 }"
3311 [(set_attr "type" "load")])
3312
3313 (define_insn ""
3314   [(set (pc)
3315         (if_then_else (match_operator 0 "comparison_operator"
3316                        [(reg 24) (const_int 0)])
3317                       (return)
3318                       (pc)))]
3319   "USE_RETURN_INSN"
3320   "*
3321 {
3322   extern int arm_ccfsm_state;
3323
3324   if (arm_ccfsm_state == 2)
3325   {
3326     arm_ccfsm_state += 2;
3327     return \"\";
3328   }
3329   return output_return_instruction (operands[0], TRUE);
3330 }"
3331 [(set_attr "conds" "use")
3332  (set_attr "type" "load")])
3333
3334 (define_insn ""
3335   [(set (pc)
3336         (if_then_else (match_operator 0 "comparison_operator"
3337                        [(reg 24) (const_int 0)])
3338                       (pc)
3339                       (return)))]
3340   "USE_RETURN_INSN"
3341   "*
3342 {
3343   extern int arm_ccfsm_state;
3344
3345   if (arm_ccfsm_state == 2)
3346   {
3347     arm_ccfsm_state += 2;
3348     return \"\";
3349   }
3350   return output_return_instruction 
3351         (gen_rtx (reverse_condition (GET_CODE (operands[0])),
3352                   GET_MODE (operands[0]), XEXP (operands[0], 0),
3353                   XEXP (operands[0], 1)),
3354          TRUE);
3355 }"
3356 [(set_attr "conds" "use")
3357  (set_attr "type" "load")])
3358
3359 ;; Call subroutine returning any type.
3360
3361 (define_expand "untyped_call"
3362   [(parallel [(call (match_operand 0 "" "")
3363                     (const_int 0))
3364               (match_operand 1 "" "")
3365               (match_operand 2 "" "")])]
3366   ""
3367   "
3368 {
3369   int i;
3370
3371   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
3372
3373   for (i = 0; i < XVECLEN (operands[2], 0); i++)
3374     {
3375       rtx set = XVECEXP (operands[2], 0, i);
3376       emit_move_insn (SET_DEST (set), SET_SRC (set));
3377     }
3378
3379   /* The optimizer does not know that the call sets the function value
3380      registers we stored in the result block.  We avoid problems by
3381      claiming that all hard registers are used and clobbered at this
3382      point.  */
3383   emit_insn (gen_blockage ());
3384
3385   DONE;
3386 }")
3387
3388 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
3389 ;; all of memory.  This blocks insns from being moved across this point.
3390
3391 (define_insn "blockage"
3392   [(unspec_volatile [(const_int 0)] 0)]
3393   ""
3394   ""
3395 [(set_attr "length" "0")
3396  (set_attr "type" "block")])
3397
3398 (define_insn "tablejump"
3399   [(set (pc)
3400         (match_operand:SI 0 "s_register_operand" "r"))
3401    (use (label_ref (match_operand 1 "" "")))]
3402   ""
3403   "mov%?\\t%|pc, %0\\t%@ table jump, label %l1")
3404
3405 (define_insn ""
3406   [(set (pc)
3407         (match_operand:SI 0 "memory_operand" "m"))
3408    (use (label_ref (match_operand 1 "" "")))]
3409   ""
3410   "ldr%?\\t%|pc, %0\\t%@ table jump, label %l1"
3411 [(set_attr "type" "load")])
3412
3413 (define_insn "indirect_jump"
3414   [(set (pc)
3415         (match_operand:SI 0 "s_register_operand" "r"))]
3416   ""
3417   "mov%?\\t%|pc, %0\\t%@ indirect jump")
3418
3419 (define_insn ""
3420   [(set (pc)
3421         (match_operand:SI 0 "memory_operand" "m"))]
3422   ""
3423   "ldr%?\\t%|pc, %0\\t%@ indirect jump"
3424 [(set_attr "type" "load")])
3425 \f
3426 ;; Misc insns
3427
3428 (define_insn "nop"
3429   [(const_int 0)]
3430   ""
3431   "mov%?\\tr0, r0\\t%@ nop")
3432 \f
3433 ;; Patterns to allow combination of arithmetic, cond code and shifts
3434
3435 (define_insn ""
3436   [(set (match_operand:SI 0 "s_register_operand" "=r")
3437         (match_operator:SI 1 "shiftable_operator"
3438           [(match_operator:SI 3 "shift_operator"
3439              [(match_operand:SI 4 "s_register_operand" "r")
3440               (match_operand:SI 5 "reg_or_int_operand" "rI")])
3441            (match_operand:SI 2 "s_register_operand" "r")]))]
3442   ""
3443   "%i1%?\\t%0, %2, %4%S3")
3444
3445 (define_insn ""
3446   [(set (reg:CC_NOOV 24)
3447         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3448                           [(match_operator:SI 3 "shift_operator"
3449                             [(match_operand:SI 4 "s_register_operand" "r")
3450                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
3451                            (match_operand:SI 2 "s_register_operand" "r")])
3452                          (const_int 0)))
3453    (set (match_operand:SI 0 "s_register_operand" "=r")
3454         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
3455                          (match_dup 2)]))]
3456   ""
3457   "%i1%?s\\t%0, %2, %4%S3"
3458 [(set_attr "conds" "set")])
3459
3460 (define_insn ""
3461   [(set (reg:CC_NOOV 24)
3462         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3463                           [(match_operator:SI 3 "shift_operator"
3464                             [(match_operand:SI 4 "s_register_operand" "r")
3465                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
3466                            (match_operand:SI 2 "s_register_operand" "r")])
3467                          (const_int 0)))
3468    (clobber (match_scratch:SI 0 "=r"))]
3469   ""
3470   "%i1%?s\\t%0, %2, %4%S3"
3471 [(set_attr "conds" "set")])
3472
3473 (define_insn ""
3474   [(set (match_operand:SI 0 "s_register_operand" "=r")
3475         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3476                   (match_operator:SI 2 "shift_operator"
3477                    [(match_operand:SI 3 "s_register_operand" "r")
3478                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
3479   ""
3480   "sub%?\\t%0, %1, %3%S2")
3481
3482 (define_insn ""
3483   [(set (reg:CC_NOOV 24)
3484         (compare:CC_NOOV
3485          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3486                    (match_operator:SI 2 "shift_operator"
3487                     [(match_operand:SI 3 "s_register_operand" "r")
3488                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
3489          (const_int 0)))
3490    (set (match_operand:SI 0 "s_register_operand" "=r")
3491         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
3492                                                  (match_dup 4)])))]
3493   ""
3494   "sub%?s\\t%0, %1, %3%S2"
3495 [(set_attr "conds" "set")])
3496
3497 (define_insn ""
3498   [(set (reg:CC_NOOV 24)
3499         (compare:CC_NOOV
3500          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3501                    (match_operator:SI 2 "shift_operator"
3502                     [(match_operand:SI 3 "s_register_operand" "r")
3503                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
3504          (const_int 0)))
3505    (clobber (match_scratch:SI 0 "=r"))]
3506   ""
3507   "sub%?s\\t%0, %1, %3%S2"
3508 [(set_attr "conds" "set")])
3509
3510 ;; These variants of the above insns can occur if the first operand is the
3511 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
3512 ;; seem to be a way around it.  Most of the predicates have to be null
3513 ;; because the format can be generated part way through reload, so
3514 ;; if we don't match it as soon as it becomes available, reload doesn't know
3515 ;; how to reload pseudos that haven't got hard registers; the constraints will
3516 ;; sort everything out.
3517
3518 (define_insn ""
3519   [(set (match_operand:SI 0 "" "=&r")
3520         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
3521                            [(match_operand:SI 3 "" "r")
3522                             (match_operand:SI 4 "" "rM")])
3523                           (match_operand:SI 2 "" "r"))
3524                  (match_operand:SI 1 "const_int_operand" "n")))]
3525   "reload_in_progress"
3526   "*
3527   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
3528   operands[2] = operands[1];
3529   operands[1] = operands[0];
3530   return output_add_immediate (operands);
3531 "
3532 ; we have no idea how long the add_immediate is, it could be up to 4.
3533 [(set_attr "length" "20")])
3534
3535 (define_insn ""
3536   [(set (reg:CC_NOOV 24)
3537         (compare:CC_NOOV (plus:SI
3538                           (plus:SI 
3539                            (match_operator:SI 5 "shift_operator"
3540                             [(match_operand:SI 3 "" "r")
3541                              (match_operand:SI 4 "" "rM")])
3542                            (match_operand:SI 1 "" "r"))
3543                           (match_operand:SI 2 "const_int_operand" "n"))
3544                          (const_int 0)))
3545    (set (match_operand:SI 0 "" "=&r")
3546         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
3547                           (match_dup 1))
3548                  (match_dup 2)))]
3549   "reload_in_progress"
3550   "*
3551   output_add_immediate (operands);
3552   return \"add%?s\\t%0, %0, %3%S5\";
3553 "
3554 [(set_attr "conds" "set")
3555  (set_attr "length" "20")])
3556
3557 (define_insn ""
3558   [(set (reg:CC_NOOV 24)
3559         (compare:CC_NOOV (plus:SI
3560                           (plus:SI 
3561                            (match_operator:SI 5 "shift_operator"
3562                             [(match_operand:SI 3 "" "r")
3563                              (match_operand:SI 4 "" "rM")])
3564                            (match_operand:SI 1 "" "r"))
3565                           (match_operand:SI 2 "const_int_operand" "n"))
3566                          (const_int 0)))
3567    (clobber (match_scratch:SI 0 "=&r"))]
3568   "reload_in_progress"
3569   "*
3570   output_add_immediate (operands);
3571   return \"add%?s\\t%0, %0, %3%S5\";
3572 "
3573 [(set_attr "conds" "set")
3574  (set_attr "length" "20")])
3575
3576 ;; These are similar, but are needed when the mla pattern contains the
3577 ;; eliminated register as operand 3.
3578
3579 (define_insn ""
3580   [(set (match_operand:SI 0 "" "=&r,&r")
3581         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
3582                                    (match_operand:SI 2 "" "r,r"))
3583                           (match_operand:SI 3 "" "r,r"))
3584                  (match_operand:SI 4 "const_int_operand" "n,n")))]
3585   "reload_in_progress"
3586   "*
3587   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
3588   operands[2] = operands[4];
3589   operands[1] = operands[0];
3590   return output_add_immediate (operands);
3591 "
3592 [(set_attr "length" "20")])
3593
3594 (define_insn ""
3595   [(set (reg:CC_NOOV 24)
3596         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
3597                                             (match_operand:SI 3 "" "r")
3598                                             (match_operand:SI 4 "" "r"))
3599                                            (match_operand:SI 1 "" "r"))
3600                                   (match_operand:SI 2 "const_int_operand" "n"))
3601                          (const_int 0)))
3602    (set (match_operand:SI 0 "" "=&r")
3603         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
3604                  (match_dup 2)))]
3605   "reload_in_progress"
3606   "*
3607   output_add_immediate (operands);
3608   output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
3609   return \"\";
3610 "
3611 [(set_attr "length" "20")
3612  (set_attr "conds" "set")])
3613
3614 (define_insn ""
3615   [(set (reg:CC_NOOV 24)
3616         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
3617                                             (match_operand:SI 3 "" "r")
3618                                             (match_operand:SI 4 "" "r"))
3619                                            (match_operand:SI 1 "" "r"))
3620                                   (match_operand:SI 2 "const_int_operand" "n"))
3621                          (const_int 0)))
3622    (clobber (match_scratch:SI 0 "=&r"))]
3623   "reload_in_progress"
3624   "*
3625   output_add_immediate (operands);
3626   return \"mla%?s\\t%0, %3, %4, %0\";
3627 "
3628 [(set_attr "length" "20")
3629  (set_attr "conds" "set")])
3630
3631
3632 \f
3633
3634 (define_insn ""
3635   [(set (match_operand:SI 0 "s_register_operand" "=r")
3636         (and:SI (match_operator 1 "comparison_operator"
3637                  [(reg 24) (const_int 0)])
3638                 (match_operand:SI 2 "s_register_operand" "r")))]
3639   ""
3640   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
3641 [(set_attr "conds" "use")
3642  (set_attr "length" "8")])
3643
3644 (define_insn ""
3645   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3646         (ior:SI (match_operator 2 "comparison_operator"
3647                  [(reg 24) (const_int 0)])
3648                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
3649   ""
3650   "@
3651    orr%d2\\t%0, %1, #1
3652    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
3653 [(set_attr "conds" "use")
3654  (set_attr "length" "4,8")])
3655
3656 (define_insn ""
3657   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3658         (match_operator 1 "comparison_operator"
3659          [(match_operand:SI 2 "s_register_operand" "r,r")
3660           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
3661    (clobber (reg 24))]
3662   ""
3663   "*
3664   if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
3665     return \"mov\\t%0, %2, lsr #31\";
3666
3667   if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
3668     return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
3669
3670   if (GET_CODE (operands[1]) == NE)
3671     {
3672       if (which_alternative == 1)
3673         return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
3674       return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
3675     }
3676   if (which_alternative == 1)
3677     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
3678   else
3679     output_asm_insn (\"cmp\\t%2, %3\", operands);
3680   return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
3681 "
3682 [(set_attr "conds" "clob")
3683  (set_attr "length" "12")])
3684
3685 (define_insn ""
3686   [(set (match_operand:SI 0 "s_register_operand" "=&r")
3687         (ior:SI (match_operator 1 "comparison_operator"
3688                  [(match_operand:SI 2 "s_register_operand" "r")
3689                   (match_operand:SI 3 "arm_rhs_operand" "rI")])
3690                 (match_operator 4 "comparison_operator"
3691                  [(match_operand:SI 5 "s_register_operand" "r")
3692                   (match_operand:SI 6 "arm_rhs_operand" "rI")])))
3693    (clobber (reg 24))]
3694   ""
3695   "*
3696 {
3697   int dominant = comparison_dominates_p (GET_CODE (operands[4]),
3698                                          GET_CODE (operands[1]));
3699
3700   output_asm_insn (dominant ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
3701                    operands);
3702   output_asm_insn (\"mov\\t%0, #0\", operands);
3703   if (GET_CODE (operands[1]) == GET_CODE (operands[4])
3704       || comparison_dominates_p (GET_CODE (operands[1]),
3705                                  GET_CODE (operands[4]))
3706       || dominant)
3707     output_asm_insn (dominant ? \"cmp%D4\\t%2, %3\" : \"cmp%D1\\t%5,%6\",
3708                      operands);
3709   else
3710     output_asm_insn (\"mov%d1\\t%0, #1\;cmp\\t%5, %6\", operands);
3711   return dominant ? \"mov%d1\\t%0, #1\" : \"mov%d4\\t%0, #1\";
3712 }
3713 "
3714 [(set_attr "conds" "clob")
3715 ; worst case length
3716  (set_attr "length" "20")])
3717
3718 (define_split
3719   [(set (pc)
3720         (if_then_else
3721          (match_operator 5 "equality_operator"
3722           [(ior:SI (match_operator 6 "comparison_operator"
3723                     [(match_operand:SI 0 "s_register_operand" "")
3724                      (match_operand:SI 1 "arm_add_operand" "")])
3725                    (match_operator 7 "comparison_operator"
3726                     [(match_operand:SI 2 "s_register_operand" "")
3727                      (match_operand:SI 3 "arm_add_operand" "")]))
3728           (const_int 0)])
3729          (label_ref (match_operand 4 "" ""))
3730          (pc)))
3731    (clobber (reg 24))]
3732   "(GET_CODE (operands[6]) == GET_CODE (operands[7])
3733     || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[7]))
3734     || comparison_dominates_p (GET_CODE (operands[7]), GET_CODE (operands[6])))"
3735   [(set (reg:CC 24)
3736         (compare:CC (ior:CC (match_op_dup 6
3737                              [(match_dup 0) (match_dup 1)])
3738                             (match_op_dup 7
3739                              [(match_dup 2) (match_dup 3)]))
3740                     (const_int 0)))
3741    (set (pc)
3742         (if_then_else (match_op_dup 5 [(reg:CC 24) (const_int 0)])
3743                       (label_ref (match_dup 4))
3744                       (pc)))]
3745   "
3746 {
3747   enum rtx_code code = comparison_dominates_p (GET_CODE (operands[6]),
3748                                                GET_CODE (operands[7]))
3749                        ? GET_CODE (operands[7]) : GET_CODE (operands[6]);
3750
3751   if (GET_CODE (operands[5]) == NE)
3752     operands[5] = gen_rtx (code, CCmode,
3753                            XEXP (operands[5], 0), XEXP (operands[5], 1));
3754   else
3755     operands[5] = gen_rtx (reverse_condition (code), CCmode,
3756                            XEXP (operands[5], 0), XEXP (operands[5], 1));
3757 }
3758 ")
3759
3760 ;; Don't match these patterns if we can use a conditional compare, since they
3761 ;; tell the final prescan branch elimator code that full branch inlining
3762 ;; can't be done.
3763
3764 (define_insn ""
3765   [(set (pc)
3766         (if_then_else
3767          (ne (ior:SI (match_operator 5 "comparison_operator"
3768                       [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
3769                        (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
3770                      (match_operator 6 "comparison_operator"
3771                       [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
3772                        (match_operand:SI 3 "arm_rhs_operand" "rI,rI,L,L")]))
3773              (const_int 0))
3774          (label_ref (match_operand 4 "" ""))
3775          (pc)))
3776    (clobber (reg 24))]
3777   "!(GET_CODE (operands[5]) == GET_CODE (operands[6])
3778      || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[6]))
3779      || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[5])))"
3780   "*
3781 {
3782   extern int arm_ccfsm_state;
3783
3784   if (which_alternative & 1)
3785     output_asm_insn (\"cmn\\t%0, #%n1\;b%d5\\t%l4\", operands);
3786   else
3787     output_asm_insn (\"cmp\\t%0, %1\;b%d5\\t%l4\", operands);
3788
3789   if (which_alternative >= 2)
3790     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
3791   else
3792     output_asm_insn (\"cmp\\t%2, %3\", operands);
3793
3794   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3795   {
3796     arm_ccfsm_state += 2;
3797     return \"\";
3798   }
3799   return \"b%d6\\t%l4\";
3800 }"
3801 [(set_attr "conds" "jump_clob")
3802  (set_attr "length" "16")])
3803
3804 (define_insn ""
3805   [(set (reg:CC 24)
3806         (compare:CC
3807          (ior:CC (match_operator 4 "comparison_operator"
3808                   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
3809                    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
3810                  (match_operator 5 "comparison_operator"
3811                   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
3812                    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
3813          (const_int 0)))]
3814   "(GET_CODE (operands[4]) == GET_CODE (operands[5])
3815     || comparison_dominates_p (GET_CODE (operands[4]), GET_CODE (operands[5]))
3816     || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))"
3817   "*
3818   if (comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))
3819     {
3820       if (which_alternative >= 2)
3821         output_asm_insn (\"cmn\\t%2, #%n3\", operands);
3822       else
3823         output_asm_insn (\"cmp\\t%2, %3\", operands);
3824
3825       if (which_alternative & 1)
3826         return \"cmn%D5\\t%0, #%n1\";
3827       return \"cmp%D5\\t%0, %1\";
3828     }
3829
3830   if (which_alternative & 1)
3831     output_asm_insn (\"cmn\\t%0, #%n1\", operands);
3832   else
3833     output_asm_insn (\"cmp\\t%0, %1\", operands);
3834
3835   if (which_alternative >= 2)
3836     return \"cmn%D4\\t%2, #%n3\";
3837   return \"cmp%D4\\t%2, %3\";
3838 "
3839 [(set_attr "conds" "set")
3840  (set_attr "length" "8")])
3841
3842 (define_insn ""
3843   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3844         (if_then_else (match_operator 3 "equality_operator"
3845                        [(match_operator 4 "comparison_operator"
3846                          [(reg 24) (const_int 0)])
3847                         (const_int 0)])
3848                       (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
3849                       (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
3850   ""
3851   "*
3852   if (GET_CODE (operands[3]) == NE)
3853     {
3854       if (which_alternative != 0)
3855         output_asm_insn (\"mov%d4\\t%0, %1\", operands);
3856       if (which_alternative != 1)
3857         output_asm_insn (\"mov%D4\\t%0, %2\", operands);
3858       return \"\";
3859     }
3860   if (which_alternative != 0)
3861     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
3862   if (which_alternative != 1)
3863     output_asm_insn (\"mov%d4\\t%0, %2\", operands);
3864   return \"\";
3865 "
3866 [(set_attr "conds" "use")
3867  (set_attr "length" "4,4,8")])
3868
3869 (define_insn ""
3870   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3871         (match_operator:SI 5 "shiftable_operator" 
3872          [(match_operator:SI 4 "comparison_operator"
3873            [(match_operand:SI 2 "s_register_operand" "r,r")
3874             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3875           (match_operand:SI 1 "s_register_operand" "0,?r")]))
3876    (clobber (reg 24))]
3877   ""
3878   "*
3879   if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
3880     return \"%i5\\t%0, %1, %2, lsr #31\";
3881
3882   output_asm_insn (\"cmp\\t%2, %3\", operands);
3883   if (GET_CODE (operands[5]) == AND)
3884     output_asm_insn (\"mov%D4\\t%0, #0\", operands);
3885   else if (which_alternative != 0)
3886     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
3887   return \"%i5%d4\\t%0, %1, #1\";
3888 "
3889 [(set_attr "conds" "clob")
3890  (set_attr "length" "12")])
3891
3892 (define_insn ""
3893   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3894         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
3895                   (match_operator:SI 4 "comparison_operator"
3896                    [(match_operand:SI 2 "s_register_operand" "r,r")
3897                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
3898    (clobber (reg 24))]
3899   ""
3900   "*
3901   output_asm_insn (\"cmp\\t%2, %3\", operands);
3902   if (which_alternative != 0)
3903     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
3904   return \"sub%d4\\t%0, %1, #1\";
3905 "
3906 [(set_attr "conds" "clob")
3907  (set_attr "length" "8,12")])
3908
3909 (define_insn ""
3910   [(set (match_operand:SI 0 "s_register_operand" "=&r")
3911         (and:SI (match_operator 1 "comparison_operator"
3912                  [(match_operand:SI 2 "s_register_operand" "r")
3913                   (match_operand:SI 3 "arm_rhs_operand" "rI")])
3914                 (match_operator 4 "comparison_operator"
3915                  [(match_operand:SI 5 "s_register_operand" "r")
3916                   (match_operand:SI 6 "arm_rhs_operand" "rI")])))
3917    (clobber (reg 24))]
3918   ""
3919   "*
3920 {
3921   int dominant =
3922         comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
3923                                 reverse_condition (GET_CODE (operands[4])))
3924         ? 1 
3925         : comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
3926                                   reverse_condition (GET_CODE (operands[1])))
3927         ? 2 : 0;
3928   output_asm_insn (dominant == 2 ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
3929                        operands);
3930   output_asm_insn (\"mov\\t%0, #1\", operands);
3931   if (GET_CODE (operands[1]) == GET_CODE (operands[4]) || dominant)
3932     {
3933       output_asm_insn (dominant == 2 ? \"cmp%d4\\t%2, %3\"
3934                            : \"cmp%d1\\t%5, %6\", operands);
3935     }
3936   else
3937     {
3938       output_asm_insn (\"mov%D1\\t%0, #0\", operands);
3939       output_asm_insn (\"cmp\\t%5, %6\", operands);
3940     }
3941   return dominant == 2 ? \"mov%D1\\t%0, #0\" : \"mov%D4\\t%0, #0\";
3942 }
3943 "
3944 [(set_attr "conds" "clob")
3945  (set_attr "length" "20")])
3946
3947 (define_split
3948   [(set (pc)
3949         (if_then_else (match_operator 1 "equality_operator"
3950                        [(and:SI (match_operator 2 "comparison_operator"
3951                                  [(match_operand:SI 3 "s_register_operand" "")
3952                                   (match_operand:SI 4 "arm_add_operand" "")])
3953                                 (match_operator 0 "comparison_operator"
3954                                  [(match_operand:SI 5 "s_register_operand" "")
3955                                   (match_operand:SI 6 "arm_add_operand" "")]))
3956                         (const_int 0)])
3957                       (label_ref (match_operand 7 "" ""))
3958                       (pc)))
3959    (clobber (reg 24))]
3960   "(GET_CODE (operands[2]) == GET_CODE (operands[0])
3961     || comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
3962                                reverse_condition (GET_CODE (operands[0])))
3963     || comparison_dominates_p (reverse_condition (GET_CODE (operands[0])),
3964                                reverse_condition (GET_CODE (operands[2]))))"
3965   [(set (reg:CC 24)
3966         (compare:CC (ior:CC (match_op_dup 2
3967                              [(match_dup 3) (match_dup 4)])
3968                             (match_op_dup 0
3969                              [(match_dup 5) (match_dup 6)]))
3970                     (const_int 0)))
3971    (set (pc)
3972         (if_then_else (match_op_dup 1 [(reg:CC 24) (const_int 0)])
3973                       (label_ref (match_dup 7))
3974                       (pc)))]
3975   "
3976 {
3977   /* Use DeMorgans law to convert this into an IOR of the inverse conditions 
3978      This is safe since we only do it for integer comparisons. */
3979   enum rtx_code code = 
3980         comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
3981                                 reverse_condition (GET_CODE (operands[0])))
3982         ? GET_CODE (operands[0]) : GET_CODE (operands[2]);
3983
3984   operands[2] = gen_rtx (reverse_condition (GET_CODE (operands[2])),
3985                          GET_MODE (operands[2]), operands[3], operands[4]);
3986   operands[0] = gen_rtx (reverse_condition (GET_CODE (operands[0])),
3987                          GET_MODE (operands[0]), operands[5], operands[6]);
3988   if (GET_CODE (operands[1]) == NE)
3989     operands[1] = gen_rtx (code, CCmode,
3990                            XEXP (operands[1], 0), XEXP (operands[1], 1));
3991   else
3992     operands[1] = gen_rtx (reverse_condition (code), CCmode,
3993                            XEXP (operands[1], 0), XEXP (operands[1], 1));
3994 }
3995 ")
3996
3997 ;; Don't match these patterns if we can use a conditional compare, since they
3998 ;; tell the final prescan branch elimator code that full branch inlining
3999 ;; can't be done.
4000
4001 (define_insn ""
4002   [(set (pc)
4003         (if_then_else
4004          (eq (and:SI (match_operator 1 "comparison_operator"
4005                       [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4006                        (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L")])
4007                      (match_operator 4 "comparison_operator"
4008                       [(match_operand:SI 5 "s_register_operand" "r,r,r,r")
4009                        (match_operand:SI 6 "arm_rhs_operand" "rI,rI,L,L")]))
4010              (const_int 0))
4011          (label_ref (match_operand 0 "" ""))
4012          (pc)))
4013    (clobber (reg 24))]
4014   "!(GET_CODE (operands[1]) == GET_CODE (operands[4])
4015      || comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
4016                                 reverse_condition (GET_CODE (operands[4])))
4017      || comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
4018                                 reverse_condition (GET_CODE (operands[1]))))"
4019   "*
4020 {
4021   extern int arm_ccfsm_state;
4022
4023   if (which_alternative & 1)
4024     output_asm_insn (\"cmn\\t%2, #%n3\;b%D1\\t%l0\", operands);
4025   else
4026     output_asm_insn (\"cmp\\t%2, %3\;b%D1\\t%l0\", operands);
4027
4028   if (which_alternative >= 2)
4029     output_asm_insn (\"cmn\\t%5, #%n6\", operands);
4030   else
4031     output_asm_insn (\"cmp\\t%5, %6\", operands);
4032
4033   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4034   {
4035     arm_ccfsm_state += 2;
4036     return \"\";
4037   }
4038   return \"b%D4\\t%l0\";
4039 }"
4040 [(set_attr "conds" "jump_clob")
4041  (set_attr "length" "16")])
4042
4043 (define_insn ""
4044   [(set (match_operand:SI 0 "s_register_operand" "=r")
4045         (neg:SI (match_operator 3 "comparison_operator"
4046                  [(match_operand:SI 1 "s_register_operand" "r")
4047                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4048    (clobber (reg 24))]
4049   ""
4050   "*
4051   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4052     return \"mov\\t%0, %1, asr #31\";
4053
4054   if (GET_CODE (operands[3]) == NE)
4055     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4056
4057   if (GET_CODE (operands[3]) == GT)
4058     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4059
4060   output_asm_insn (\"cmp\\t%1, %2\", operands);
4061   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4062   return \"mvn%d3\\t%0, #0\";
4063 "
4064 [(set_attr "conds" "clob")
4065  (set_attr "length" "12")])
4066
4067 (define_insn "movcond"
4068   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4069         (if_then_else:SI
4070          (match_operator 5 "comparison_operator"
4071           [(match_operand:SI 3 "s_register_operand" "r,r,r")
4072            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4073          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4074          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4075    (clobber (reg 24))]
4076   ""
4077   "*
4078   if (GET_CODE (operands[5]) == LT
4079       && (operands[4] == const0_rtx))
4080     {
4081       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4082         {
4083           if (operands[2] == const0_rtx)
4084             return \"and\\t%0, %1, %3, asr #31\";
4085           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4086         }
4087       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4088         {
4089           if (operands[1] == const0_rtx)
4090             return \"bic\\t%0, %2, %3, asr #31\";
4091           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4092         }
4093       /* The only case that falls through to here is when both ops 1 & 2
4094          are constants */
4095     }
4096
4097   if (GET_CODE (operands[5]) == GE
4098       && (operands[4] == const0_rtx))
4099     {
4100       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4101         {
4102           if (operands[2] == const0_rtx)
4103             return \"bic\\t%0, %1, %3, asr #31\";
4104           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4105         }
4106       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4107         {
4108           if (operands[1] == const0_rtx)
4109             return \"and\\t%0, %2, %3, asr #31\";
4110           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4111         }
4112       /* The only case that falls through to here is when both ops 1 & 2
4113          are constants */
4114     }
4115   if (GET_CODE (operands[4]) == CONST_INT
4116       && !const_ok_for_arm (INTVAL (operands[4])))
4117     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4118   else
4119     output_asm_insn (\"cmp\\t%3, %4\", operands);
4120   if (which_alternative != 0)
4121     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4122   if (which_alternative != 1)
4123     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4124   return \"\";
4125 "
4126 [(set_attr "conds" "clob")
4127  (set_attr "length" "8,8,12")])
4128
4129 (define_insn ""
4130   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4131         (if_then_else:SI (match_operator 9 "comparison_operator"
4132                           [(match_operand:SI 5 "s_register_operand" "r,r")
4133                            (match_operand:SI 6 "arm_add_operand" "rI,L")])
4134                          (match_operator:SI 8 "shiftable_operator"
4135                           [(match_operand:SI 1 "s_register_operand" "r,r")
4136                            (match_operand:SI 2 "arm_rhs_operand" "rI,rI")])
4137                          (match_operator:SI 7 "shiftable_operator"
4138                           [(match_operand:SI 3 "s_register_operand" "r,r")
4139                            (match_operand:SI 4 "arm_rhs_operand" "rI,rI")])))
4140    (clobber (reg 24))]
4141   ""
4142   "@
4143    cmp\\t%5, %6\;%I8%d9\\t%0, %1, %2\;%I7%D9\\t%0, %3, %4
4144    cmn\\t%5, #%n6\;%I8%d9\\t%0, %1, %2\;%I7%D9\\t%0, %3, %4"
4145 [(set_attr "conds" "clob")
4146  (set_attr "length" "12")])
4147
4148 (define_insn ""
4149   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4150         (if_then_else:SI (match_operator 6 "comparison_operator"
4151                           [(match_operand:SI 2 "s_register_operand" "r,r")
4152                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
4153                          (match_operator:SI 7 "shiftable_operator"
4154                           [(match_operand:SI 4 "s_register_operand" "r,r")
4155                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
4156                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4157    (clobber (reg 24))]
4158   ""
4159   "*
4160   /* If we have an operation where (op x 0) is the identity operation and
4161      the condtional operator is LT or GE and we are comparing against zero and
4162      everything is in registers then we can do this in two instructions */
4163   if (operands[3] == const0_rtx
4164       && GET_CODE (operands[7]) != AND
4165       && GET_CODE (operands[5]) == REG
4166       && GET_CODE (operands[1]) == REG 
4167       && REGNO (operands[1]) == REGNO (operands[4])
4168       && REGNO (operands[4]) != REGNO (operands[0]))
4169     {
4170       if (GET_CODE (operands[6]) == LT)
4171         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4172       else if (GET_CODE (operands[6]) == GE)
4173         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4174     }
4175   if (GET_CODE (operands[3]) == CONST_INT
4176       && !const_ok_for_arm (INTVAL (operands[3])))
4177     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4178   else
4179     output_asm_insn (\"cmp\\t%2, %3\", operands);
4180   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
4181   if (which_alternative != 0)
4182     {
4183       if (GET_CODE (operands[1]) == MEM)
4184         return \"ldr%D6\\t%0, %1\";
4185       else
4186         return \"mov%D6\\t%0, %1\";
4187     }
4188   return \"\";
4189 "
4190 [(set_attr "conds" "clob")
4191  (set_attr "length" "8,12")])
4192
4193 (define_insn ""
4194   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4195         (if_then_else:SI (match_operator 6 "comparison_operator"
4196                           [(match_operand:SI 4 "s_register_operand" "r,r")
4197                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4198                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4199                          (match_operator:SI 7 "shiftable_operator"
4200                           [(match_operand:SI 2 "s_register_operand" "r,r")
4201                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4202    (clobber (reg 24))]
4203   ""
4204   "*
4205   /* If we have an operation where (op x 0) is the identity operation and
4206      the condtional operator is LT or GE and we are comparing against zero and
4207      everything is in registers then we can do this in two instructions */
4208   if (operands[5] == const0_rtx
4209       && GET_CODE (operands[7]) != AND
4210       && GET_CODE (operands[3]) == REG
4211       && GET_CODE (operands[1]) == REG 
4212       && REGNO (operands[1]) == REGNO (operands[2])
4213       && REGNO (operands[2]) != REGNO (operands[0]))
4214     {
4215       if (GET_CODE (operands[6]) == GE)
4216         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4217       else if (GET_CODE (operands[6]) == LT)
4218         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4219     }
4220
4221   if (GET_CODE (operands[5]) == CONST_INT
4222       && !const_ok_for_arm (INTVAL (operands[5])))
4223     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4224   else
4225     output_asm_insn (\"cmp\\t%4, %5\", operands);
4226
4227   if (which_alternative != 0)
4228     {
4229       if (GET_CODE (operands[1]) == MEM)
4230         output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4231       else
4232         output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4233     }
4234   return \"%I7%D6\\t%0, %2, %3\";
4235 "
4236 [(set_attr "conds" "clob")
4237  (set_attr "length" "8,12")])
4238
4239 (define_insn ""
4240   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4241         (if_then_else:SI (match_operator 6 "comparison_operator"
4242                           [(match_operand:SI 4 "s_register_operand" "r,r")
4243                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4244                          (plus:SI
4245                           (match_operand:SI 2 "s_register_operand" "r,r")
4246                           (match_operand:SI 3 "arm_add_operand" "rL,rL"))
4247                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4248    (clobber (reg 24))]
4249   ""
4250   "*
4251 {
4252   if (GET_CODE (operands[5]) == CONST_INT
4253       && !const_ok_for_arm (INTVAL (operands[5])))
4254     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4255   else
4256     output_asm_insn (\"cmp\\t%4, %5\", operands);
4257   if (GET_CODE (operands[3]) == CONST_INT
4258       && !const_ok_for_arm (INTVAL (operands[3])))
4259     output_asm_insn (\"sub%d6\\t%0, %2, #%n3\", operands);
4260   else
4261     output_asm_insn (\"add%d6\\t%0, %2, %3\", operands);
4262   if (which_alternative != 0)
4263     {
4264       if (GET_CODE (operands[1]) == MEM)
4265         output_asm_insn (\"ldr%D6\\t%0, %1\", operands);
4266       else
4267         output_asm_insn (\"mov%D6\\t%0, %1\", operands);
4268     }
4269   return \"\";
4270 }
4271 "
4272 [(set_attr "conds" "clob")
4273  (set_attr "length" "8,12")])
4274
4275 (define_insn ""
4276   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4277         (if_then_else:SI (match_operator 6 "comparison_operator"
4278                           [(match_operand:SI 4 "s_register_operand" "r,r")
4279                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4280                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4281                          (plus:SI
4282                           (match_operand:SI 2 "s_register_operand" "r,r")
4283                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4284    (clobber (reg 24))]
4285   ""
4286   "*
4287 {
4288   if (GET_CODE (operands[5]) == CONST_INT
4289       && !const_ok_for_arm (INTVAL (operands[5])))
4290     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4291   else
4292     output_asm_insn (\"cmp\\t%4, %5\", operands);
4293   if (GET_CODE (operands[3]) == CONST_INT
4294       && !const_ok_for_arm (INTVAL (operands[3])))
4295     output_asm_insn (\"sub%D6\\t%0, %2, #%n3\", operands);
4296   else
4297     output_asm_insn (\"add%D6\\t%0, %2, %3\", operands);
4298   if (which_alternative != 0)
4299     {
4300       if (GET_CODE (operands[6]) == MEM)
4301         output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4302       else
4303         output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4304     }
4305   return \"\";
4306 }
4307 "
4308 [(set_attr "conds" "clob")
4309  (set_attr "length" "8,12")])
4310
4311 (define_insn ""
4312   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4313         (if_then_else:SI (match_operator 5 "comparison_operator"
4314                           [(match_operand:SI 3 "s_register_operand" "r,r")
4315                            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
4316                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4317                          (not:SI
4318                           (match_operand:SI 2 "s_register_operand" "r,r"))))
4319    (clobber (reg 24))]
4320   ""
4321   "#"
4322 [(set_attr "conds" "clob")
4323  (set_attr "length" "8,12")])
4324
4325 (define_insn ""
4326   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4327         (if_then_else:SI 
4328          (match_operator 5 "comparison_operator"
4329           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4330            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4331          (not:SI
4332           (match_operand:SI 2 "s_register_operand" "r,r,r,r"))
4333          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4334    (clobber (reg 24))]
4335   ""
4336   "@
4337    cmp\\t%3, %4\;mvn%d5\\t%0, %2
4338    cmn\\t%3, #%n4\;mvn%d5\\t%0, %2
4339    cmp\\t%3, %4\;mov%D5\\t%0, %1\;mvn%d5\\t%0, %2
4340    cmn\\t%3, #%n4\;mov%D5\\t%0, %1\;mvn%d5\\t%0, %2"
4341 [(set_attr "conds" "clob")
4342  (set_attr "length" "8,8,12,12")])
4343
4344 (define_insn ""
4345   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4346         (if_then_else:SI
4347          (match_operator 6 "comparison_operator"
4348           [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
4349            (match_operand:SI 5 "arm_add_operand" "rI,L,rI,L")])
4350          (match_operator:SI 7 "shift_operator"
4351           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4352            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM,rM")])
4353          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4354    (clobber (reg 24))]
4355   ""
4356   "@
4357    cmp\\t%4, %5\;mov%d6\\t%0, %2%S7
4358    cmn\\t%4, #%n5\;mov%d6\\t%0, %2%S7
4359    cmp\\t%4, %5\;mov%D6\\t%0, %1\;mov%d6\\t%0, %2%S7
4360    cmn\\t%4, #%n5\;mov%D6\\t%0, %1\;mov%d6\\t%0, %2%S7"
4361 [(set_attr "conds" "clob")
4362  (set_attr "length" "8,8,12,12")])
4363
4364 (define_insn ""
4365   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4366         (if_then_else:SI
4367          (match_operator 6 "comparison_operator"
4368           [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
4369            (match_operand:SI 5 "arm_add_operand" "rI,L,rI,L")])
4370          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4371          (match_operator:SI 7 "shift_operator"
4372           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4373            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM,rM")])))
4374    (clobber (reg 24))]
4375   ""
4376   "@
4377    cmp\\t%4, %5\;mov%D6\\t%0, %2%S7
4378    cmn\\t%4, #%n5\;mov%D6\\t%0, %2%S7
4379    cmp\\t%4, %5\;mov%d6\\t%0, %1\;mov%D6\\t%0, %2%S7
4380    cmn\\t%4, #%n5\;mov%d6\\t%0, %1\;mov%D6\\t%0, %2%S7"
4381 [(set_attr "conds" "clob")
4382  (set_attr "length" "8,8,12,12")])
4383
4384 (define_insn ""
4385   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4386         (if_then_else:SI
4387          (match_operator 7 "comparison_operator"
4388           [(match_operand:SI 5 "s_register_operand" "r,r")
4389            (match_operand:SI 6 "arm_add_operand" "rI,L")])
4390          (match_operator:SI 8 "shift_operator"
4391           [(match_operand:SI 1 "s_register_operand" "r,r")
4392            (match_operand:SI 2 "arm_rhs_operand" "rM,rM")])
4393          (match_operator:SI 9 "shift_operator"
4394           [(match_operand:SI 3 "s_register_operand" "r,r")
4395            (match_operand:SI 4 "arm_rhs_operand" "rI,rI")])))
4396    (clobber (reg 24))]
4397   ""
4398   "@
4399    cmp\\t%5, %6\;mov%d7\\t%0, %1%S8\;mov%D7\\t%0, %3%S9
4400    cmn\\t%5, #%n6\;mov%d7\\t%0, %1%S8\;mov%D7\\t%0, %3%S9"
4401 [(set_attr "conds" "clob")
4402  (set_attr "length" "12")])
4403
4404 (define_insn ""
4405   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4406         (if_then_else:SI
4407          (match_operator 6 "comparison_operator"
4408           [(match_operand:SI 4 "s_register_operand" "r,r")
4409            (match_operand:SI 5 "arm_add_operand" "rI,L")])
4410          (not:SI (match_operand:SI 1 "s_register_operand" "r,r"))
4411          (match_operator:SI 7 "shiftable_operator"
4412           [(match_operand:SI 2 "s_register_operand" "r,r")
4413            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4414    (clobber (reg 24))]
4415   ""
4416   "@
4417    cmp\\t%4, %5\;mvn%d6\\t%0, %1\;%I7%D6\\t%0, %2, %3
4418    cmn\\t%4, #%n5\;mvn%d6\\t%0, %1\;%I7%D6\\t%0, %2, %3"
4419 [(set_attr "conds" "clob")
4420  (set_attr "length" "12")])
4421
4422 (define_insn ""
4423   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4424         (if_then_else:SI
4425          (match_operator 6 "comparison_operator"
4426           [(match_operand:SI 4 "s_register_operand" "r,r")
4427            (match_operand:SI 5 "arm_add_operand" "rI,L")])
4428          (match_operator:SI 7 "shiftable_operator"
4429           [(match_operand:SI 2 "s_register_operand" "r,r")
4430            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4431          (not:SI (match_operand:SI 1 "s_register_operand" "r,r"))))
4432    (clobber (reg 24))]
4433   ""
4434   "@
4435    cmp\\t%4, %5\;mvn%D6\\t%0, %1\;%I7%d6\\t%0, %2, %3
4436    cmn\\t%4, #%n5\;mvn%D6\\t%0, %1\;%I7%d6\\t%0, %2, %3"
4437 [(set_attr "conds" "clob")
4438  (set_attr "length" "12")])
4439
4440 (define_insn ""
4441   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4442         (if_then_else:SI
4443          (match_operator 5 "comparison_operator"
4444           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4445            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4446          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r"))
4447          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4448    (clobber (reg:CC 24))]
4449   ""
4450   "@
4451    cmp\\t%3, %4\;rsb%d5\\t%0, %2, #0
4452    cmn\\t%3, #%n4\;rsb%d5\\t%0, %2, #0
4453    cmp\\t%3, %4\;mov%D5\\t%0, %1\;rsb%d5\\t%0, %2, #0
4454    cmn\\t%3, #%n4\;mov%D5\\t%0, %1\;rsb%d5\\t%0, %2, #0"
4455 [(set_attr "conds" "clob")
4456  (set_attr "length" "8,8,12,12")])
4457
4458 (define_insn ""
4459   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4460         (if_then_else:SI
4461          (match_operator 5 "comparison_operator"
4462           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4463            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4464          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4465          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r"))))
4466    (clobber (reg:CC 24))]
4467   ""
4468   "@
4469    cmp\\t%3, %4\;rsb%D5\\t%0, %2, #0
4470    cmn\\t%3, #%n4\;rsb%D5\\t%0, %2, #0
4471    cmp\\t%3, %4\;mov%d5\\t%0, %1\;rsb%D5\\t%0, %2, #0
4472    cmn\\t%3, #%n4\;mov%d5\\t%0, %1\;rsb%D5\\t%0, %2, #0"
4473 [(set_attr "conds" "clob")
4474  (set_attr "length" "8,8,12,12")])
4475
4476 (define_insn ""
4477   [(set (match_operand:SI 0 "s_register_operand" "=r")
4478         (match_operator:SI 1 "shiftable_operator"
4479          [(match_operand:SI 2 "memory_operand" "m")
4480           (match_operand:SI 3 "memory_operand" "m")]))
4481    (clobber (match_scratch:SI 4 "=r"))]
4482   "adjacent_mem_locations (operands[2], operands[3])"
4483   "*
4484 {
4485   rtx ldm[3];
4486   rtx arith[4];
4487   int val1 = 0, val2 = 0;
4488
4489   if (REGNO (operands[0]) > REGNO (operands[4]))
4490     {
4491       ldm[1] = operands[4];
4492       ldm[2] = operands[0];
4493     }
4494   else
4495     {
4496       ldm[1] = operands[0];
4497       ldm[2] = operands[4];
4498     }
4499   if (GET_CODE (XEXP (operands[2], 0)) != REG)
4500     val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
4501   if (GET_CODE (XEXP (operands[3], 0)) != REG)
4502     val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
4503   arith[0] = operands[0];
4504   arith[3] = operands[1];
4505   if (val1 < val2)
4506     {
4507       arith[1] = ldm[1];
4508       arith[2] = ldm[2];
4509     }
4510   else
4511     {
4512       arith[1] = ldm[2];
4513       arith[2] = ldm[1];
4514     }
4515   if (val1 && val2)
4516     {
4517       rtx ops[3];
4518       ldm[0] = ops[0] = operands[4];
4519       ops[1] = XEXP (XEXP (operands[2], 0), 0);
4520       ops[2] = XEXP (XEXP (operands[2], 0), 1);
4521       output_add_immediate (ops);
4522       if (val1 < val2)
4523         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4524       else
4525         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4526     }
4527   else if (val1)
4528     {
4529       ldm[0] = XEXP (operands[3], 0);
4530       if (val1 < val2)
4531         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4532       else
4533         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4534     }
4535   else
4536     {
4537       ldm[0] = XEXP (operands[2], 0);
4538       if (val1 < val2)
4539         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4540       else
4541         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4542     }
4543   output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
4544   return \"\";
4545 }
4546 "
4547 [(set_attr "length" "12")
4548  (set_attr "type" "load")])
4549
4550 ;; the arm can support extended pre-inc instructions
4551
4552 ;; In all these cases, we use operands 0 and 1 for the register being
4553 ;; incremented because those are the operands that local-alloc will
4554 ;; tie and these are the pair most likely to be tieable (and the ones
4555 ;; that will benefit the most).
4556
4557 ;; We reject the frame pointer if it occurs anywhere in these patterns since
4558 ;; elimination will cause too many headaches.
4559
4560 (define_insn ""
4561   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4562                          (match_operand:SI 2 "index_operand" "rJ")))
4563         (match_operand:QI 3 "s_register_operand" "r"))
4564    (set (match_operand:SI 0 "s_register_operand" "=r")
4565         (plus:SI (match_dup 1) (match_dup 2)))]
4566   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4567    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4568    && (GET_CODE (operands[2]) != REG
4569        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4570   "str%?b\\t%3, [%0, %2]!"
4571 [(set_attr "type" "store1")])
4572
4573 (define_insn ""
4574   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4575                           (match_operand:SI 2 "s_register_operand" "r")))
4576         (match_operand:QI 3 "s_register_operand" "r"))
4577    (set (match_operand:SI 0 "s_register_operand" "=r")
4578         (minus:SI (match_dup 1) (match_dup 2)))]
4579   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4580    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4581    && (GET_CODE (operands[2]) != REG
4582        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4583   "str%?b\\t%3, [%0, -%2]!"
4584 [(set_attr "type" "store1")])
4585
4586 (define_insn ""
4587   [(set (match_operand:QI 3 "s_register_operand" "=r")
4588         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4589                          (match_operand:SI 2 "index_operand" "rJ"))))
4590    (set (match_operand:SI 0 "s_register_operand" "=r")
4591         (plus:SI (match_dup 1) (match_dup 2)))]
4592   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4593    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4594    && (GET_CODE (operands[2]) != REG
4595        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4596   "ldr%?b\\t%3, [%0, %2]!"
4597 [(set_attr "type" "load")])
4598
4599 (define_insn ""
4600   [(set (match_operand:QI 3 "s_register_operand" "=r")
4601         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4602                           (match_operand:SI 2 "s_register_operand" "r"))))
4603    (set (match_operand:SI 0 "s_register_operand" "=r")
4604         (minus:SI (match_dup 1) (match_dup 2)))]
4605   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4606    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4607    && (GET_CODE (operands[2]) != REG
4608        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4609   "ldr%?b\\t%3, [%0, -%2]!"
4610 [(set_attr "type" "load")])
4611
4612 (define_insn ""
4613   [(set (match_operand:SI 3 "s_register_operand" "=r")
4614         (zero_extend:SI
4615          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4616                           (match_operand:SI 2 "index_operand" "rJ")))))
4617    (set (match_operand:SI 0 "s_register_operand" "=r")
4618         (plus:SI (match_dup 1) (match_dup 2)))]
4619   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4620    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4621    && (GET_CODE (operands[2]) != REG
4622        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4623   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
4624 [(set_attr "type" "load")])
4625
4626 (define_insn ""
4627   [(set (match_operand:SI 3 "s_register_operand" "=r")
4628         (zero_extend:SI
4629          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4630                            (match_operand:SI 2 "s_register_operand" "r")))))
4631    (set (match_operand:SI 0 "s_register_operand" "=r")
4632         (minus:SI (match_dup 1) (match_dup 2)))]
4633   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4634    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4635    && (GET_CODE (operands[2]) != REG
4636        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4637   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
4638 [(set_attr "type" "load")])
4639
4640 (define_insn ""
4641   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4642                          (match_operand:SI 2 "index_operand" "rJ")))
4643         (match_operand:SI 3 "s_register_operand" "r"))
4644    (set (match_operand:SI 0 "s_register_operand" "=r")
4645         (plus:SI (match_dup 1) (match_dup 2)))]
4646   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4647    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4648    && (GET_CODE (operands[2]) != REG
4649        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4650   "str%?\\t%3, [%0, %2]!"
4651 [(set_attr "type" "store1")])
4652
4653 (define_insn ""
4654   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4655                           (match_operand:SI 2 "s_register_operand" "r")))
4656         (match_operand:SI 3 "s_register_operand" "r"))
4657    (set (match_operand:SI 0 "s_register_operand" "=r")
4658         (minus:SI (match_dup 1) (match_dup 2)))]
4659   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4660    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4661    && (GET_CODE (operands[2]) != REG
4662        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4663   "str%?\\t%3, [%0, -%2]!"
4664 [(set_attr "type" "store1")])
4665
4666 (define_insn ""
4667   [(set (match_operand:SI 3 "s_register_operand" "=r")
4668         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4669                          (match_operand:SI 2 "index_operand" "rJ"))))
4670    (set (match_operand:SI 0 "s_register_operand" "=r")
4671         (plus:SI (match_dup 1) (match_dup 2)))]
4672   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4673    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4674    && (GET_CODE (operands[2]) != REG
4675        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4676   "ldr%?\\t%3, [%0, %2]!"
4677 [(set_attr "type" "load")])
4678
4679 (define_insn ""
4680   [(set (match_operand:SI 3 "s_register_operand" "=r")
4681         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4682                           (match_operand:SI 2 "s_register_operand" "r"))))
4683    (set (match_operand:SI 0 "s_register_operand" "=r")
4684         (minus:SI (match_dup 1) (match_dup 2)))]
4685   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4686    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4687    && (GET_CODE (operands[2]) != REG
4688        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4689   "ldr%?\\t%3, [%0, -%2]!"
4690 [(set_attr "type" "load")])
4691
4692 (define_insn ""
4693   [(set (match_operand:HI 3 "s_register_operand" "=r")
4694         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4695                          (match_operand:SI 2 "index_operand" "rJ"))))
4696    (set (match_operand:SI 0 "s_register_operand" "=r")
4697         (plus:SI (match_dup 1) (match_dup 2)))]
4698   "(! BYTES_BIG_ENDIAN)
4699    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
4700    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4701    && (GET_CODE (operands[2]) != REG
4702        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4703   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
4704 [(set_attr "type" "load")])
4705
4706 (define_insn ""
4707   [(set (match_operand:HI 3 "s_register_operand" "=r")
4708         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4709                           (match_operand:SI 2 "s_register_operand" "r"))))
4710    (set (match_operand:SI 0 "s_register_operand" "=r")
4711         (minus:SI (match_dup 1) (match_dup 2)))]
4712   "(!BYTES_BIG_ENDIAN)
4713    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
4714    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4715    && (GET_CODE (operands[2]) != REG
4716        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4717   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
4718 [(set_attr "type" "load")])
4719
4720 (define_insn ""
4721   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
4722                           [(match_operand:SI 3 "s_register_operand" "r")
4723                            (match_operand:SI 4 "const_shift_operand" "n")])
4724                          (match_operand:SI 1 "s_register_operand" "0")))
4725         (match_operand:QI 5 "s_register_operand" "r"))
4726    (set (match_operand:SI 0 "s_register_operand" "=r")
4727         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
4728                  (match_dup 1)))]
4729   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4730    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4731    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4732   "str%?b\\t%5, [%0, %3%S2]!"
4733 [(set_attr "type" "store1")])
4734
4735 (define_insn ""
4736   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4737                           (match_operator:SI 2 "shift_operator"
4738                            [(match_operand:SI 3 "s_register_operand" "r")
4739                             (match_operand:SI 4 "const_shift_operand" "n")])))
4740         (match_operand:QI 5 "s_register_operand" "r"))
4741    (set (match_operand:SI 0 "s_register_operand" "=r")
4742         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4743                                                  (match_dup 4)])))]
4744   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4745    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4746    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4747   "str%?b\\t%5, [%0, -%3%S2]!"
4748 [(set_attr "type" "store1")])
4749
4750 (define_insn ""
4751   [(set (match_operand:QI 5 "s_register_operand" "=r")
4752         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
4753                           [(match_operand:SI 3 "s_register_operand" "r")
4754                            (match_operand:SI 4 "const_shift_operand" "n")])
4755                          (match_operand:SI 1 "s_register_operand" "0"))))
4756    (set (match_operand:SI 0 "s_register_operand" "=r")
4757         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
4758                  (match_dup 1)))]
4759   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4760    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4761    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4762   "ldr%?b\\t%5, [%0, %3%S2]!"
4763 [(set_attr "type" "load")])
4764
4765 (define_insn ""
4766   [(set (match_operand:QI 5 "s_register_operand" "=r")
4767         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4768                           (match_operator:SI 2 "shift_operator"
4769                            [(match_operand:SI 3 "s_register_operand" "r")
4770                             (match_operand:SI 4 "const_shift_operand" "n")]))))
4771    (set (match_operand:SI 0 "s_register_operand" "=r")
4772         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4773                                                  (match_dup 4)])))]
4774   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4775    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4776    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4777   "ldr%?b\\t%5, [%0, -%3%S2]!"
4778 [(set_attr "type" "load")])
4779
4780 (define_insn ""
4781   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
4782                           [(match_operand:SI 3 "s_register_operand" "r")
4783                            (match_operand:SI 4 "const_shift_operand" "n")])
4784                          (match_operand:SI 1 "s_register_operand" "0")))
4785         (match_operand:SI 5 "s_register_operand" "r"))
4786    (set (match_operand:SI 0 "s_register_operand" "=r")
4787         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
4788                  (match_dup 1)))]
4789   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4790    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4791    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4792   "str%?\\t%5, [%0, %3%S2]!"
4793 [(set_attr "type" "store1")])
4794
4795 (define_insn ""
4796   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4797                           (match_operator:SI 2 "shift_operator"
4798                            [(match_operand:SI 3 "s_register_operand" "r")
4799                             (match_operand:SI 4 "const_shift_operand" "n")])))
4800         (match_operand:SI 5 "s_register_operand" "r"))
4801    (set (match_operand:SI 0 "s_register_operand" "=r")
4802         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4803                                                  (match_dup 4)])))]
4804   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4805    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4806    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4807   "str%?\\t%5, [%0, -%3%S2]!"
4808 [(set_attr "type" "store1")])
4809
4810 (define_insn ""
4811   [(set (match_operand:SI 5 "s_register_operand" "=r")
4812         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
4813                           [(match_operand:SI 3 "s_register_operand" "r")
4814                            (match_operand:SI 4 "const_shift_operand" "n")])
4815                          (match_operand:SI 1 "s_register_operand" "0"))))
4816    (set (match_operand:SI 0 "s_register_operand" "=r")
4817         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
4818                  (match_dup 1)))]
4819   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4820    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4821    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4822   "ldr%?\\t%5, [%0, %3%S2]!"
4823 [(set_attr "type" "load")])
4824
4825 (define_insn ""
4826   [(set (match_operand:SI 5 "s_register_operand" "=r")
4827         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4828                           (match_operator:SI 2 "shift_operator"
4829                            [(match_operand:SI 3 "s_register_operand" "r")
4830                             (match_operand:SI 4 "const_shift_operand" "n")]))))
4831    (set (match_operand:SI 0 "s_register_operand" "=r")
4832         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4833                                                  (match_dup 4)])))]
4834   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4835    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4836    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4837   "ldr%?\\t%5, [%0, -%3%S2]!"
4838 [(set_attr "type" "load")])
4839
4840 (define_insn ""
4841   [(set (match_operand:HI 5 "s_register_operand" "=r")
4842         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
4843                           [(match_operand:SI 3 "s_register_operand" "r")
4844                            (match_operand:SI 4 "const_shift_operand" "n")])
4845                          (match_operand:SI 1 "s_register_operand" "0"))))
4846    (set (match_operand:SI 0 "s_register_operand" "=r")
4847         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
4848                  (match_dup 1)))]
4849   "(! BYTES_BIG_ENDIAN)
4850    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
4851    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4852    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4853   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
4854 [(set_attr "type" "load")])
4855
4856 (define_insn ""
4857   [(set (match_operand:HI 5 "s_register_operand" "=r")
4858         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4859                           (match_operator:SI 2 "shift_operator"
4860                            [(match_operand:SI 3 "s_register_operand" "r")
4861                             (match_operand:SI 4 "const_shift_operand" "n")]))))
4862    (set (match_operand:SI 0 "s_register_operand" "=r")
4863         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4864                                                  (match_dup 4)])))]
4865   "(! BYTES_BIG_ENDIAN)
4866    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
4867    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4868    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
4869   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
4870 [(set_attr "type" "load")])
4871
4872 ; It can also support extended post-inc expressions, but combine doesn't
4873 ; try these....
4874 ; It doesn't seem worth adding peepholes for anything but the most common
4875 ; cases since, unlike combine, the increment must immediately follow the load
4876 ; for this pattern to match.
4877 ; When loading we must watch to see that the base register isn't trampled by
4878 ; the load.  In such cases this isn't a post-inc expression.
4879
4880 (define_peephole
4881   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
4882         (match_operand:QI 2 "s_register_operand" "r"))
4883    (set (match_dup 0)
4884         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
4885   ""
4886   "str%?b\\t%2, [%0], %1")
4887
4888 (define_peephole
4889   [(set (match_operand:QI 0 "s_register_operand" "=r")
4890         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
4891    (set (match_dup 1)
4892         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
4893   "REGNO(operands[0]) != REGNO(operands[1])
4894    && (GET_CODE (operands[2]) != REG
4895        || REGNO(operands[0]) != REGNO (operands[2]))"
4896   "ldr%?b\\t%0, [%1], %2")
4897
4898 (define_peephole
4899   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
4900         (match_operand:SI 2 "s_register_operand" "r"))
4901    (set (match_dup 0)
4902         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
4903   ""
4904   "str%?\\t%2, [%0], %1")
4905
4906 (define_peephole
4907   [(set (match_operand:HI 0 "s_register_operand" "=r")
4908         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
4909    (set (match_dup 1)
4910         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
4911   "(! BYTES_BIG_ENDIAN)
4912    && REGNO(operands[0]) != REGNO(operands[1])
4913    && (GET_CODE (operands[2]) != REG
4914        || REGNO(operands[0]) != REGNO (operands[2]))"
4915   "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
4916
4917 (define_peephole
4918   [(set (match_operand:SI 0 "s_register_operand" "=r")
4919         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
4920    (set (match_dup 1)
4921         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
4922   "REGNO(operands[0]) != REGNO(operands[1])
4923    && (GET_CODE (operands[2]) != REG
4924        || REGNO(operands[0]) != REGNO (operands[2]))"
4925   "ldr%?\\t%0, [%1], %2")
4926
4927 (define_peephole
4928   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
4929                          (match_operand:SI 1 "index_operand" "rJ")))
4930         (match_operand:QI 2 "s_register_operand" "r"))
4931    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
4932   ""
4933   "str%?b\\t%2, [%0, %1]!")
4934
4935 (define_peephole
4936   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
4937                           [(match_operand:SI 0 "s_register_operand" "r")
4938                            (match_operand:SI 1 "const_int_operand" "n")])
4939                          (match_operand:SI 2 "s_register_operand" "+r")))
4940         (match_operand:QI 3 "s_register_operand" "r"))
4941    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
4942                                (match_dup 2)))]
4943   ""
4944   "str%?b\\t%3, [%2, %0%S4]!")
4945
4946 ; This pattern is never tried by combine, so do it as a peephole
4947
4948 (define_peephole
4949   [(set (match_operand:SI 0 "s_register_operand" "=r")
4950         (match_operand:SI 1 "s_register_operand" "r"))
4951    (set (match_operand 2 "cc_register" "")
4952         (compare (match_dup 1) (const_int 0)))]
4953   ""
4954   "sub%?s\\t%0, %1, #0"
4955 [(set_attr "conds" "set")])
4956
4957 ; Peepholes to spot possible load- and store-multiples, if the ordering is
4958 ; reversed, check that the memory references aren't volatile.
4959
4960 (define_peephole
4961   [(set (match_operand:SI 0 "s_register_operand" "=r")
4962         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
4963                          (const_int 12))))
4964    (set (match_operand:SI 2 "s_register_operand" "=r")
4965         (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4966    (set (match_operand:SI 3 "s_register_operand" "=r")
4967         (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4968    (set (match_operand:SI 4 "s_register_operand" "=r")
4969         (mem:SI (match_dup 1)))]
4970   "REGNO (operands[0]) > REGNO (operands[2])
4971    && REGNO (operands[2]) > REGNO (operands[3])
4972    && REGNO (operands[3]) > REGNO (operands[4])
4973    && !(REGNO (operands[1]) == REGNO (operands[0])
4974        || REGNO (operands[1]) == REGNO (operands[2])
4975        || REGNO (operands[1]) == REGNO (operands[3])
4976        || REGNO (operands[1]) == REGNO (operands[4]))
4977    && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
4978    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
4979    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
4980                                          (prev_nonnote_insn (insn)))))
4981    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
4982                                          (prev_nonnote_insn 
4983                                           (prev_nonnote_insn (insn))))))"
4984   "ldm%?ia\\t%1, {%4, %3, %2, %0}\\t%@ phole ldm")
4985
4986 (define_peephole
4987   [(set (match_operand:SI 0 "s_register_operand" "=r")
4988         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
4989                          (const_int 8))))
4990    (set (match_operand:SI 2 "s_register_operand" "=r")
4991         (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4992    (set (match_operand:SI 3 "s_register_operand" "=r")
4993         (mem:SI (match_dup 1)))]
4994   "REGNO (operands[0]) >  REGNO (operands[2])
4995    && REGNO (operands[2]) > REGNO (operands[3])
4996    && !(REGNO (operands[1]) == REGNO (operands[0])
4997        || REGNO (operands[1]) == REGNO (operands[2])
4998        || REGNO (operands[1]) == REGNO (operands[3]))
4999    && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5000    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
5001    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5002                                          (prev_nonnote_insn (insn)))))"
5003   "ldm%?ia\\t%1, {%3, %2, %0}\\t%@ phole ldm")
5004
5005 (define_peephole
5006   [(set (match_operand:SI 0 "s_register_operand" "=r")
5007         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5008                          (const_int 4))))
5009    (set (match_operand:SI 2 "s_register_operand" "=r")
5010         (mem:SI (match_dup 1)))]
5011   "REGNO (operands[0]) > REGNO (operands[2])
5012    && !(REGNO (operands[1]) == REGNO (operands[0])
5013        || REGNO (operands[1]) == REGNO (operands[2]))
5014    && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5015    && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))"
5016   "ldm%?ia\\t%1, {%2, %0}\\t%@ phole ldm")
5017
5018 (define_peephole
5019   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5020                          (const_int 12)))
5021         (match_operand:SI 0 "s_register_operand" "r"))
5022    (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5023         (match_operand:SI 2 "s_register_operand" "r"))
5024    (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5025         (match_operand:SI 3 "s_register_operand" "r"))
5026    (set (mem:SI (match_dup 1))
5027         (match_operand:SI 4 "s_register_operand" "r"))]
5028   "REGNO (operands[0]) >  REGNO (operands[2])
5029    && REGNO (operands[2]) > REGNO (operands[3])
5030    && REGNO (operands[3]) > REGNO (operands[4])
5031    && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5032    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5033    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5034                                           (prev_nonnote_insn (insn)))))
5035    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5036                                           (prev_nonnote_insn 
5037                                            (prev_nonnote_insn (insn))))))"
5038   "stm%?ia\\t%1, {%4, %3, %2, %0}\\t%@ phole stm")
5039
5040 (define_peephole
5041   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5042                          (const_int 8)))
5043         (match_operand:SI 0 "s_register_operand" "r"))
5044    (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5045         (match_operand:SI 2 "s_register_operand" "r"))
5046    (set (mem:SI (match_dup 1))
5047         (match_operand:SI 3 "s_register_operand" "r"))]
5048   "REGNO (operands[0]) >  REGNO (operands[2])
5049    && REGNO (operands[2]) > REGNO (operands[3])
5050    && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5051    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5052    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5053                                           (prev_nonnote_insn (insn)))))"
5054   "stm%?ia\\t%1, {%3, %2, %0}\\t%@ phole stm")
5055
5056 (define_peephole
5057   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5058                          (const_int 4)))
5059         (match_operand:SI 0 "s_register_operand" "r"))
5060    (set (mem:SI (match_dup 1))
5061         (match_operand:SI 2 "s_register_operand" "r"))]
5062   "REGNO (operands[0]) >  REGNO (operands[2])
5063    && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5064    && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))"
5065   "stm%?ia\\t%1, {%2, %0}\\t%@ phole stm")
5066
5067 ;; A call followed by return can be replaced by restoring the regs and
5068 ;; jumping to the subroutine, provided we aren't passing the address of
5069 ;; any of our local variables.  If we call alloca then this is unsafe
5070 ;; since restoring the frame frees the memory, which is not what we want.
5071 ;; Sometimes the return might have been targeted by the final prescan:
5072 ;; if so then emit a propper return insn as well.
5073 ;; Unfortunately, if the frame pointer is required, we don't know if the
5074 ;; current function has any implicit stack pointer adjustments that will 
5075 ;; be restored by the return: we can't therefore do a tail call.
5076 ;; Another unfortunate that we can't handle is if current_function_args_size
5077 ;; is non-zero: in this case elimination of the argument pointer assumed
5078 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5079 ;; calculations.
5080
5081 (define_peephole
5082   [(parallel [(call (mem:SI (match_operand:SI 0 "" "i"))
5083                           (match_operand:SI 1 "general_operand" "g"))
5084                     (clobber (reg:SI 14))])
5085    (return)]
5086   "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN
5087     && !get_frame_size () && !current_function_calls_alloca
5088     && !frame_pointer_needed && !current_function_args_size)"
5089   "*
5090 {
5091   extern rtx arm_target_insn;
5092   extern int arm_ccfsm_state, arm_current_cc;
5093
5094   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5095   {
5096     arm_current_cc ^= 1;
5097     output_return_instruction (NULL, TRUE);
5098     arm_ccfsm_state = 0;
5099     arm_target_insn = NULL;
5100   }
5101
5102   output_return_instruction (NULL, FALSE);
5103   return \"b%?\\t%a0\";
5104 }"
5105 [(set (attr "conds")
5106       (if_then_else (eq_attr "cpu" "arm6")
5107                     (const_string "clob")
5108                     (const_string "nocond")))
5109  (set_attr "length" "8")])
5110
5111 (define_peephole
5112   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5113                    (call (mem:SI (match_operand:SI 1 "" "i"))
5114                          (match_operand:SI 2 "general_operand" "g")))
5115               (clobber (reg:SI 14))])
5116    (return)]
5117   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5118     && !get_frame_size () && !current_function_calls_alloca
5119     && !frame_pointer_needed && !current_function_args_size)"
5120   "*
5121 {
5122   extern rtx arm_target_insn;
5123   extern int arm_ccfsm_state, arm_current_cc;
5124
5125   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5126   {
5127     arm_current_cc ^= 1;
5128     output_return_instruction (NULL, TRUE);
5129     arm_ccfsm_state = 0;
5130     arm_target_insn = NULL;
5131   }
5132
5133   output_return_instruction (NULL, FALSE);
5134   return \"b%?\\t%a1\";
5135 }"
5136 [(set (attr "conds")
5137       (if_then_else (eq_attr "cpu" "arm6")
5138                     (const_string "clob")
5139                     (const_string "nocond")))
5140  (set_attr "length" "8")])
5141
5142 ;; As above but when this function is not void, we must be returning the
5143 ;; result of the called subroutine.
5144
5145 (define_peephole
5146   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5147                    (call (mem:SI (match_operand:SI 1 "" "i"))
5148                          (match_operand:SI 2 "general_operand" "g")))
5149               (clobber (reg:SI 14))])
5150    (use (match_dup 0))
5151    (return)]
5152   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5153     && !get_frame_size () && !current_function_calls_alloca
5154     && !frame_pointer_needed && !current_function_args_size)"
5155   "*
5156 {
5157   extern rtx arm_target_insn;
5158   extern int arm_ccfsm_state, arm_current_cc;
5159
5160   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5161   {
5162     arm_current_cc ^= 1;
5163     output_return_instruction (NULL, TRUE);
5164     arm_ccfsm_state = 0;
5165     arm_target_insn = NULL;
5166   }
5167
5168   output_return_instruction (NULL, FALSE);
5169   return \"b%?\\t%a1\";
5170 }"
5171 [(set (attr "conds")
5172       (if_then_else (eq_attr "cpu" "arm6")
5173                     (const_string "clob")
5174                     (const_string "nocond")))
5175  (set_attr "length" "8")])
5176
5177 ;; If calling a subroutine and then jumping back to somewhere else, but not
5178 ;; too far away, then we can set the link register with the branch address
5179 ;; and jump direct to the subroutine.  On return from the subroutine
5180 ;; execution continues at the branch; this avoids a prefetch stall.
5181 ;; We use the length attribute (via short_branch ()) to establish whether or
5182 ;; not this is possible, this is the same asthe sparc does.
5183
5184 (define_peephole
5185   [(parallel[(call (mem:SI (match_operand:SI 0 "" "i"))
5186                    (match_operand:SI 1 "general_operand" "g"))
5187              (clobber (reg:SI 14))])
5188    (set (pc)
5189         (label_ref (match_operand 2 "" "")))]
5190   "GET_CODE (operands[0]) == SYMBOL_REF 
5191    && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
5192    && arm_insn_not_targeted (insn)"
5193   "*
5194 {
5195   int backward = arm_backwards_branch (INSN_UID (insn),
5196                                        INSN_UID (operands[2]));
5197
5198 #if 0
5199   /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
5200    * above, leaving it out means that the code will still run on an arm 2 or 3
5201    */
5202   if (TARGET_6)
5203     {
5204       if (backward)
5205         output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l2)\", operands);
5206       else
5207         output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l2 - . -8)\", operands);
5208     }
5209   else
5210 #endif
5211     {
5212       output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands);
5213       if (backward)
5214         output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l2)\", operands);
5215       else
5216         output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l2 - . -4)\", operands);
5217     }
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")
5225       (if_then_else (eq_attr "cpu" "arm6")
5226                     (const_int 8)
5227                     (const_int 12)))])
5228
5229 (define_peephole
5230   [(parallel[(set (match_operand:SI 0 "s_register_operand" "=r")
5231                   (call (mem:SI (match_operand:SI 1 "" "i"))
5232                         (match_operand:SI 2 "general_operand" "g")))
5233              (clobber (reg:SI 14))])
5234    (set (pc)
5235         (label_ref (match_operand 3 "" "")))]
5236   "GET_CODE (operands[0]) == SYMBOL_REF
5237    && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
5238    && arm_insn_not_targeted (insn)"
5239   "*
5240 {
5241   int backward = arm_backwards_branch (INSN_UID (insn),
5242                                        INSN_UID (operands[3]));
5243
5244 #if 0
5245   /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
5246    * above, leaving it out means that the code will still run on an arm 2 or 3
5247    */
5248   if (TARGET_6)
5249     {
5250       if (backward)
5251         output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l3)\", operands);
5252       else
5253         output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l3 - . -8)\", operands);
5254     }
5255   else
5256 #endif
5257     {
5258       output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands);
5259       if (backward)
5260         output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l3)\", operands);
5261       else
5262         output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l3 - . -4)\", operands);
5263     }
5264   return \"b%?\\t%a1\";
5265 }"
5266 [(set (attr "conds")
5267       (if_then_else (eq_attr "cpu" "arm6")
5268                     (const_string "clob")
5269                     (const_string "nocond")))
5270  (set (attr "length")
5271       (if_then_else (eq_attr "cpu" "arm6")
5272                     (const_int 8)
5273                     (const_int 12)))])
5274
5275 (define_split
5276   [(set (pc)
5277         (if_then_else (match_operator 0 "comparison_operator"
5278                        [(match_operator:SI 1 "shift_operator"
5279                          [(match_operand:SI 2 "s_register_operand" "r")
5280                           (match_operand:SI 3 "reg_or_int_operand" "rM")])
5281                         (match_operand:SI 4 "s_register_operand" "r")])
5282                       (label_ref (match_operand 5 "" ""))
5283                       (pc)))
5284    (clobber (reg 24))]
5285   ""
5286   [(set (reg:CC 24)
5287         (compare:CC (match_dup 4)
5288                     (match_op_dup 1 [(match_dup 2) (match_dup 3)])))
5289    (set (pc)
5290         (if_then_else (match_op_dup 0 [(reg 24) (const_int 0)])
5291                       (label_ref (match_dup 5))
5292                       (pc)))]
5293   "
5294   operands[0] = gen_rtx (swap_condition (GET_CODE (operands[0])), VOIDmode,
5295                          operands[1], operands[2]);
5296 ")
5297
5298 (define_split
5299   [(set (match_operand:SI 0 "s_register_operand" "")
5300         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
5301                        (const_int 0))
5302                 (neg:SI (match_operator:SI 2 "comparison_operator"
5303                          [(match_operand:SI 3 "s_register_operand" "")
5304                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
5305    (clobber (match_operand:SI 5 "s_register_operand" ""))]
5306   ""
5307   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
5308    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5309                               (match_dup 5)))]
5310   "")
5311
5312 ;; This pattern can be used because cc_noov mode implies that the following
5313 ;; branch will be an equality (EQ or NE), so the sign extension is not
5314 ;; needed.  Combine doesn't eliminate these because by the time it sees the
5315 ;; branch it no-longer knows that the data came from memory.
5316
5317 (define_insn ""
5318   [(set (reg:CC_NOOV 24)
5319         (compare:CC_NOOV
5320          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "m") 0)
5321                     (const_int 24))
5322          (match_operand 1 "immediate_operand" "I")))
5323    (clobber (match_scratch:SI 2 "=r"))]
5324   "((unsigned long) INTVAL (operands[1]))
5325    == (((unsigned long) INTVAL (operands[1])) >> 24) << 24"
5326   "*
5327   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
5328   output_asm_insn (\"ldr%?b\\t%2, %0\", operands);
5329   output_asm_insn (\"cmp%?\\t%2, %1\", operands);
5330   return \"\";
5331 "
5332 [(set_attr "conds" "set")
5333  (set_attr "length" "8")
5334  (set_attr "type" "load")])
5335
5336 (define_expand "prologue"
5337   [(clobber (const_int 0))]
5338   ""
5339   "
5340   arm_expand_prologue ();
5341   DONE;
5342 ")
5343
5344 (define_expand "save_stack_nonlocal"
5345   [(match_operand:DI 0 "memory_operand" "")
5346    (match_operand:SI 1 "s_register_operand" "")]
5347   ""
5348   "
5349 {
5350   /* We also need to save the frame pointer for non-local gotos */
5351   emit_move_insn (operand_subword (operands[0], 0, 0, DImode),
5352                   hard_frame_pointer_rtx);
5353   emit_move_insn (operand_subword (operands[0], 1, 0, DImode), operands[1]);
5354   DONE;
5355 }")
5356
5357 (define_expand "restore_stack_nonlocal"
5358   [(match_operand:SI 0 "s_register_operand" "")
5359    (match_operand:DI 1 "memory_operand" "")]
5360   ""
5361   "
5362 {
5363   /* Restore the frame pointer first, the stack pointer second. */
5364   emit_move_insn (operands[0], operand_subword (operands[1], 1, 0, DImode));
5365   emit_move_insn (hard_frame_pointer_rtx, operand_subword (operands[1], 0, 0,
5366                                                            DImode));
5367   DONE;
5368 }")
5369
5370 ;; This split is only used during output to reduce the number of patterns
5371 ;; that need assembler instructions adding to them.  We allowed the setting
5372 ;; of the conditions to be implicit during rtl generation so that
5373 ;; the conditional compare patterns would work.  However this conflicts to
5374 ;; some extend with the conditional data operations, so we have to split them
5375 ;; up again here.
5376
5377 (define_split
5378   [(set (match_operand:SI 0 "s_register_operand" "")
5379         (if_then_else:SI (match_operator 1 "comparison_operator"
5380                           [(match_operand 2 "" "") (match_operand 3 "" "")])
5381                          (match_operand 4 "" "")
5382                          (match_operand 5 "" "")))
5383    (clobber (reg 24))]
5384   "reload_completed"
5385   [(set (match_dup 6) (match_dup 7))
5386    (set (match_dup 0) 
5387         (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
5388                          (match_dup 4)
5389                          (match_dup 5)))]
5390   "
5391 {
5392   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
5393                                            operands[3]);
5394
5395   operands[6] = gen_rtx (REG, mode, 24);
5396   operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
5397 }
5398 ")
5399
5400
5401 (define_insn ""
5402   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5403         (if_then_else:SI (match_operator 4 "comparison_operator"
5404                           [(match_operand 3 "cc_register" "") (const_int 0)])
5405                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5406                          (not:SI
5407                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
5408   ""
5409   "@
5410    mvn%D4\\t%0, %2
5411    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
5412 [(set_attr "conds" "use")
5413  (set_attr "length" "4,8")])
5414
5415 ;; The next two patterns occur when an AND operation is followed by a
5416 ;; scc insn sequence 
5417
5418 (define_insn ""
5419   [(set (match_operand:SI 0 "s_register_operand" "=r")
5420         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5421                          (const_int 1)
5422                          (match_operand:SI 2 "immediate_operand" "n")))]
5423   ""
5424   "*
5425   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5426   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
5427   return \"mvnne\\t%0, #0\";
5428 "
5429 [(set_attr "conds" "clob")
5430  (set_attr "length" "8")])
5431
5432 (define_insn ""
5433   [(set (match_operand:SI 0 "s_register_operand" "=r")
5434         (not:SI
5435          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5436                           (const_int 1)
5437                           (match_operand:SI 2 "immediate_operand" "n"))))]
5438   ""
5439   "*
5440   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5441   output_asm_insn (\"tst\\t%1, %2\", operands);
5442   output_asm_insn (\"mvneq\\t%0, #0\", operands);
5443   return \"movne\\t%0, #0\";
5444 "
5445 [(set_attr "conds" "clob")
5446  (set_attr "length" "12")])
5447
5448 ;; Push multiple registers to the stack.  The first register is in the
5449 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
5450 ;; expressions.
5451 (define_insn ""
5452   [(match_parallel 2 "multi_register_push"
5453     [(set (match_operand:BLK 0 "memory_operand" "=m")
5454           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
5455   ""
5456   "*
5457 {
5458   char pattern[100];
5459   int i;
5460   extern int lr_save_eliminated;
5461
5462   if (lr_save_eliminated)
5463     {
5464       if (XVECLEN (operands[2], 0) > 1)
5465         abort ();
5466       return \"\";
5467     }
5468   strcpy (pattern, \"stmfd\\t%m0!, {%|%1\");
5469   for (i = 1; i < XVECLEN (operands[2], 0); i++)
5470     {
5471       strcat (pattern, \", %|\");
5472       strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
5473                                               0))]);
5474     }
5475   strcat (pattern, \"}\");
5476   output_asm_insn (pattern, operands);
5477   return \"\";
5478 }"
5479 [(set_attr "type" "store4")])