* arm.md (extendhisi2_mem, movhi, movhi_bytes): Propagate the volatile
[official-gcc.git] / gcc / config / arm / arm.md
blob5a313e4d8e4e5abead7d7097f9f2fa6c7b4c3829
1 ;;- Machine description for Advanced RISC Machines' ARM for GNU compiler
2 ;;  Copyright (C) 1991, 93-97, 1998 Free Software Foundation, Inc.
3 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
4 ;;  and Martin Simmons (@harleqn.co.uk).
5 ;;  More major hacks by Richard Earnshaw (rwe11@cl.cam.ac.uk)
7 ;; This file is part of GNU CC.
9 ;; GNU CC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
14 ;; GNU CC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU CC; see the file COPYING.  If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26 ;; There are patterns in this file to support XFmode arithmetic.
27 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
28 ;; (See arm.h)
30 ;; UNSPEC Usage:
31 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
32 ;;   the mode is MODE_FLOAT
33 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
34 ;;   the mode is MODE_FLOAT
35 ;; 2 `push multiple' operation: operand 0 is the first register.  Subsequent
36 ;;   registers are in parallel (use...) expressions.
37 ;; 3 A symbol that has been treated properly for pic usage, that is, we
38 ;;   will add the pic_register value to it before trying to dereference it.
39 ;; Note: sin and cos are no-longer used.
41 ;; Attributes
43 ; PROG_MODE attribute is used to determine whether condition codes are
44 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
45 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
46 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
48 ; CPU attribute is used to determine whether condition codes are clobbered
49 ; by a call insn: on the arm6 they are if in 32-bit addressing mode; on the
50 ; arm2 and arm3 the condition codes are restored by the return.
52 (define_attr "cpu" "arm2,arm3,arm6,arm7,arm8,st_arm"
53         (const (symbol_ref "arm_cpu_attr")))
55 ; Floating Point Unit.  If we only have floating point emulation, then there
56 ; is no point in scheduling the floating point insns.  (Well, for best
57 ; performance we should try and group them together).
59 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
61 ; LENGTH of an instruction (in bytes)
62 (define_attr "length" "" (const_int 4))
64 ; An assembler sequence may clobber the condition codes without us knowing
65 (define_asm_attributes
66  [(set_attr "conds" "clob")
67   (set_attr "length" "4")])
69 ; TYPE attribute is used to detect floating point instructions which, if
70 ; running on a co-processor can run in parallel with other, basic instructions
71 ; If write-buffer scheduling is enabled then it can also be used in the
72 ; scheduling of writes.
74 ; Classification of each insn
75 ; normal        any data instruction that doesn't hit memory or fp regs
76 ; mult          a multiply instruction
77 ; block         blockage insn, this blocks all functional units
78 ; float         a floating point arithmetic operation (subject to expansion)
79 ; fdivx         XFmode floating point division
80 ; fdivd         DFmode floating point division
81 ; fdivs         SFmode floating point division
82 ; fmul          Floating point multiply
83 ; ffmul         Fast floating point multiply
84 ; farith        Floating point arithmetic (4 cycle)
85 ; ffarith       Fast floating point arithmetic (2 cycle)
86 ; float_em      a floating point arithmetic operation that is normally emulated
87 ;               even on a machine with an fpa.
88 ; f_load        a floating point load from memory
89 ; f_store       a floating point store to memory
90 ; f_mem_r       a transfer of a floating point register to a real reg via mem
91 ; r_mem_f       the reverse of f_mem_r
92 ; f_2_r         fast transfer float to arm (no memory needed)
93 ; r_2_f         fast transfer arm to float
94 ; call          a subroutine call
95 ; load          any load from memory
96 ; store1        store 1 word to memory from arm registers
97 ; store2        store 2 words
98 ; store3        store 3 words
99 ; store4        store 4 words
101 (define_attr "type"
102         "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4" 
103         (const_string "normal"))
105 ; Load scheduling, set from the cpu characteristic
106 (define_attr "ldsched" "no,yes"
107   (if_then_else (eq_attr "cpu" "arm8,st_arm")
108                 (const_string "yes")
109                 (const_string "no")))
111 ; condition codes: this one is used by final_prescan_insn to speed up
112 ; conditionalizing instructions.  It saves having to scan the rtl to see if
113 ; it uses or alters the condition codes.
115 ; USE means that the condition codes are used by the insn in the process of
116 ; outputting code, this means (at present) that we can't use the insn in
117 ; inlined branches
119 ; SET means that the purpose of the insn is to set the condition codes in a
120 ; well defined manner.
122 ; CLOB means that the condition codes are altered in an undefined manner, if
123 ; they are altered at all
125 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
126 ; but are if the branch wasn't taken; the effect is to limit the branch
127 ; elimination scanning.
129 ; NOCOND means that the condition codes are neither altered nor affect the
130 ; output of this insn
132 (define_attr "conds" "use,set,clob,jump_clob,nocond"
133         (if_then_else (eq_attr "type" "call")
134          (if_then_else (eq_attr "prog_mode" "prog32")
135           (const_string "clob") (const_string "nocond"))
136          (const_string "nocond")))
138 (define_attr "write_conflict" "no,yes"
139   (if_then_else (eq_attr "type"
140                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
141                 (const_string "yes")
142                 (const_string "no")))
144 (define_attr "core_cycles" "single,multi"
145   (if_then_else (eq_attr "type"
146                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
147                 (const_string "single")
148                 (const_string "multi")))
150 ; The write buffer on some of the arm6 processors is hard to model exactly.
151 ; There is room in the buffer for up to two addresses and up to eight words
152 ; of memory, but the two needn't be split evenly.  When writing the two
153 ; addresses are fully pipelined.  However, a read from memory that is not
154 ; currently in the cache will block until the writes have completed.
155 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
156 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
157 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
158 ; cycle to add as well.
160 ;; (define_function_unit {name} {num-units} {n-users} {test}
161 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
162 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
163                                      (eq_attr "type" "fdivx")) 71 69)
165 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
166                                      (eq_attr "type" "fdivd")) 59 57)
168 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
169                                      (eq_attr "type" "fdivs")) 31 29)
171 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
172                                      (eq_attr "type" "fmul")) 9 7)
174 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
175                                      (eq_attr "type" "ffmul")) 6 4)
177 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
178                                      (eq_attr "type" "farith")) 4 2)
180 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
181                                      (eq_attr "type" "ffarith")) 2 2)
183 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
184                                      (eq_attr "type" "r_2_f")) 5 3)
186 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
187                                      (eq_attr "type" "f_2_r")) 1 2)
189 ;; The fpa10 doesn't really have a memory read unit, but it can start to
190 ;; speculatively execute the instruction in the pipeline, provided the data
191 ;; is already loaded, so pretend reads have a delay of 2 (and that the
192 ;; pipeline is infinite.
194 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
195                                          (eq_attr "type" "f_load")) 3 1)
197 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store1") 5 3)
198 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store2") 7 4)
199 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store3") 9 5)
200 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store4") 11 6)
201 (define_function_unit "write_buf" 1 2 (eq_attr "type" "r_mem_f") 5 3)
203 ;; The write_blockage unit models (partially), the fact that writes will stall
204 ;; until the write buffer empties.
206 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store1") 5 5
207         [(eq_attr "write_conflict" "yes")])
208 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store2") 7 7
209         [(eq_attr "write_conflict" "yes")])
210 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store3") 9 9
211         [(eq_attr "write_conflict" "yes")])
212 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store4") 11 11
213         [(eq_attr "write_conflict" "yes")])
214 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "r_mem_f") 5 5
215         [(eq_attr "write_conflict" "yes")])
216 (define_function_unit "write_blockage" 1 0 
217         (eq_attr "write_conflict" "yes") 1 1)
221 (define_function_unit "core" 1 1 (eq_attr "core_cycles" "single") 1 1)
223 (define_function_unit "core" 1 1 
224   (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 1 1)
226 (define_function_unit "core" 1 1 
227   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load")) 2 2)
229 (define_function_unit "core" 1 1 (eq_attr "type" "mult") 16 16)
231 (define_function_unit "core" 1 1 
232   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
234 (define_function_unit "core" 1 1 
235   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "store1")) 2 2)
237 (define_function_unit "core" 1 1 (eq_attr "type" "store2") 3 3)
239 (define_function_unit "core" 1 1 (eq_attr "type" "store3") 4 4)
241 (define_function_unit "core" 1 1 (eq_attr "type" "store4") 5 5)
243 (define_function_unit "core" 1 1
244   (and (eq_attr "core_cycles" "multi")
245        (eq_attr "type" "!mult,load,store2,store3,store4")) 32 32)
247 (define_function_unit "loader" 1 0 
248   (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
251 ;; Note: For DImode insns, there is normally no reason why operands should
252 ;; not be in the same register, what we don't want is for something being
253 ;; written to partially overlap something that is an input.
255 ;; Addition insns.
257 (define_insn "adddi3"
258   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
259         (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
260                  (match_operand:DI 2 "s_register_operand" "r,0")))
261    (clobber (reg:CC 24))]
262   ""
263   "adds\\t%Q0, %Q1, %Q2\;adc\\t%R0, %R1, %R2"
264 [(set_attr "conds" "clob")
265  (set_attr "length" "8")])
267 (define_insn "*adddi_sesidi_di"
268   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
269         (plus:DI (sign_extend:DI
270                   (match_operand:SI 2 "s_register_operand" "r,r"))
271                  (match_operand:DI 1 "s_register_operand" "r,0")))
272    (clobber (reg:CC 24))]
273   ""
274   "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, %2, asr #31"
275 [(set_attr "conds" "clob")
276  (set_attr "length" "8")])
278 (define_insn "*adddi_zesidi_di"
279   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
280         (plus:DI (zero_extend:DI
281                   (match_operand:SI 2 "s_register_operand" "r,r"))
282                  (match_operand:DI 1 "s_register_operand" "r,0")))
283    (clobber (reg:CC 24))]
284   ""
285   "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, #0"
286 [(set_attr "conds" "clob")
287  (set_attr "length" "8")])
289 (define_expand "addsi3"
290   [(set (match_operand:SI 0 "s_register_operand" "")
291         (plus:SI (match_operand:SI 1 "s_register_operand" "")
292                  (match_operand:SI 2 "reg_or_int_operand" "")))]
293   ""
294   "
295   if (GET_CODE (operands[2]) == CONST_INT)
296     {
297       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
298                           operands[1],
299                           (reload_in_progress || reload_completed ? 0
300                            : preserve_subexpressions_p ()));
301       DONE;
302     }
305 (define_split
306   [(set (match_operand:SI 0 "s_register_operand" "")
307         (plus:SI (match_operand:SI 1 "s_register_operand" "")
308                  (match_operand:SI 2 "const_int_operand" "")))]
309   "! (const_ok_for_arm (INTVAL (operands[2]))
310       || const_ok_for_arm (-INTVAL (operands[2])))"
311   [(clobber (const_int 0))]
312   "
313   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
314                       operands[1], 0);
315   DONE;
318 (define_insn "*addsi3_insn"
319   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
320         (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
321                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
322   ""
323   "@
324    add%?\\t%0, %1, %2
325    sub%?\\t%0, %1, #%n2
326    #"
327 [(set_attr "length" "4,4,16")])
329 (define_insn "*addsi3_compare0"
330   [(set (reg:CC_NOOV 24)
331         (compare:CC_NOOV
332          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
333                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
334          (const_int 0)))
335    (set (match_operand:SI 0 "s_register_operand" "=r,r")
336         (plus:SI (match_dup 1) (match_dup 2)))]
337   ""
338   "@
339    add%?s\\t%0, %1, %2
340    sub%?s\\t%0, %1, #%n2"
341 [(set_attr "conds" "set")])
343 (define_insn "*addsi3_compare0_scratch"
344   [(set (reg:CC_NOOV 24)
345         (compare:CC_NOOV
346          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
347                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
348          (const_int 0)))]
349   ""
350   "@
351    cmn%?\\t%0, %1
352    cmp%?\\t%0, #%n1"
353 [(set_attr "conds" "set")])
355 ;; The next four insns work because they compare the result with one of
356 ;; the operands, and we know that the use of the condition code is
357 ;; either GEU or LTU, so we can use the carry flag from the addition
358 ;; instead of doing the compare a second time.
359 (define_insn "*addsi3_compare_op1"
360   [(set (reg:CC_C 24)
361         (compare:CC_C
362          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
363                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
364          (match_dup 1)))
365    (set (match_operand:SI 0 "s_register_operand" "=r,r")
366         (plus:SI (match_dup 1) (match_dup 2)))]
367   ""
368   "@
369    add%?s\\t%0, %1, %2
370    sub%?s\\t%0, %1, #%n2"
371 [(set_attr "conds" "set")])
373 (define_insn "*addsi3_compare_op2"
374   [(set (reg:CC_C 24)
375         (compare:CC_C
376          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
377                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
378          (match_dup 2)))
379    (set (match_operand:SI 0 "s_register_operand" "=r,r")
380         (plus:SI (match_dup 1) (match_dup 2)))]
381   ""
382   "@
383    add%?s\\t%0, %1, %2
384    sub%?s\\t%0, %1, #%n2"
385 [(set_attr "conds" "set")])
387 (define_insn "*compare_addsi2_op0"
388   [(set (reg:CC_C 24)
389         (compare:CC_C
390          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
391                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
392          (match_dup 0)))]
393   ""
394   "@
395    cmn%?\\t%0, %1
396    cmp%?\\t%0, #%n1"
397 [(set_attr "conds" "set")])
399 (define_insn "*compare_addsi2_op1"
400   [(set (reg:CC_C 24)
401         (compare:CC_C
402          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
403                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
404          (match_dup 1)))]
405   ""
406   "@
407    cmn%?\\t%0, %1
408    cmp%?\\t%0, #%n1"
409 [(set_attr "conds" "set")])
411 (define_insn "*addsi3_carryin"
412   [(set (match_operand:SI 0 "s_register_operand" "=r")
413         (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
414                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
415                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
416   ""
417   "adc%?\\t%0, %1, %2"
418 [(set_attr "conds" "use")])
420 (define_insn "*addsi3_carryin_alt1"
421   [(set (match_operand:SI 0 "s_register_operand" "=r")
422         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
423                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
424                  (ltu:SI (reg:CC_C 24) (const_int 0))))]
425   ""
426   "adc%?\\t%0, %1, %2"
427 [(set_attr "conds" "use")])
429 (define_insn "*addsi3_carryin_alt2"
430   [(set (match_operand:SI 0 "s_register_operand" "=r")
431         (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
432                           (match_operand:SI 1 "s_register_operand" "r"))
433                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
434   ""
435   "adc%?\\t%0, %1, %2"
436 [(set_attr "conds" "use")])
438 (define_insn "*addsi3_carryin_alt3"
439   [(set (match_operand:SI 0 "s_register_operand" "=r")
440         (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
441                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
442                  (match_operand:SI 1 "s_register_operand" "r")))]
443   ""
444   "adc%?\\t%0, %1, %2"
445 [(set_attr "conds" "use")])
447 (define_insn "incscc"
448   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
449         (plus:SI (match_operator:SI 2 "comparison_operator"
450                     [(match_operand 3 "cc_register" "") (const_int 0)])
451                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
452   ""
453   "@
454   add%d2\\t%0, %1, #1
455   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
456 [(set_attr "conds" "use")
457  (set_attr "length" "4,8")])
459 ; If a constant is too big to fit in a single instruction then the constant
460 ; will be pre-loaded into a register taking at least two insns, we might be
461 ; able to merge it with an add, but it depends on the exact value.
463 (define_split
464   [(set (match_operand:SI 0 "s_register_operand" "=r")
465         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
466                  (match_operand:SI 2 "const_int_operand" "n")))]
467   "!(const_ok_for_arm (INTVAL (operands[2]))
468      || const_ok_for_arm (-INTVAL (operands[2])))"
469   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
470    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
471   "
473   unsigned int val = (unsigned) INTVAL (operands[2]);
474   int i;
475   unsigned int temp;
477   /* this code is similar to the approach followed in movsi, but it must
478      generate exactly two insns */
480   for (i = 30; i >= 0; i -= 2)
481     {
482       if (val & (3 << i))
483         {
484           i -= 6;
485           if (i < 0) i = 0;
486           if (const_ok_for_arm (temp = (val & ~(255 << i))))
487             {
488               val &= 255 << i;
489               break;
490             }
491           /* we might be able to do this as (larger number - small number) */
492           temp = ((val >> i) & 255) + 1;
493           if (temp > 255 && i < 24)
494             {
495               i += 2;
496               temp = ((val >> i) & 255) + 1;
497             }
498           if (const_ok_for_arm ((temp << i) - val))
499             {
500               i = temp << i;
501               temp = (unsigned) - (int) (i - val);
502               val = i;
503               break;
504             }
505           FAIL;
506         }
507     }
508   /* if we got here, we have found a way of doing it in two instructions.
509      the two constants are in val and temp */
510   operands[2] = GEN_INT ((int)val);
511   operands[3] = GEN_INT ((int)temp);
515 (define_insn "addsf3"
516   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
517         (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
518                  (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
519   "TARGET_HARD_FLOAT"
520   "@
521    adf%?s\\t%0, %1, %2
522    suf%?s\\t%0, %1, #%N2"
523 [(set_attr "type" "farith")])
525 (define_insn "adddf3"
526   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
527         (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
528                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
529   "TARGET_HARD_FLOAT"
530   "@
531    adf%?d\\t%0, %1, %2
532    suf%?d\\t%0, %1, #%N2"
533 [(set_attr "type" "farith")])
535 (define_insn "*adddf_df_esfdf"
536   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
537         (plus:DF (float_extend:DF
538                   (match_operand:SF 1 "s_register_operand" "f,f"))
539                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
540   "TARGET_HARD_FLOAT"
541   "@
542    adf%?d\\t%0, %1, %2
543    suf%?d\\t%0, %1, #%N2"
544 [(set_attr "type" "farith")])
546 (define_insn "*adddf_df_esfdf"
547   [(set (match_operand:DF 0 "s_register_operand" "=f")
548         (plus:DF (match_operand:DF 1 "s_register_operand" "f")
549                  (float_extend:DF
550                   (match_operand:SF 2 "s_register_operand" "f"))))]
551   "TARGET_HARD_FLOAT"
552   "adf%?d\\t%0, %1, %2"
553 [(set_attr "type" "farith")])
555 (define_insn "*adddf_esfdf_esfdf"
556   [(set (match_operand:DF 0 "s_register_operand" "=f")
557         (plus:DF (float_extend:DF 
558                   (match_operand:SF 1 "s_register_operand" "f"))
559                  (float_extend:DF
560                   (match_operand:SF 2 "s_register_operand" "f"))))]
561   "TARGET_HARD_FLOAT"
562   "adf%?d\\t%0, %1, %2"
563 [(set_attr "type" "farith")])
565 (define_insn "addxf3"
566   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
567         (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
568                  (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
569   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
570   "@
571    adf%?e\\t%0, %1, %2
572    suf%?e\\t%0, %1, #%N2"
573 [(set_attr "type" "farith")])
575 (define_insn "subdi3"
576   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
577         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
578                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
579    (clobber (reg:CC 24))]
580   ""
581   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
582 [(set_attr "conds" "clob")
583  (set_attr "length" "8")])
585 (define_insn "*subdi_di_zesidi"
586   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
587         (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
588                   (zero_extend:DI
589                    (match_operand:SI 2 "s_register_operand" "r,r"))))
590    (clobber (reg:CC 24))]
591   ""
592   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
593 [(set_attr "conds" "clob")
594  (set_attr "length" "8")])
596 (define_insn "*subdi_di_sesidi"
597   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
598         (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
599                   (sign_extend:DI
600                    (match_operand:SI 2 "s_register_operand" "r,r"))))
601    (clobber (reg:CC 24))]
602   ""
603   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
604 [(set_attr "conds" "clob")
605  (set_attr "length" "8")])
607 (define_insn "*subdi_zesidi_di"
608   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
609         (minus:DI (zero_extend:DI
610                    (match_operand:SI 2 "s_register_operand" "r,r"))
611                   (match_operand:DI 1 "s_register_operand" "?r,0")))
612    (clobber (reg:CC 24))]
613   ""
614   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
615 [(set_attr "conds" "clob")
616  (set_attr "length" "8")])
618 (define_insn "*subdi_sesidi_di"
619   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
620         (minus:DI (sign_extend:DI
621                    (match_operand:SI 2 "s_register_operand" "r,r"))
622                   (match_operand:DI 1 "s_register_operand" "?r,0")))
623    (clobber (reg:CC 24))]
624   ""
625   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
626 [(set_attr "conds" "clob")
627  (set_attr "length" "8")])
629 (define_insn "*subdi_zesidi_zesidi"
630   [(set (match_operand:DI 0 "s_register_operand" "=r")
631         (minus:DI (zero_extend:DI
632                    (match_operand:SI 1 "s_register_operand" "r"))
633                   (zero_extend:DI
634                    (match_operand:SI 2 "s_register_operand" "r"))))
635    (clobber (reg:CC 24))]
636   ""
637   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
638 [(set_attr "conds" "clob")
639  (set_attr "length" "8")])
641 (define_expand "subsi3"
642   [(set (match_operand:SI 0 "s_register_operand" "")
643         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
644                   (match_operand:SI 2 "s_register_operand" "")))]
645   ""
646   "
647   if (GET_CODE (operands[1]) == CONST_INT)
648     {
649       arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
650                           operands[2],
651                           (reload_in_progress || reload_completed ? 0
652                            : preserve_subexpressions_p ()));
653       DONE;
654     }
657 (define_insn "*subsi3_insn"
658   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
659         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
660                   (match_operand:SI 2 "s_register_operand" "r,r")))]
661   ""
662   "@
663    rsb%?\\t%0, %2, %1
664    #"
665 [(set_attr "length" "4,16")])
667 (define_split
668   [(set (match_operand:SI 0 "s_register_operand" "")
669         (minus:SI (match_operand:SI 1 "const_int_operand" "")
670                   (match_operand:SI 2 "s_register_operand" "")))]
671   "! const_ok_for_arm (INTVAL (operands[1]))"
672   [(clobber (const_int 0))]
673   "
674   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
675                       operands[2], 0);
676   DONE;
679 (define_insn "*subsi3_compare0"
680   [(set (reg:CC_NOOV 24)
681         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
682                                  (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
683                          (const_int 0)))
684    (set (match_operand:SI 0 "s_register_operand" "=r,r")
685         (minus:SI (match_dup 1) (match_dup 2)))]
686   ""
687   "@
688    sub%?s\\t%0, %1, %2
689    rsb%?s\\t%0, %2, %1"
690 [(set_attr "conds" "set")])
692 (define_insn "decscc"
693   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
694         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
695                   (match_operator:SI 2 "comparison_operator"
696                    [(match_operand 3 "cc_register" "") (const_int 0)])))]
697   ""
698   "@
699   sub%d2\\t%0, %1, #1
700   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
701 [(set_attr "conds" "use")
702  (set_attr "length" "*,8")])
704 (define_insn "subsf3"
705   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
706         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
707                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
708   "TARGET_HARD_FLOAT"
709   "@
710    suf%?s\\t%0, %1, %2
711    rsf%?s\\t%0, %2, %1"
712 [(set_attr "type" "farith")])
714 (define_insn "subdf3"
715   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
716         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
717                   (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
718   "TARGET_HARD_FLOAT"
719   "@
720    suf%?d\\t%0, %1, %2
721    rsf%?d\\t%0, %2, %1"
722 [(set_attr "type" "farith")])
724 (define_insn "*subdf_esfdf_df"
725   [(set (match_operand:DF 0 "s_register_operand" "=f")
726         (minus:DF (float_extend:DF
727                    (match_operand:SF 1 "s_register_operand" "f"))
728                   (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
729   "TARGET_HARD_FLOAT"
730   "suf%?d\\t%0, %1, %2"
731 [(set_attr "type" "farith")])
733 (define_insn "*subdf_df_esfdf"
734   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
735         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
736                   (float_extend:DF
737                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
738   "TARGET_HARD_FLOAT"
739   "@
740    suf%?d\\t%0, %1, %2
741    rsf%?d\\t%0, %2, %1"
742 [(set_attr "type" "farith")])
744 (define_insn "*subdf_esfdf_esfdf"
745   [(set (match_operand:DF 0 "s_register_operand" "=f")
746         (minus:DF (float_extend:DF
747                    (match_operand:SF 1 "s_register_operand" "f"))
748                   (float_extend:DF
749                    (match_operand:SF 2 "s_register_operand" "f"))))]
750   "TARGET_HARD_FLOAT"
751   "suf%?d\\t%0, %1, %2"
752 [(set_attr "type" "farith")])
754 (define_insn "subxf3"
755   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
756         (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
757                   (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
758   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
759   "@
760    suf%?e\\t%0, %1, %2
761    rsf%?e\\t%0, %2, %1"
762 [(set_attr "type" "farith")])
764 ;; Multiplication insns
766 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
767 (define_insn "mulsi3"
768   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
769         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
770                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
771   ""
772   "mul%?\\t%0, %2, %1"
773 [(set_attr "type" "mult")])
775 (define_insn "*mulsi3_compare0"
776   [(set (reg:CC_NOOV 24)
777         (compare:CC_NOOV (mult:SI
778                           (match_operand:SI 2 "s_register_operand" "r,r")
779                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
780                          (const_int 0)))
781    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
782         (mult:SI (match_dup 2) (match_dup 1)))]
783   ""
784   "mul%?s\\t%0, %2, %1"
785 [(set_attr "conds" "set")
786  (set_attr "type" "mult")])
788 (define_insn "*mulsi_compare0_scratch"
789   [(set (reg:CC_NOOV 24)
790         (compare:CC_NOOV (mult:SI
791                           (match_operand:SI 2 "s_register_operand" "r,r")
792                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
793                          (const_int 0)))
794    (clobber (match_scratch:SI 0 "=&r,&r"))]
795   ""
796   "mul%?s\\t%0, %2, %1"
797 [(set_attr "conds" "set")
798  (set_attr "type" "mult")])
800 ;; Unnamed templates to match MLA instruction.
802 (define_insn "*mulsi3addsi"
803   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
804         (plus:SI
805           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
806                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
807           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
808   ""
809   "mla%?\\t%0, %2, %1, %3"
810 [(set_attr "type" "mult")])
812 (define_insn "*mulsi3addsi_compare0"
813   [(set (reg:CC_NOOV 24)
814         (compare:CC_NOOV (plus:SI
815                           (mult:SI
816                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
817                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
818                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
819                          (const_int 0)))
820    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
821         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
822                  (match_dup 3)))]
823   ""
824   "mla%?s\\t%0, %2, %1, %3"
825 [(set_attr "conds" "set")
826  (set_attr "type" "mult")])
828 (define_insn "*mulsi3addsi_compare0_scratch"
829   [(set (reg:CC_NOOV 24)
830         (compare:CC_NOOV (plus:SI
831                           (mult:SI
832                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
833                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
834                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
835                          (const_int 0)))
836    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
837   ""
838   "mla%?s\\t%0, %2, %1, %3"
839 [(set_attr "conds" "set")
840  (set_attr "type" "mult")])
842 (define_insn "mulsidi3"
843   [(set (match_operand:DI 0 "s_register_operand" "=&r")
844       (mult:DI (sign_extend:DI
845                 (match_operand:SI 1 "s_register_operand" "%r"))
846                (sign_extend:DI
847                (match_operand:SI 2 "s_register_operand" "r"))))]
848   "arm_fast_multiply"
849   "smull%?\\t%Q0, %R0, %1, %2"
850 [(set_attr "type" "mult")])
852 (define_insn "umulsidi3"
853   [(set (match_operand:DI 0 "s_register_operand" "=&r")
854       (mult:DI (zero_extend:DI
855                 (match_operand:SI 1 "s_register_operand" "%r"))
856                (zero_extend:DI
857                 (match_operand:SI 2 "s_register_operand" "r"))))]
858   "arm_fast_multiply"
859   "umull%?\\t%Q0, %R0, %1, %2"
860 [(set_attr "type" "mult")])
862 (define_insn "smulsi3_highpart"
863   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
864         (truncate:SI
865          (lshiftrt:DI
866           (mult:DI (sign_extend:DI
867                     (match_operand:SI 1 "s_register_operand" "%r,0"))
868                    (sign_extend:DI
869                     (match_operand:SI 2 "s_register_operand" "r,r")))
870           (const_int 32))))
871    (clobber (match_scratch:SI 3 "=&r,&r"))]
872   "arm_fast_multiply"
873   "smull%?\\t%3, %0, %2, %1"
874 [(set_attr "type" "mult")])
876 (define_insn "umulsi3_highpart"
877   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
878         (truncate:SI
879          (lshiftrt:DI
880           (mult:DI (zero_extend:DI
881                     (match_operand:SI 1 "s_register_operand" "%r,0"))
882                    (zero_extend:DI
883                     (match_operand:SI 2 "s_register_operand" "r,r")))
884           (const_int 32))))
885    (clobber (match_scratch:SI 3 "=&r,&r"))]
886   "arm_fast_multiply"
887   "umull%?\\t%3, %0, %2, %1"
888 [(set_attr "type" "mult")])
890 (define_insn "mulsf3"
891   [(set (match_operand:SF 0 "s_register_operand" "=f")
892         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
893                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
894   "TARGET_HARD_FLOAT"
895   "fml%?s\\t%0, %1, %2"
896 [(set_attr "type" "ffmul")])
898 (define_insn "muldf3"
899   [(set (match_operand:DF 0 "s_register_operand" "=f")
900         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
901                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
902   "TARGET_HARD_FLOAT"
903   "muf%?d\\t%0, %1, %2"
904 [(set_attr "type" "fmul")])
906 (define_insn "*muldf_esfdf_df"
907   [(set (match_operand:DF 0 "s_register_operand" "=f")
908         (mult:DF (float_extend:DF
909                   (match_operand:SF 1 "s_register_operand" "f"))
910                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
911   "TARGET_HARD_FLOAT"
912   "muf%?d\\t%0, %1, %2"
913 [(set_attr "type" "fmul")])
915 (define_insn "*muldf_df_esfdf"
916   [(set (match_operand:DF 0 "s_register_operand" "=f")
917         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
918                  (float_extend:DF
919                   (match_operand:SF 2 "s_register_operand" "f"))))]
920   "TARGET_HARD_FLOAT"
921   "muf%?d\\t%0, %1, %2"
922 [(set_attr "type" "fmul")])
924 (define_insn "*muldf_esfdf_esfdf"
925   [(set (match_operand:DF 0 "s_register_operand" "=f")
926         (mult:DF (float_extend:DF
927                   (match_operand:SF 1 "s_register_operand" "f"))
928                  (float_extend:DF
929                   (match_operand:SF 2 "s_register_operand" "f"))))]
930   "TARGET_HARD_FLOAT"
931   "muf%?d\\t%0, %1, %2"
932 [(set_attr "type" "fmul")])
934 (define_insn "mulxf3"
935   [(set (match_operand:XF 0 "s_register_operand" "=f")
936         (mult:XF (match_operand:XF 1 "s_register_operand" "f")
937                  (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
938   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
939   "muf%?e\\t%0, %1, %2"
940 [(set_attr "type" "fmul")])
942 ;; Division insns
944 (define_insn "divsf3"
945   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
946         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
947                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
948   "TARGET_HARD_FLOAT"
949   "@
950    fdv%?s\\t%0, %1, %2
951    frd%?s\\t%0, %2, %1"
952 [(set_attr "type" "fdivs")])
954 (define_insn "divdf3"
955   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
956         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
957                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
958   "TARGET_HARD_FLOAT"
959   "@
960    dvf%?d\\t%0, %1, %2
961    rdf%?d\\t%0, %2, %1"
962 [(set_attr "type" "fdivd")])
964 (define_insn "*divdf_esfdf_df"
965   [(set (match_operand:DF 0 "s_register_operand" "=f")
966         (div:DF (float_extend:DF
967                  (match_operand:SF 1 "s_register_operand" "f"))
968                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
969   "TARGET_HARD_FLOAT"
970   "dvf%?d\\t%0, %1, %2"
971 [(set_attr "type" "fdivd")])
973 (define_insn "*divdf_df_esfdf"
974   [(set (match_operand:DF 0 "s_register_operand" "=f")
975         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
976                 (float_extend:DF
977                  (match_operand:SF 2 "s_register_operand" "f"))))]
978   "TARGET_HARD_FLOAT"
979   "rdf%?d\\t%0, %2, %1"
980 [(set_attr "type" "fdivd")])
982 (define_insn "*divdf_esfdf_esfdf"
983   [(set (match_operand:DF 0 "s_register_operand" "=f")
984         (div:DF (float_extend:DF
985                  (match_operand:SF 1 "s_register_operand" "f"))
986                 (float_extend:DF
987                  (match_operand:SF 2 "s_register_operand" "f"))))]
988   "TARGET_HARD_FLOAT"
989   "dvf%?d\\t%0, %1, %2"
990 [(set_attr "type" "fdivd")])
992 (define_insn "divxf3"
993   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
994         (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
995                 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
996   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
997   "@
998    dvf%?e\\t%0, %1, %2
999    rdf%?e\\t%0, %2, %1"
1000 [(set_attr "type" "fdivx")])
1002 ;; Modulo insns
1004 (define_insn "modsf3"
1005   [(set (match_operand:SF 0 "s_register_operand" "=f")
1006         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1007                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1008   "TARGET_HARD_FLOAT"
1009   "rmf%?s\\t%0, %1, %2"
1010 [(set_attr "type" "fdivs")])
1012 (define_insn "moddf3"
1013   [(set (match_operand:DF 0 "s_register_operand" "=f")
1014         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1015                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1016   "TARGET_HARD_FLOAT"
1017   "rmf%?d\\t%0, %1, %2"
1018 [(set_attr "type" "fdivd")])
1020 (define_insn "*moddf_esfdf_df"
1021   [(set (match_operand:DF 0 "s_register_operand" "=f")
1022         (mod:DF (float_extend:DF
1023                  (match_operand:SF 1 "s_register_operand" "f"))
1024                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1025   "TARGET_HARD_FLOAT"
1026   "rmf%?d\\t%0, %1, %2"
1027 [(set_attr "type" "fdivd")])
1029 (define_insn "*moddf_df_esfdf"
1030   [(set (match_operand:DF 0 "s_register_operand" "=f")
1031         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1032                 (float_extend:DF
1033                  (match_operand:SF 2 "s_register_operand" "f"))))]
1034   "TARGET_HARD_FLOAT"
1035   "rmf%?d\\t%0, %1, %2"
1036 [(set_attr "type" "fdivd")])
1038 (define_insn "*moddf_esfdf_esfdf"
1039   [(set (match_operand:DF 0 "s_register_operand" "=f")
1040         (mod:DF (float_extend:DF
1041                  (match_operand:SF 1 "s_register_operand" "f"))
1042                 (float_extend:DF
1043                  (match_operand:SF 2 "s_register_operand" "f"))))]
1044   "TARGET_HARD_FLOAT"
1045   "rmf%?d\\t%0, %1, %2"
1046 [(set_attr "type" "fdivd")])
1048 (define_insn "modxf3"
1049   [(set (match_operand:XF 0 "s_register_operand" "=f")
1050         (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1051                 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1052   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1053   "rmf%?e\\t%0, %1, %2"
1054 [(set_attr "type" "fdivx")])
1056 ;; Boolean and,ior,xor insns
1058 (define_insn "anddi3"
1059   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1060         (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1061                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1062   ""
1063   "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2"
1064 [(set_attr "length" "8")])
1066 (define_insn "*anddi_zesidi_di"
1067   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1068         (and:DI (zero_extend:DI
1069                  (match_operand:SI 2 "s_register_operand" "r,r"))
1070                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1071   ""
1072   "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0"
1073 [(set_attr "length" "8")])
1075 (define_insn "*anddi_sesdi_di"
1076   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1077         (and:DI (sign_extend:DI
1078                  (match_operand:SI 2 "s_register_operand" "r,r"))
1079                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1080   ""
1081   "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31"
1082 [(set_attr "length" "8")])
1084 (define_expand "andsi3"
1085   [(set (match_operand:SI 0 "s_register_operand" "")
1086         (and:SI (match_operand:SI 1 "s_register_operand" "")
1087                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1088   ""
1089   "
1090   if (GET_CODE (operands[2]) == CONST_INT)
1091     {
1092       arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1093                           operands[1],
1094                           (reload_in_progress || reload_completed
1095                            ? 0 : preserve_subexpressions_p ()));
1096       DONE;
1097     }
1100 (define_insn "*andsi3_insn"
1101   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1102         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1103                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1104   ""
1105   "@
1106    and%?\\t%0, %1, %2
1107    bic%?\\t%0, %1, #%B2
1108    #"
1109 [(set_attr "length" "4,4,16")])
1111 (define_split
1112   [(set (match_operand:SI 0 "s_register_operand" "")
1113         (and:SI (match_operand:SI 1 "s_register_operand" "")
1114                 (match_operand:SI 2 "const_int_operand" "")))]
1115   "! (const_ok_for_arm (INTVAL (operands[2]))
1116       || const_ok_for_arm (~ INTVAL (operands[2])))"
1117   [(clobber (const_int 0))]
1118   "
1119   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1120                        operands[1], 0);
1121   DONE;
1124 (define_insn "*andsi3_compare0"
1125   [(set (reg:CC_NOOV 24)
1126         (compare:CC_NOOV
1127          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1128                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1129          (const_int 0)))
1130    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1131         (and:SI (match_dup 1) (match_dup 2)))]
1132   ""
1133   "@
1134    and%?s\\t%0, %1, %2
1135    bic%?s\\t%0, %1, #%B2"
1136 [(set_attr "conds" "set")])
1138 (define_insn "*andsi3_compare0_scratch"
1139   [(set (reg:CC_NOOV 24)
1140         (compare:CC_NOOV
1141          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1142                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1143          (const_int 0)))
1144    (clobber (match_scratch:SI 3 "=X,r"))]
1145   ""
1146   "@
1147    tst%?\\t%0, %1
1148    bic%?s\\t%3, %0, #%B1"
1149 [(set_attr "conds" "set")])
1151 (define_insn "*zeroextractsi_compare0_scratch"
1152   [(set (reg:CC_NOOV 24)
1153         (compare:CC_NOOV (zero_extract:SI
1154                           (match_operand:SI 0 "s_register_operand" "r")
1155                           (match_operand 1 "const_int_operand" "n")
1156                           (match_operand 2 "const_int_operand" "n"))
1157                          (const_int 0)))]
1158   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1159    && INTVAL (operands[1]) > 0 
1160    && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1161    && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1162   "*
1164   unsigned int mask = 0;
1165   int cnt = INTVAL (operands[1]);
1166   
1167   while (cnt--)
1168     mask = (mask << 1) | 1;
1169   operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1170   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1171   return \"\";
1174 [(set_attr "conds" "set")])
1176 (define_insn "*zeroextractqi_compare0_scratch"
1177   [(set (reg:CC_NOOV 24)
1178         (compare:CC_NOOV (zero_extract:SI
1179                           (match_operand:QI 0 "memory_operand" "m")
1180                           (match_operand 1 "const_int_operand" "n")
1181                           (match_operand 2 "const_int_operand" "n"))
1182                          (const_int 0)))
1183    (clobber (match_scratch:QI 3 "=r"))]
1184   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 8
1185    && INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8"
1186   "*
1188   unsigned int mask = 0;
1189   int cnt = INTVAL (operands[1]);
1190   
1191   while (cnt--)
1192     mask = (mask << 1) | 1;
1193   operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1194   output_asm_insn (\"ldr%?b\\t%3, %0\", operands);
1195   output_asm_insn (\"tst%?\\t%3, %1\", operands);
1196   return \"\";
1199 [(set_attr "conds" "set")
1200  (set_attr "length" "8")])
1202 (define_expand "insv"
1203   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1204                          (match_operand:SI 1 "general_operand" "")
1205                          (match_operand:SI 2 "general_operand" ""))
1206         (match_operand:SI 3 "nonmemory_operand" ""))]
1207   ""
1208   "
1210   HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << INTVAL (operands[1])) - 1;
1211   rtx target, subtarget;
1213   target = operands[0];
1214   /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1215      subreg as the final target.  */
1216   if (GET_CODE (target) == SUBREG)
1217     {
1218       subtarget = gen_reg_rtx (SImode);
1219       if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1220           < GET_MODE_SIZE (SImode))
1221         target = SUBREG_REG (target);
1222     }
1223   else
1224     subtarget = target;    
1225     
1226   if (GET_CODE (operands[3]) == CONST_INT)
1227     {
1228       /* Since we are inserting a known constant, we may be able to
1229          reduce the number of bits that we have to clear so that
1230          the mask becomes simple.  */
1231       rtx op1 = gen_reg_rtx (SImode);
1232       HOST_WIDE_INT mask2 = ((mask & ~INTVAL (operands[3]))
1233                              << INTVAL (operands[2]));
1235       emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1236       emit_insn (gen_iorsi3 (subtarget, op1,
1237                              GEN_INT (INTVAL (operands[3])
1238                                       << INTVAL (operands[2]))));
1239     }
1240   else if (INTVAL (operands[2]) == 0
1241            && ! (const_ok_for_arm (mask)
1242                  || const_ok_for_arm (~mask)))
1243     {
1244       /* A Trick, since we are setting the bottom bits in the word,
1245          we can shift operand[3] up, operand[0] down, OR them together
1246          and rotate the result back again.  This takes 3 insns, and
1247          the third might be mergable into another op.  */
1249       rtx op0 = gen_reg_rtx (SImode);
1250       rtx op1 = gen_reg_rtx (SImode);
1252       emit_insn (gen_ashlsi3 (op0, operands[3],
1253                               GEN_INT (32 - INTVAL (operands[1]))));
1254       emit_insn (gen_iorsi3 (op1, gen_rtx (LSHIFTRT, SImode, operands[0],
1255                                            operands[1]),
1256                              op0));
1257       emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1258     }
1259   else if ((INTVAL (operands[1]) + INTVAL (operands[2]) == 32)
1260            && ! (const_ok_for_arm (mask)
1261                  || const_ok_for_arm (~mask)))
1262     {
1263       /* Similar trick, but slightly less efficient.  */
1265       rtx op0 = gen_reg_rtx (SImode);
1266       rtx op1 = gen_reg_rtx (SImode);
1268       emit_insn (gen_ashlsi3 (op0, operands[3],
1269                               GEN_INT (32 - INTVAL (operands[1]))));
1270       emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1271       emit_insn (gen_iorsi3 (subtarget,
1272                              gen_rtx (LSHIFTRT, SImode, op1,
1273                                       operands[1]), op0));
1274     }
1275   else
1276     {
1277       rtx op0 = GEN_INT (mask);
1278       rtx op1 = gen_reg_rtx (SImode);
1279       rtx op2 = gen_reg_rtx (SImode);
1281       if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1282         {
1283           rtx tmp = gen_reg_rtx (SImode);
1285           emit_insn (gen_movsi (tmp, op0));
1286           op0 = tmp;
1287         }
1289       emit_insn (gen_andsi3 (op1, operands[3], op0));
1291       if (GET_CODE (op0) == CONST_INT
1292           && (const_ok_for_arm (mask << INTVAL (operands[2]))
1293               || const_ok_for_arm (~ (mask << INTVAL (operands[2])))))
1294         {
1295           op0 = GEN_INT (~(mask << INTVAL (operands[2])));
1296           emit_insn (gen_andsi3 (op2, operands[0], op0));
1297         }
1298       else
1299         {
1300           if (GET_CODE (op0) == CONST_INT)
1301             {
1302               rtx tmp = gen_reg_rtx (SImode);
1304               emit_insn (gen_movsi (tmp, op0));
1305               op0 = tmp;
1306             }
1308           if (INTVAL (operands[2]) != 0)
1309             op0 = gen_rtx (ASHIFT, SImode, op0, operands[2]);
1310           emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1311         }
1313       if (INTVAL (operands[2]) != 0)
1314         op1 = gen_rtx (ASHIFT, SImode, op1, operands[2]);
1316       emit_insn (gen_iorsi3 (subtarget, op1, op2));
1317     }
1319   if (subtarget != target)
1320     {
1321       /* If TARGET is still a SUBREG, then it must be wider than a word,
1322          so we must be careful only to set the subword we were asked to. */
1323       if (GET_CODE (target) == SUBREG)
1324         emit_move_insn (target, subtarget);
1325       else
1326         emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1327     }
1329   DONE;
1333 ;; constants for op 2 will never be given to these patterns.
1334 (define_insn "*anddi_notdi_di"
1335   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1336         (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1337                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1338   ""
1339   "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2"
1340 [(set_attr "length" "8")])
1341   
1342 (define_insn "*anddi_notzesidi_di"
1343   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1344         (and:DI (not:DI (zero_extend:DI
1345                          (match_operand:SI 2 "s_register_operand" "r,r")))
1346                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1347   ""
1348   "@
1349    bic%?\\t%Q0, %Q1, %2
1350    bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1351 [(set_attr "length" "4,8")])
1352   
1353 (define_insn "*anddi_notsesidi_di"
1354   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1355         (and:DI (not:DI (sign_extend:DI
1356                          (match_operand:SI 2 "s_register_operand" "r,r")))
1357                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1358   ""
1359   "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
1360 [(set_attr "length" "8")])
1361   
1362 (define_insn "andsi_notsi_si"
1363   [(set (match_operand:SI 0 "s_register_operand" "=r")
1364         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1365                 (match_operand:SI 1 "s_register_operand" "r")))]
1366   ""
1367   "bic%?\\t%0, %1, %2")
1369 (define_insn "andsi_not_shiftsi_si"
1370   [(set (match_operand:SI 0 "s_register_operand" "=r")
1371         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1372                          [(match_operand:SI 2 "s_register_operand" "r")
1373                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1374                 (match_operand:SI 1 "s_register_operand" "r")))]
1375   ""
1376   "bic%?\\t%0, %1, %2%S4")
1378 (define_insn "*andsi_notsi_si_compare0"
1379   [(set (reg:CC_NOOV 24)
1380         (compare:CC_NOOV
1381          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1382                  (match_operand:SI 1 "s_register_operand" "r"))
1383          (const_int 0)))
1384    (set (match_operand:SI 0 "s_register_operand" "=r")
1385         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1386   ""
1387   "bic%?s\\t%0, %1, %2"
1388 [(set_attr "conds" "set")])
1390 (define_insn "*andsi_notsi_si_compare0_scratch"
1391   [(set (reg:CC_NOOV 24)
1392         (compare:CC_NOOV
1393          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1394                  (match_operand:SI 1 "s_register_operand" "r"))
1395          (const_int 0)))
1396    (clobber (match_scratch:SI 0 "=r"))]
1397   ""
1398   "bic%?s\\t%0, %1, %2"
1399 [(set_attr "conds" "set")])
1401 (define_insn "iordi3"
1402   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1403         (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1404                 (match_operand:DI 2 "s_register_operand" "r")))]
1405   ""
1406   "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2"
1407 [(set_attr "length" "8")])
1409 (define_insn "*iordi_zesidi_di"
1410   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1411         (ior:DI (zero_extend:DI
1412                  (match_operand:SI 2 "s_register_operand" "r,r"))
1413                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1414   ""
1415   "@
1416    orr%?\\t%Q0, %Q1, %2
1417    orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1418 [(set_attr "length" "4,8")])
1420 (define_insn "*iordi_sesidi_di"
1421   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1422         (ior:DI (sign_extend:DI
1423                  (match_operand:SI 2 "s_register_operand" "r,r"))
1424                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1425   ""
1426   "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1427 [(set_attr "length" "8")])
1429 (define_expand "iorsi3"
1430   [(set (match_operand:SI 0 "s_register_operand" "")
1431         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1432                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1433   ""
1434   "
1435   if (GET_CODE (operands[2]) == CONST_INT)
1436     {
1437       arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1438                           operands[1],
1439                           (reload_in_progress || reload_completed
1440                            ? 0 : preserve_subexpressions_p ()));
1441       DONE;
1442     }
1445 (define_insn "*iorsi3_insn"
1446   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1447         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1448                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1449   ""
1450   "@
1451    orr%?\\t%0, %1, %2
1452    #"
1453 [(set_attr "length" "4,16")])
1455 (define_split
1456   [(set (match_operand:SI 0 "s_register_operand" "")
1457         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1458                 (match_operand:SI 2 "const_int_operand" "")))]
1459   "! const_ok_for_arm (INTVAL (operands[2]))"
1460   [(clobber (const_int 0))]
1461   "
1462   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1463                       operands[1], 0);
1464   DONE;
1466   
1467 (define_insn "*iorsi3_compare0"
1468   [(set (reg:CC_NOOV 24)
1469         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1470                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1471                          (const_int 0)))
1472    (set (match_operand:SI 0 "s_register_operand" "=r")
1473         (ior:SI (match_dup 1) (match_dup 2)))]
1474   ""
1475   "orr%?s\\t%0, %1, %2"
1476 [(set_attr "conds" "set")])
1478 (define_insn "*iorsi3_compare0_scratch"
1479   [(set (reg:CC_NOOV 24)
1480         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1481                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1482                          (const_int 0)))
1483    (clobber (match_scratch:SI 0 "=r"))]
1484   ""
1485   "orr%?s\\t%0, %1, %2"
1486 [(set_attr "conds" "set")])
1488 (define_insn "xordi3"
1489   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1490         (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1491                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1492   ""
1493   "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2"
1494 [(set_attr "length" "8")])
1496 (define_insn "*xordi_zesidi_di"
1497   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1498         (xor:DI (zero_extend:DI
1499                  (match_operand:SI 2 "s_register_operand" "r,r"))
1500                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1501   ""
1502   "@
1503    eor%?\\t%Q0, %Q1, %2
1504    eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1505 [(set_attr "length" "4,8")])
1507 (define_insn "*xordi_sesidi_di"
1508   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1509         (xor:DI (sign_extend:DI
1510                  (match_operand:SI 2 "s_register_operand" "r,r"))
1511                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1512   ""
1513   "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1514 [(set_attr "length" "8")])
1516 (define_insn "xorsi3"
1517   [(set (match_operand:SI 0 "s_register_operand" "=r")
1518         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1519                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1520   ""
1521   "eor%?\\t%0, %1, %2")
1523 (define_insn "*xorsi3_compare0"
1524   [(set (reg:CC_NOOV 24)
1525         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1526                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1527                          (const_int 0)))
1528    (set (match_operand:SI 0 "s_register_operand" "=r")
1529         (xor:SI (match_dup 1) (match_dup 2)))]
1530   ""
1531   "eor%?s\\t%0, %1, %2"
1532 [(set_attr "conds" "set")])
1534 (define_insn "*xorsi3_compare0_scratch"
1535   [(set (reg:CC_NOOV 24)
1536         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1537                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
1538                          (const_int 0)))]
1539   ""
1540   "teq%?\\t%0, %1"
1541 [(set_attr "conds" "set")])
1543 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
1544 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1545 ;; insns
1547 (define_split
1548   [(set (match_operand:SI 0 "s_register_operand" "=r")
1549         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1550                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1551                 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1552    (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1553   ""
1554   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1555                               (not:SI (match_dup 3))))
1556    (set (match_dup 0) (not:SI (match_dup 4)))]
1557   ""
1560 (define_insn "*andsi_iorsi3_notsi"
1561   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1562         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1563                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1564                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1565   ""
1566   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1567 [(set_attr "length" "8")])
1571 ;; Minimum and maximum insns
1573 (define_insn "smaxsi3"
1574   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1575         (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1576                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1577    (clobber (reg:CC 24))]
1578   ""
1579   "@
1580    cmp\\t%1, %2\;movlt\\t%0, %2
1581    cmp\\t%1, %2\;movge\\t%0, %1
1582    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1583 [(set_attr "conds" "clob")
1584  (set_attr "length" "8,8,12")])
1586 (define_insn "sminsi3"
1587   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1588         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1589                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1590    (clobber (reg:CC 24))]
1591   ""
1592   "@
1593    cmp\\t%1, %2\;movge\\t%0, %2
1594    cmp\\t%1, %2\;movlt\\t%0, %1
1595    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1596 [(set_attr "conds" "clob")
1597  (set_attr "length" "8,8,12")])
1599 (define_insn "umaxsi3"
1600   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1601         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1602                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1603    (clobber (reg:CC 24))]
1604   ""
1605   "@
1606    cmp\\t%1, %2\;movcc\\t%0, %2
1607    cmp\\t%1, %2\;movcs\\t%0, %1
1608    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1609 [(set_attr "conds" "clob")
1610  (set_attr "length" "8,8,12")])
1612 (define_insn "uminsi3"
1613   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1614         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1615                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1616    (clobber (reg:CC 24))]
1617   ""
1618   "@
1619    cmp\\t%1, %2\;movcs\\t%0, %2
1620    cmp\\t%1, %2\;movcc\\t%0, %1
1621    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1622 [(set_attr "conds" "clob")
1623  (set_attr "length" "8,8,12")])
1625 (define_insn "*store_minmaxsi"
1626   [(set (match_operand:SI 0 "memory_operand" "=m")
1627         (match_operator:SI 3 "minmax_operator"
1628          [(match_operand:SI 1 "s_register_operand" "r")
1629           (match_operand:SI 2 "s_register_operand" "r")]))
1630    (clobber (reg:CC 24))]
1631   ""
1632   "*
1633   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1634                          operands[2]);
1635   output_asm_insn (\"cmp\\t%1, %2\", operands);
1636   output_asm_insn (\"str%d3\\t%1, %0\", operands);
1637   output_asm_insn (\"str%D3\\t%2, %0\", operands);
1638   return \"\";
1640 [(set_attr "conds" "clob")
1641  (set_attr "length" "12")
1642  (set_attr "type" "store1")])
1644 ; Reject the frame pointer in operand[1], since reloading this after
1645 ; it has been eliminated can cause carnage.
1646 (define_insn "*minmax_arithsi"
1647   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1648         (match_operator:SI 4 "shiftable_operator"
1649          [(match_operator:SI 5 "minmax_operator"
1650            [(match_operand:SI 2 "s_register_operand" "r,r")
1651             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1652           (match_operand:SI 1 "s_register_operand" "0,?r")]))
1653    (clobber (reg:CC 24))]
1654   "GET_CODE (operands[1]) != REG
1655    || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
1656        && REGNO(operands[1]) != ARG_POINTER_REGNUM)"
1657   "*
1659   enum rtx_code code = GET_CODE (operands[4]);
1661   operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1662                          operands[3]);
1663   output_asm_insn (\"cmp\\t%2, %3\", operands);
1664   output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1665   if (which_alternative != 0 || operands[3] != const0_rtx
1666       || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1667     output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1668   return \"\";
1671 [(set_attr "conds" "clob")
1672  (set_attr "length" "12")])
1675 ;; Shift and rotation insns
1677 (define_expand "ashlsi3"
1678   [(set (match_operand:SI 0 "s_register_operand" "")
1679         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
1680                    (match_operand:SI 2 "arm_rhs_operand" "")))]
1681   ""
1682   "
1683   if (GET_CODE (operands[2]) == CONST_INT
1684       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1685     {
1686       emit_insn (gen_movsi (operands[0], const0_rtx));
1687       DONE;
1688     }
1691 (define_expand "ashrsi3"
1692   [(set (match_operand:SI 0 "s_register_operand" "")
1693         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1694                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1695   ""
1696   "
1697   if (GET_CODE (operands[2]) == CONST_INT
1698       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1699     operands[2] = GEN_INT (31);
1702 (define_expand "lshrsi3"
1703   [(set (match_operand:SI 0 "s_register_operand" "")
1704         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1705                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1706   ""
1707   "
1708   if (GET_CODE (operands[2]) == CONST_INT
1709       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1710     {
1711       emit_insn (gen_movsi (operands[0], const0_rtx));
1712       DONE;
1713     }
1716 (define_expand "rotlsi3"
1717   [(set (match_operand:SI 0 "s_register_operand" "")
1718         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1719                      (match_operand:SI 2 "reg_or_int_operand" "")))]
1720   ""
1721   "
1722   if (GET_CODE (operands[2]) == CONST_INT)
1723     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1724   else
1725     {
1726       rtx reg = gen_reg_rtx (SImode);
1727       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1728       operands[2] = reg;
1729     }
1732 (define_expand "rotrsi3"
1733   [(set (match_operand:SI 0 "s_register_operand" "")
1734         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1735                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1736   ""
1737   "
1738   if (GET_CODE (operands[2]) == CONST_INT
1739       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1740     operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1743 (define_insn "*shiftsi3"
1744   [(set (match_operand:SI 0 "s_register_operand" "=r")
1745         (match_operator:SI 3 "shift_operator"
1746          [(match_operand:SI 1 "s_register_operand" "r")
1747           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1748   ""
1749   "mov%?\\t%0, %1%S3")
1751 (define_insn "*shiftsi3_compare0"
1752   [(set (reg:CC_NOOV 24)
1753         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1754                           [(match_operand:SI 1 "s_register_operand" "r")
1755                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1756                          (const_int 0)))
1757    (set (match_operand:SI 0 "s_register_operand" "=r")
1758         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1759   ""
1760   "mov%?s\\t%0, %1%S3"
1761 [(set_attr "conds" "set")])
1763 (define_insn "*shiftsi3_compare0_scratch"
1764   [(set (reg:CC_NOOV 24)
1765         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1766                           [(match_operand:SI 1 "s_register_operand" "r")
1767                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1768                          (const_int 0)))
1769    (clobber (match_scratch:SI 0 "=r"))]
1770   ""
1771   "mov%?s\\t%0, %1%S3"
1772 [(set_attr "conds" "set")])
1774 (define_insn "*notsi_shiftsi"
1775   [(set (match_operand:SI 0 "s_register_operand" "=r")
1776         (not:SI (match_operator:SI 3 "shift_operator"
1777                  [(match_operand:SI 1 "s_register_operand" "r")
1778                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1779   ""
1780   "mvn%?\\t%0, %1%S3")
1782 (define_insn "*notsi_shiftsi_compare0"
1783   [(set (reg:CC_NOOV 24)
1784         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1785                           [(match_operand:SI 1 "s_register_operand" "r")
1786                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1787                          (const_int 0)))
1788    (set (match_operand:SI 0 "s_register_operand" "=r")
1789         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1790   ""
1791   "mvn%?s\\t%0, %1%S3"
1792 [(set_attr "conds" "set")])
1794 (define_insn "*not_shiftsi_compare0_scratch"
1795   [(set (reg:CC_NOOV 24)
1796         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1797                           [(match_operand:SI 1 "s_register_operand" "r")
1798                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1799                          (const_int 0)))
1800    (clobber (match_scratch:SI 0 "=r"))]
1801   ""
1802   "mvn%?s\\t%0, %1%S3"
1803 [(set_attr "conds" "set")])
1806 ;; Unary arithmetic insns
1808 (define_insn "negdi2"
1809   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1810         (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1811   ""
1812   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
1813 [(set_attr "conds" "clob")
1814  (set_attr "length" "8")])
1816 (define_insn "negsi2"
1817   [(set (match_operand:SI 0 "s_register_operand" "=r")
1818         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1819   ""
1820   "rsb%?\\t%0, %1, #0")
1822 (define_insn "negsf2"
1823   [(set (match_operand:SF 0 "s_register_operand" "=f")
1824         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1825   "TARGET_HARD_FLOAT"
1826   "mnf%?s\\t%0, %1"
1827 [(set_attr "type" "ffarith")])
1829 (define_insn "negdf2"
1830   [(set (match_operand:DF 0 "s_register_operand" "=f")
1831         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1832   "TARGET_HARD_FLOAT"
1833   "mnf%?d\\t%0, %1"
1834 [(set_attr "type" "ffarith")])
1836 (define_insn "*negdf_esfdf"
1837   [(set (match_operand:DF 0 "s_register_operand" "=f")
1838         (neg:DF (float_extend:DF
1839                  (match_operand:SF 1 "s_register_operand" "f"))))]
1840   "TARGET_HARD_FLOAT"
1841   "mnf%?d\\t%0, %1"
1842 [(set_attr "type" "ffarith")])
1844 (define_insn "negxf2"
1845   [(set (match_operand:XF 0 "s_register_operand" "=f")
1846         (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1847   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1848   "mnf%?e\\t%0, %1"
1849 [(set_attr "type" "ffarith")])
1851 ;; abssi2 doesn't really clobber the condition codes if a different register
1852 ;; is being set.  To keep things simple, assume during rtl manipulations that
1853 ;; it does, but tell the final scan operator the truth.  Similarly for
1854 ;; (neg (abs...))
1856 (define_insn "abssi2"
1857   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1858         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1859    (clobber (reg 24))]
1860   ""
1861   "@
1862    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1863    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1864 [(set_attr "conds" "clob,*")
1865  (set_attr "length" "8")])
1867 (define_insn "*neg_abssi2"
1868   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1869         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1870    (clobber (reg 24))]
1871   ""
1872   "@
1873    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1874    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1875 [(set_attr "conds" "clob,*")
1876  (set_attr "length" "8")])
1878 (define_insn "abssf2"
1879   [(set (match_operand:SF 0 "s_register_operand" "=f")
1880          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1881   "TARGET_HARD_FLOAT"
1882   "abs%?s\\t%0, %1"
1883 [(set_attr "type" "ffarith")])
1885 (define_insn "absdf2"
1886   [(set (match_operand:DF 0 "s_register_operand" "=f")
1887         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1888   "TARGET_HARD_FLOAT"
1889   "abs%?d\\t%0, %1"
1890 [(set_attr "type" "ffarith")])
1892 (define_insn "*absdf_esfdf"
1893   [(set (match_operand:DF 0 "s_register_operand" "=f")
1894         (abs:DF (float_extend:DF
1895                  (match_operand:SF 1 "s_register_operand" "f"))))]
1896   "TARGET_HARD_FLOAT"
1897   "abs%?d\\t%0, %1"
1898 [(set_attr "type" "ffarith")])
1900 (define_insn "absxf2"
1901   [(set (match_operand:XF 0 "s_register_operand" "=f")
1902         (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1903   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1904   "abs%?e\\t%0, %1"
1905 [(set_attr "type" "ffarith")])
1907 (define_insn "sqrtsf2"
1908   [(set (match_operand:SF 0 "s_register_operand" "=f")
1909         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1910   "TARGET_HARD_FLOAT"
1911   "sqt%?s\\t%0, %1"
1912 [(set_attr "type" "float_em")])
1914 (define_insn "sqrtdf2"
1915   [(set (match_operand:DF 0 "s_register_operand" "=f")
1916         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1917   "TARGET_HARD_FLOAT"
1918   "sqt%?d\\t%0, %1"
1919 [(set_attr "type" "float_em")])
1921 (define_insn "*sqrtdf_esfdf"
1922   [(set (match_operand:DF 0 "s_register_operand" "=f")
1923         (sqrt:DF (float_extend:DF
1924                   (match_operand:SF 1 "s_register_operand" "f"))))]
1925   "TARGET_HARD_FLOAT"
1926   "sqt%?d\\t%0, %1"
1927 [(set_attr "type" "float_em")])
1929 (define_insn "sqrtxf2"
1930   [(set (match_operand:XF 0 "s_register_operand" "=f")
1931         (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1932   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1933   "sqt%?e\\t%0, %1"
1934 [(set_attr "type" "float_em")])
1936 ;; SIN COS TAN and family are always emulated, so it's probably better
1937 ;; to always call a library function.
1938 ;(define_insn "sinsf2"
1939 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
1940 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1941 ;  "TARGET_HARD_FLOAT"
1942 ;  "sin%?s\\t%0, %1"
1943 ;[(set_attr "type" "float_em")])
1945 ;(define_insn "sindf2"
1946 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1947 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1948 ;  "TARGET_HARD_FLOAT"
1949 ;  "sin%?d\\t%0, %1"
1950 ;[(set_attr "type" "float_em")])
1952 ;(define_insn "*sindf_esfdf"
1953 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1954 ;       (unspec:DF [(float_extend:DF
1955 ;                    (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1956 ;  "TARGET_HARD_FLOAT"
1957 ;  "sin%?d\\t%0, %1"
1958 ;[(set_attr "type" "float_em")])
1960 ;(define_insn "sinxf2"
1961 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
1962 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1963 ;  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1964 ;  "sin%?e\\t%0, %1"
1965 ;[(set_attr "type" "float_em")])
1967 ;(define_insn "cossf2"
1968 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
1969 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
1970 ;  "TARGET_HARD_FLOAT"
1971 ;  "cos%?s\\t%0, %1"
1972 ;[(set_attr "type" "float_em")])
1974 ;(define_insn "cosdf2"
1975 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1976 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
1977 ;  "TARGET_HARD_FLOAT"
1978 ;  "cos%?d\\t%0, %1"
1979 ;[(set_attr "type" "float_em")])
1981 ;(define_insn "*cosdf_esfdf"
1982 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1983 ;       (unspec:DF [(float_extend:DF
1984 ;                    (match_operand:SF 1 "s_register_operand" "f"))] 1))]
1985 ;  "TARGET_HARD_FLOAT"
1986 ;  "cos%?d\\t%0, %1"
1987 ;[(set_attr "type" "float_em")])
1989 ;(define_insn "cosxf2"
1990 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
1991 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
1992 ;  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1993 ;  "cos%?e\\t%0, %1"
1994 ;[(set_attr "type" "float_em")])
1996 (define_insn "one_cmpldi2"
1997   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1998         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1999   ""
2000   "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1"
2001 [(set_attr "length" "8")])
2003 (define_insn "one_cmplsi2"
2004   [(set (match_operand:SI 0 "s_register_operand" "=r")
2005         (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2006   ""
2007   "mvn%?\\t%0, %1")
2009 (define_insn "*notsi_compare0"
2010   [(set (reg:CC_NOOV 24)
2011         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2012                          (const_int 0)))
2013    (set (match_operand:SI 0 "s_register_operand" "=r")
2014         (not:SI (match_dup 1)))]
2015   ""
2016   "mvn%?s\\t%0, %1"
2017 [(set_attr "conds" "set")])
2019 (define_insn "*notsi_compare0_scratch"
2020   [(set (reg:CC_NOOV 24)
2021         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2022                          (const_int 0)))
2023    (clobber (match_scratch:SI 0 "=r"))]
2024   ""
2025   "mvn%?s\\t%0, %1"
2026 [(set_attr "conds" "set")])
2028 ;; Fixed <--> Floating conversion insns
2030 (define_insn "floatsisf2"
2031   [(set (match_operand:SF 0 "s_register_operand" "=f")
2032         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2033   "TARGET_HARD_FLOAT"
2034   "flt%?s\\t%0, %1"
2035 [(set_attr "type" "r_2_f")])
2037 (define_insn "floatsidf2"
2038   [(set (match_operand:DF 0 "s_register_operand" "=f")
2039         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2040   "TARGET_HARD_FLOAT"
2041   "flt%?d\\t%0, %1"
2042 [(set_attr "type" "r_2_f")])
2044 (define_insn "floatsixf2"
2045   [(set (match_operand:XF 0 "s_register_operand" "=f")
2046         (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
2047   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2048   "flt%?e\\t%0, %1"
2049 [(set_attr "type" "r_2_f")])
2051 (define_insn "fix_truncsfsi2"
2052   [(set (match_operand:SI 0 "s_register_operand" "=r")
2053         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2054   "TARGET_HARD_FLOAT"
2055   "fix%?z\\t%0, %1"
2056 [(set_attr "type" "f_2_r")])
2058 (define_insn "fix_truncdfsi2"
2059   [(set (match_operand:SI 0 "s_register_operand" "=r")
2060         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2061   "TARGET_HARD_FLOAT"
2062   "fix%?z\\t%0, %1"
2063 [(set_attr "type" "f_2_r")])
2065 (define_insn "fix_truncxfsi2"
2066   [(set (match_operand:SI 0 "s_register_operand" "=r")
2067         (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
2068   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2069   "fix%?z\\t%0, %1"
2070 [(set_attr "type" "f_2_r")])
2072 ;; Truncation insns
2074 (define_insn "truncdfsf2"
2075   [(set (match_operand:SF 0 "s_register_operand" "=f")
2076         (float_truncate:SF
2077          (match_operand:DF 1 "s_register_operand" "f")))]
2078   "TARGET_HARD_FLOAT"
2079   "mvf%?s\\t%0, %1"
2080 [(set_attr "type" "ffarith")])
2082 (define_insn "truncxfsf2"
2083   [(set (match_operand:SF 0 "s_register_operand" "=f")
2084         (float_truncate:SF
2085          (match_operand:XF 1 "s_register_operand" "f")))]
2086   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2087   "mvf%?s\\t%0, %1"
2088 [(set_attr "type" "ffarith")])
2090 (define_insn "truncxfdf2"
2091   [(set (match_operand:DF 0 "s_register_operand" "=f")
2092         (float_truncate:DF
2093          (match_operand:XF 1 "s_register_operand" "f")))]
2094   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2095   "mvf%?d\\t%0, %1"
2096 [(set_attr "type" "ffarith")])
2098 ;; Zero and sign extension instructions.
2100 (define_insn "zero_extendsidi2"
2101   [(set (match_operand:DI 0 "s_register_operand" "=r")
2102         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2103   ""
2104   "*
2105   if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2106     output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2107   return \"mov%?\\t%R0, #0\";
2109 [(set_attr "length" "8")])
2111 (define_insn "zero_extendqidi2"
2112   [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2113         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2114   ""
2115   "@
2116    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2117    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2118 [(set_attr "length" "8")
2119  (set_attr "type" "*,load")])
2121 (define_insn "extendsidi2"
2122   [(set (match_operand:DI 0 "s_register_operand" "=r")
2123         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2124   ""
2125   "*
2126   if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2127     output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2128   return \"mov%?\\t%R0, %Q0, asr #31\";
2130 [(set_attr "length" "8")])
2132 (define_expand "zero_extendhisi2"
2133   [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2134                                  (const_int 16)))
2135    (set (match_operand:SI 0 "s_register_operand" "")
2136         (lshiftrt:SI (match_dup 2) (const_int 16)))]
2137   ""
2138   "
2140   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2141     {
2142       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2143                           gen_rtx (ZERO_EXTEND, SImode, operands[1])));
2144       DONE;
2145     }
2146   if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2147     {
2148       emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2149       DONE;
2150     }
2151   if (! s_register_operand (operands[1], HImode))
2152     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2153   operands[1] = gen_lowpart (SImode, operands[1]);
2154   operands[2] = gen_reg_rtx (SImode); 
2157 (define_insn "*zero_extendhisi_insn"
2158   [(set (match_operand:SI 0 "s_register_operand" "=r")
2159         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2160   "arm_arch4"
2161   "ldr%?h\\t%0, %1"
2162 [(set_attr "type" "load")])
2164 (define_split
2165   [(set (match_operand:SI 0 "s_register_operand" "")
2166         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2167    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2168   "! arm_arch4"
2169   [(set (match_dup 2) (match_dup 1))
2170    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2171   "
2173   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2174     FAIL;
2177 (define_split
2178   [(set (match_operand:SI 0 "s_register_operand" "")
2179         (match_operator:SI 3 "shiftable_operator"
2180          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2181           (match_operand:SI 4 "s_register_operand" "")]))
2182    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2183   "! arm_arch4"
2184   [(set (match_dup 2) (match_dup 1))
2185    (set (match_dup 0)
2186         (match_op_dup 3
2187          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2188   "
2190   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2191     FAIL;
2194 (define_expand "zero_extendqisi2"
2195   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2196         (zero_extend:SI
2197          (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2198   ""
2199   "
2200   if (GET_CODE (operands[1]) != MEM)
2201     {
2202       emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
2203                              GEN_INT (255)));
2204       DONE;
2205     }
2208 (define_insn "*load_extendqisi"
2209   [(set (match_operand:SI 0 "s_register_operand" "=r")
2210         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2211   ""
2212   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
2213 [(set_attr "type" "load")])
2215 (define_split
2216   [(set (match_operand:SI 0 "s_register_operand" "")
2217         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
2218    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2219   "GET_CODE (operands[1]) != MEM"
2220   [(set (match_dup 2) (match_dup 1))
2221    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
2222   "")
2224 (define_insn "*compareqi_eq0"
2225   [(set (reg:CC_Z 24)
2226         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
2227                          (const_int 0)))]
2228   ""
2229   "tst\\t%0, #255"
2230 [(set_attr "conds" "set")])
2232 (define_expand "extendhisi2"
2233   [(set (match_dup 2)
2234         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2235                    (const_int 16)))
2236    (set (match_operand:SI 0 "s_register_operand" "")
2237         (ashiftrt:SI (match_dup 2)
2238                      (const_int 16)))]
2239   ""
2240   "
2242   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2243     {
2244       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2245                  gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2246       DONE;
2247     }
2249   if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2250     {
2251       emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
2252       DONE;
2253     }
2254   if (! s_register_operand (operands[1], HImode))
2255     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2256   operands[1] = gen_lowpart (SImode, operands[1]);
2257   operands[2] = gen_reg_rtx (SImode);
2260 (define_expand "extendhisi2_mem"
2261   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
2262    (set (match_dup 3)
2263         (zero_extend:SI (match_dup 7)))
2264    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
2265    (set (match_operand:SI 0 "" "")
2266         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
2267   ""
2268   "
2270   rtx mem1, mem2;
2271   rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2273   mem1 = gen_rtx (MEM, QImode, addr);
2274   MEM_VOLATILE_P (mem1) = MEM_VOLATILE_P (operands[1]);
2275   MEM_IN_STRUCT_P (mem1) = MEM_IN_STRUCT_P (operands[1]);
2276   RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
2277   mem2 = gen_rtx (MEM, QImode, plus_constant (addr, 1));
2278   MEM_VOLATILE_P (mem2) = MEM_VOLATILE_P (operands[1]);
2279   MEM_IN_STRUCT_P (mem2) = MEM_IN_STRUCT_P (operands[1]);
2280   RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
2281   operands[0] = gen_lowpart (SImode, operands[0]);
2282   operands[1] = mem1;
2283   operands[2] = gen_reg_rtx (SImode);
2284   operands[3] = gen_reg_rtx (SImode);
2285   operands[6] = gen_reg_rtx (SImode);
2286   operands[7] = mem2;
2288   if (BYTES_BIG_ENDIAN)
2289     {
2290       operands[4] = operands[2];
2291       operands[5] = operands[3];
2292     }
2293   else
2294     {
2295       operands[4] = operands[3];
2296       operands[5] = operands[2];
2297     }
2301 (define_insn "*extendhisi_insn"
2302   [(set (match_operand:SI 0 "s_register_operand" "=r")
2303         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2304   "arm_arch4"
2305   "ldr%?sh\\t%0, %1"
2306 [(set_attr "type" "load")])
2308 (define_split
2309   [(set (match_operand:SI 0 "s_register_operand" "")
2310         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2311    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2312   "! arm_arch4"
2313   [(set (match_dup 2) (match_dup 1))
2314    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2315   "
2317   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2318     FAIL;
2321 (define_split
2322   [(set (match_operand:SI 0 "s_register_operand" "")
2323         (match_operator:SI 3 "shiftable_operator"
2324          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2325           (match_operand:SI 4 "s_register_operand" "")]))
2326    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2327   "! arm_arch4"
2328   [(set (match_dup 2) (match_dup 1))
2329    (set (match_dup 0)
2330         (match_op_dup 3
2331          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2332   "
2334   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2335     FAIL;
2338 (define_expand "extendqihi2"
2339   [(set (match_dup 2)
2340         (ashift:SI (match_operand:QI 1 "general_operand" "")
2341                    (const_int 24)))
2342    (set (match_operand:HI 0 "s_register_operand" "")
2343         (ashiftrt:SI (match_dup 2)
2344                      (const_int 24)))]
2345   ""
2346   "
2348   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2349     {
2350       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2351                           gen_rtx (SIGN_EXTEND, HImode, operands[1])));
2352       DONE;
2353     }
2354   if (! s_register_operand (operands[1], QImode))
2355     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2356   operands[0] = gen_lowpart (SImode, operands[0]);
2357   operands[1] = gen_lowpart (SImode, operands[1]);
2358   operands[2] = gen_reg_rtx (SImode);
2361 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2362 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2363 (define_insn "*extendqihi_insn"
2364   [(set (match_operand:HI 0 "s_register_operand" "=r")
2365         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
2366   "arm_arch4"
2367   "*
2368   /* If the address is invalid, this will split the instruction into two. */
2369   if (bad_signed_byte_operand(operands[1], QImode))
2370     return \"#\";
2371   return \"ldr%?sb\\t%0, %1\";
2373 [(set_attr "type" "load")
2374  (set_attr "length" "8")])
2376 (define_split
2377   [(set (match_operand:HI 0 "s_register_operand" "")
2378         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2379   "arm_arch4 && reload_completed"
2380   [(set (match_dup 3) (match_dup 1))
2381    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
2382   "
2383   {
2384     HOST_WIDE_INT offset;
2386     operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]));
2387     operands[2] = gen_rtx (MEM, QImode, operands[3]);
2388     MEM_VOLATILE_P (operands[2]) = MEM_VOLATILE_P (operands[1]);
2389     MEM_IN_STRUCT_P (operands[2]) = MEM_IN_STRUCT_P (operands[1]);
2390     RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2391     operands[1] = XEXP (operands[1], 0);
2392     if (GET_CODE (operands[1]) == PLUS
2393         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2394         && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2395               || const_ok_for_arm (-offset)))
2396       {
2397         HOST_WIDE_INT low = (offset > 0
2398                              ? (offset & 0xff) : -((-offset) & 0xff));
2399         XEXP (operands[2], 0) = plus_constant (operands[3], low);
2400         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2401       }
2402   }
2405 (define_expand "extendqisi2"
2406   [(set (match_dup 2)
2407         (ashift:SI (match_operand:QI 1 "general_operand" "")
2408                    (const_int 24)))
2409    (set (match_operand:SI 0 "s_register_operand" "")
2410         (ashiftrt:SI (match_dup 2)
2411                      (const_int 24)))]
2412   ""
2413   "
2415   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2416     {
2417       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2418                           gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2419       DONE;
2420     }
2421   if (! s_register_operand (operands[1], QImode))
2422     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2423   operands[1] = gen_lowpart (SImode, operands[1]);
2424   operands[2] = gen_reg_rtx (SImode);
2427 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2428 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2429 (define_insn "*extendqisi_insn"
2430   [(set (match_operand:SI 0 "s_register_operand" "=r")
2431         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2432   "arm_arch4"
2433   "*
2434   /* If the address is invalid, this will split the instruction into two. */
2435   if (bad_signed_byte_operand(operands[1], QImode))
2436     return \"#\";
2437   return \"ldr%?sb\\t%0, %1\";
2439 [(set_attr "type" "load")
2440  (set_attr "length" "8")])
2442 (define_split
2443   [(set (match_operand:SI 0 "s_register_operand" "")
2444         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2445   "arm_arch4 && reload_completed"
2446   [(set (match_dup 0) (match_dup 1))
2447    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2448   "
2449   {
2450     HOST_WIDE_INT offset;
2452     operands[2] = gen_rtx (MEM, QImode, operands[0]);
2453     MEM_VOLATILE_P (operands[2]) = MEM_VOLATILE_P (operands[1]);
2454     MEM_IN_STRUCT_P (operands[2]) = MEM_IN_STRUCT_P (operands[1]);
2455     RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2456     operands[1] = XEXP (operands[1], 0);
2457     if (GET_CODE (operands[1]) == PLUS
2458         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2459         && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2460               || const_ok_for_arm (-offset)))
2461       {
2462         HOST_WIDE_INT low = (offset > 0
2463                              ? (offset & 0xff) : -((-offset) & 0xff));
2464         XEXP (operands[2], 0) = plus_constant (operands[0], low);
2465         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2466       }
2467   }
2470 (define_insn "extendsfdf2"
2471   [(set (match_operand:DF 0 "s_register_operand" "=f")
2472         (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2473   "TARGET_HARD_FLOAT"
2474   "mvf%?d\\t%0, %1"
2475 [(set_attr "type" "ffarith")])
2477 (define_insn "extendsfxf2"
2478   [(set (match_operand:XF 0 "s_register_operand" "=f")
2479         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2480   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2481   "mvf%?e\\t%0, %1"
2482 [(set_attr "type" "ffarith")])
2484 (define_insn "extenddfxf2"
2485   [(set (match_operand:XF 0 "s_register_operand" "=f")
2486         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2487   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2488   "mvf%?e\\t%0, %1"
2489 [(set_attr "type" "ffarith")])
2492 ;; Move insns (including loads and stores)
2494 ;; XXX Just some ideas about movti.
2495 ;; I don't think these are a good idea on the arm, there just aren't enough
2496 ;; registers
2497 ;;(define_expand "loadti"
2498 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
2499 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
2500 ;;  "" "")
2502 ;;(define_expand "storeti"
2503 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2504 ;;      (match_operand:TI 1 "s_register_operand" ""))]
2505 ;;  "" "")
2507 ;;(define_expand "movti"
2508 ;;  [(set (match_operand:TI 0 "general_operand" "")
2509 ;;      (match_operand:TI 1 "general_operand" ""))]
2510 ;;  ""
2511 ;;  "
2513 ;;  rtx insn;
2515 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2516 ;;    operands[1] = copy_to_reg (operands[1]);
2517 ;;  if (GET_CODE (operands[0]) == MEM)
2518 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2519 ;;  else if (GET_CODE (operands[1]) == MEM)
2520 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2521 ;;  else
2522 ;;    FAIL;
2524 ;;  emit_insn (insn);
2525 ;;  DONE;
2526 ;;}")
2528 ;; Recognise garbage generated above.
2530 ;;(define_insn ""
2531 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2532 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2533 ;;  ""
2534 ;;  "*
2535 ;;  {
2536 ;;    register mem = (which_alternative < 3);
2537 ;;    register char *template;
2539 ;;    operands[mem] = XEXP (operands[mem], 0);
2540 ;;    switch (which_alternative)
2541 ;;      {
2542 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2543 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
2544 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
2545 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
2546 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
2547 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
2548 ;;      }
2549 ;;    output_asm_insn (template, operands);
2550 ;;    return \"\";
2551 ;;  }")
2554 (define_insn "movdi"
2555   [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2556         (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2557   ""
2558   "*
2559   return (output_move_double (operands));
2561 [(set_attr "length" "8,8,8")
2562  (set_attr "type" "*,load,store2")])
2564 (define_expand "movsi"
2565   [(set (match_operand:SI 0 "general_operand" "")
2566         (match_operand:SI 1 "general_operand" ""))]
2567   ""
2568   "
2569   /* Everything except mem = const or mem = mem can be done easily */
2570   if (GET_CODE (operands[0]) == MEM)
2571     operands[1] = force_reg (SImode, operands[1]);
2572   if (GET_CODE (operands[1]) == CONST_INT
2573       && !(const_ok_for_arm (INTVAL (operands[1]))
2574            || const_ok_for_arm (~INTVAL (operands[1]))))
2575     {
2576       arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2577                           NULL_RTX,
2578                           (reload_in_progress || reload_completed ? 0
2579                            : preserve_subexpressions_p ()));
2580       DONE;
2581     }
2582   if (CONSTANT_P (operands[1]) && flag_pic)
2583     operands[1] = legitimize_pic_address (operands[1], SImode,
2584                                           ((reload_in_progress
2585                                             || reload_completed)
2586                                            ? operands[0] : 0));
2589 (define_insn "*movsi_insn"
2590   [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2591         (match_operand:SI 1 "general_operand"  "rI,K,mi,r"))]
2592   "register_operand (operands[0], SImode)
2593    || register_operand (operands[1], SImode)"
2594   "@
2595    mov%?\\t%0, %1
2596    mvn%?\\t%0, #%B1
2597    ldr%?\\t%0, %1
2598    str%?\\t%1, %0"
2599 [(set_attr "type" "*,*,load,store1")])
2601 (define_split
2602   [(set (match_operand:SI 0 "s_register_operand" "")
2603         (match_operand:SI 1 "const_int_operand" ""))]
2604   "! (const_ok_for_arm (INTVAL (operands[1]))
2605       || const_ok_for_arm (~INTVAL (operands[1])))"
2606   [(clobber (const_int 0))]
2607   "
2608   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2609                       NULL_RTX, 0);
2610   DONE;
2613 (define_expand "movaddr"
2614   [(set (match_operand:SI 0 "s_register_operand" "")
2615         (match_operand:DI 1 "address_operand" ""))]
2616   ""
2617   "")
2619 (define_insn "*movaddr_insn"
2620   [(set (match_operand:SI 0 "s_register_operand" "=r")
2621         (match_operand:DI 1 "address_operand" "p"))]
2622   "reload_completed
2623    && (GET_CODE (operands[1]) == LABEL_REF
2624        || (GET_CODE (operands[1]) == CONST
2625            && GET_CODE (XEXP (operands[1], 0)) == PLUS
2626            && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2627            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2628   "adr%?\\t%0, %a1")
2630 /* When generating pic, we need to load the symbol offset into a register.
2631    So that the optimizer does not confuse this with a normal symbol load
2632    we use an unspec.  The offset will be loaded from a constant pool entry,
2633    since that is the only type of relocation we can use.  */
2635 (define_insn "pic_load_addr"
2636   [(set (match_operand:SI 0 "s_register_operand" "=r")
2637         (unspec:SI [(match_operand 1 "" "")] 3))]
2638   "flag_pic"
2639   "ldr%?\\t%0, %a1"
2640  [(set_attr "type" "load")])
2642 ;; This variant is used for AOF assembly, since it needs to mention the
2643 ;; pic register in the rtl.
2644 (define_expand "pic_load_addr_based"
2645   [(set (match_operand:SI 0 "s_register_operand" "=r")
2646         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
2647   "flag_pic"
2648   "operands[2] = pic_offset_table_rtx;")
2650 (define_insn "*pic_load_addr_based_insn"
2651   [(set (match_operand:SI 0 "s_register_operand" "=r")
2652         (unspec:SI [(match_operand 1 "" "")
2653                     (match_operand 2 "s_register_operand" "r")] 3))]
2654   "flag_pic && operands[2] == pic_offset_table_rtx"
2655   "*
2656 #ifdef AOF_ASSEMBLER
2657   operands[1] = aof_pic_entry (operands[1]);
2658 #endif
2659   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
2660   return \"\";
2661 " [(set_attr "type" "load")])
2663 (define_insn "pic_add_dot_plus_eight"
2664   [(set (pc) (label_ref (match_operand 0 "" "")))
2665    (set (match_operand 1 "register_operand" "+r")
2666         (plus:SI (match_dup 1) (const (plus:SI (pc) (const_int 8)))))]
2667   "flag_pic"
2668   "add%?\\t%1, %|pc, %1")
2670 ;; If copying one reg to another we can set the condition codes according to
2671 ;; its value.  Such a move is common after a return from subroutine and the
2672 ;; result is being tested against zero.
2674 (define_insn "*movsi_compare0"
2675   [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
2676                                 (const_int 0)))
2677    (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2678   ""
2679   "@
2680    cmp%?\\t%0, #0
2681    sub%?s\\t%0, %1, #0"
2682 [(set_attr "conds" "set")])
2684 ;; Subroutine to store a half word from a register into memory.
2685 ;; Operand 0 is the source register (HImode)
2686 ;; Operand 1 is the destination address in a register (SImode)
2688 ;; In both this routine and the next, we must be careful not to spill
2689 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2690 ;; can generate unrecognizable rtl.
2692 (define_expand "storehi"
2693   [;; store the low byte
2694    (set (match_operand 1 "" "") (match_dup 3))
2695    ;; extract the high byte
2696    (set (match_dup 2)
2697         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2698    ;; store the high byte
2699    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
2700   ""
2701   "
2703   rtx addr = XEXP (operands[1], 0);
2704   enum rtx_code code = GET_CODE (addr);
2706   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2707       || code == MINUS)
2708     addr = force_reg (SImode, addr);
2710   operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2711   operands[1] = change_address (operands[1], QImode, NULL_RTX);
2712   operands[3] = gen_lowpart (QImode, operands[0]);
2713   operands[0] = gen_lowpart (SImode, operands[0]);
2714   operands[2] = gen_reg_rtx (SImode); 
2718 (define_expand "storehi_bigend"
2719   [(set (match_dup 4) (match_dup 3))
2720    (set (match_dup 2)
2721         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2722    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
2723   ""
2724   "
2726   rtx addr = XEXP (operands[1], 0);
2727   enum rtx_code code = GET_CODE (addr);
2729   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2730       || code == MINUS)
2731     addr = force_reg (SImode, addr);
2733   operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2734   operands[1] = change_address (operands[1], QImode, NULL_RTX);
2735   operands[3] = gen_lowpart (QImode, operands[0]);
2736   operands[0] = gen_lowpart (SImode, operands[0]);
2737   operands[2] = gen_reg_rtx (SImode);
2741 ;; Subroutine to store a half word integer constant into memory.
2742 (define_expand "storeinthi"
2743   [(set (match_operand 0 "" "")
2744         (subreg:QI (match_operand 1 "" "") 0))
2745    (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
2746   ""
2747   "
2749   HOST_WIDE_INT value = INTVAL (operands[1]);
2750   rtx addr = XEXP (operands[0], 0);
2751   enum rtx_code code = GET_CODE (addr);
2753   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2754       || code == MINUS)
2755     addr = force_reg (SImode, addr);
2757   operands[1] = gen_reg_rtx (SImode);
2758   if (BYTES_BIG_ENDIAN)
2759     {
2760       emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2761       if ((value & 255) == ((value >> 8) & 255))
2762         operands[2] = operands[1];
2763       else
2764         {
2765           operands[2] = gen_reg_rtx (SImode);
2766           emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2767         }
2768     }
2769   else
2770     {
2771       emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2772       if ((value & 255) == ((value >> 8) & 255))
2773         operands[2] = operands[1];
2774       else
2775         {
2776           operands[2] = gen_reg_rtx (SImode);
2777           emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2778         }
2779     }
2781   operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
2782   operands[0] = change_address (operands[0], QImode, NULL_RTX);
2786 (define_expand "storehi_single_op"
2787   [(set (match_operand:HI 0 "memory_operand" "")
2788         (match_operand:HI 1 "general_operand" ""))]
2789   "arm_arch4"
2790   "
2791   if (! s_register_operand (operands[1], HImode))
2792     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2795 (define_expand "movhi"
2796   [(set (match_operand:HI 0 "general_operand" "")
2797         (match_operand:HI 1 "general_operand" ""))]
2798   ""
2799   "
2801   rtx insn;
2803   if (! (reload_in_progress || reload_completed))
2804     {
2805       if (GET_CODE (operands[0]) == MEM)
2806         {
2807           if (arm_arch4)
2808             {
2809               emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2810               DONE;
2811             }
2812           if (GET_CODE (operands[1]) == CONST_INT)
2813             emit_insn (gen_storeinthi (operands[0], operands[1]));
2814           else
2815             {
2816               if (GET_CODE (operands[1]) == MEM)
2817                 operands[1] = force_reg (HImode, operands[1]);
2818               if (BYTES_BIG_ENDIAN)
2819                 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
2820               else
2821                 emit_insn (gen_storehi (operands[1], operands[0]));
2822             }
2823           DONE;
2824         }
2825       /* Sign extend a constant, and keep it in an SImode reg.  */
2826       else if (GET_CODE (operands[1]) == CONST_INT)
2827         {
2828           rtx reg = gen_reg_rtx (SImode);
2829           HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2831           /* If the constant is already valid, leave it alone.  */
2832           if (! const_ok_for_arm (val))
2833             {
2834               /* If setting all the top bits will make the constant 
2835                  loadable in a single instruction, then set them.  
2836                  Otherwise, sign extend the number.  */
2838               if (const_ok_for_arm (~ (val | ~0xffff)))
2839                 val |= ~0xffff;
2840               else if (val & 0x8000)
2841                 val |= ~0xffff;
2842             }
2844           emit_insn (gen_movsi (reg, GEN_INT (val)));
2845           operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
2846         }
2847       else if (! arm_arch4)
2848         {
2849           if (GET_CODE (operands[1]) == MEM)
2850             {
2851               if (TARGET_SHORT_BY_BYTES)
2852                 {
2853                   rtx base;
2854                   rtx offset = const0_rtx;
2855                   rtx reg = gen_reg_rtx (SImode);
2857                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2858                        || (GET_CODE (base) == PLUS
2859                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2860                            && GET_CODE (base = XEXP (base, 0)) == REG))
2861                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2862                     {
2863                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~2;
2864                       rtx new;
2866                       new = gen_rtx (MEM, SImode,
2867                                      plus_constant (base, new_offset));
2868                       MEM_VOLATILE_P (new) = MEM_VOLATILE_P (operands[1]);
2869                       MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (operands[1]);
2870                       RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2871                       emit_insn (gen_movsi (reg, new));
2872                       if (((INTVAL (offset) & 2) != 0)
2873                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
2874                         {
2875                           rtx reg2 = gen_reg_rtx (SImode);
2877                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
2878                           reg = reg2;
2879                         }
2880                     }
2881                   else
2882                     emit_insn (gen_movhi_bytes (reg, operands[1]));
2884                   operands[1] = gen_lowpart (HImode, reg);
2885                 }
2886               else if (BYTES_BIG_ENDIAN)
2887                 {
2888                   rtx base;
2889                   rtx offset = const0_rtx;
2891                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2892                        || (GET_CODE (base) == PLUS
2893                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2894                            && GET_CODE (base = XEXP (base, 0)) == REG))
2895                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2896                     {
2897                       rtx reg = gen_reg_rtx (SImode);
2898                       rtx new;
2900                       if ((INTVAL (offset) & 2) == 2)
2901                         {
2902                           HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
2903                           new = gen_rtx (MEM, SImode,
2904                                          plus_constant (base, new_offset));
2905                           MEM_VOLATILE_P (new) = MEM_VOLATILE_P (operands[1]);
2906                           MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (operands[1]);
2907                           RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2908                           emit_insn (gen_movsi (reg, new));
2909                         }
2910                       else
2911                         {
2912                           new = gen_rtx (MEM, SImode, XEXP (operands[1], 0));
2913                           MEM_VOLATILE_P (new) = MEM_VOLATILE_P (operands[1]);
2914                           MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (operands[1]);
2915                           RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2916                           emit_insn (gen_rotated_loadsi (reg, new));
2917                         }
2919                       operands[1] = gen_lowpart (HImode, reg);
2920                     }
2921                   else
2922                     {
2923                       emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2924                       DONE;
2925                     }
2926                 }
2927             }
2928         }
2929     }
2930   /* Handle loading a large integer during reload */
2931   else if (GET_CODE (operands[1]) == CONST_INT
2932            && ! const_ok_for_arm (INTVAL (operands[1]))
2933            && ! const_ok_for_arm (~INTVAL (operands[1])))
2934     {
2935       /* Writing a constant to memory needs a scratch, which should
2936          be handled with SECONDARY_RELOADs.  */
2937       if (GET_CODE (operands[0]) != REG)
2938         abort ();
2940       operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
2941       emit_insn (gen_movsi (operands[0], operands[1]));
2942       DONE;
2943     }
2947 (define_insn "rotated_loadsi"
2948   [(set (match_operand:SI 0 "s_register_operand" "=r")
2949         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
2950                    (const_int 16)))]
2951   "! TARGET_SHORT_BY_BYTES"
2952   "*
2954   rtx ops[2];
2956   ops[0] = operands[0];
2957   ops[1] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 2));
2958   output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
2959   return \"\";
2961 [(set_attr "type" "load")])
2963 (define_expand "movhi_bytes"
2964   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
2965    (set (match_dup 3)
2966         (zero_extend:SI (match_dup 6)))
2967    (set (match_operand:SI 0 "" "")
2968          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
2969   ""
2970   "
2972   rtx mem1, mem2;
2973   rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2975   mem1 = gen_rtx (MEM, QImode, addr);
2976   MEM_VOLATILE_P (mem1) = MEM_VOLATILE_P (operands[1]);
2977   MEM_IN_STRUCT_P (mem1) = MEM_IN_STRUCT_P (operands[1]);
2978   RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
2979   mem2 = gen_rtx (MEM, QImode, plus_constant (addr, 1));
2980   MEM_VOLATILE_P (mem2) = MEM_VOLATILE_P (operands[1]);
2981   MEM_IN_STRUCT_P (mem2) = MEM_IN_STRUCT_P (operands[1]);
2982   RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
2983   operands[0] = gen_lowpart (SImode, operands[0]);
2984   operands[1] = mem1;
2985   operands[2] = gen_reg_rtx (SImode);
2986   operands[3] = gen_reg_rtx (SImode);
2987   operands[6] = mem2;
2989   if (BYTES_BIG_ENDIAN)
2990     {
2991       operands[4] = operands[2];
2992       operands[5] = operands[3];
2993     }
2994   else
2995     {
2996       operands[4] = operands[3];
2997       operands[5] = operands[2];
2998     }
3002 (define_expand "movhi_bigend"
3003   [(set (match_dup 2)
3004         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
3005                    (const_int 16)))
3006    (set (match_dup 3)
3007         (ashiftrt:SI (match_dup 2) (const_int 16)))
3008    (set (match_operand:HI 0 "s_register_operand" "")
3009         (subreg:HI (match_dup 3) 0))]
3010   ""
3011   "
3012   operands[2] = gen_reg_rtx (SImode);
3013   operands[3] = gen_reg_rtx (SImode);
3016 ;; Pattern to recognise insn generated default case above
3018 (define_insn "*movhi_insn_arch4"
3019   [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
3020         (match_operand:HI 1 "general_operand"  "rI,K,m,r"))]
3021   "arm_arch4
3022    && (GET_CODE (operands[1]) != CONST_INT
3023        || const_ok_for_arm (INTVAL (operands[1]))
3024        || const_ok_for_arm (~INTVAL (operands[1])))"
3025   "@
3026    mov%?\\t%0, %1\\t%@ movhi
3027    mvn%?\\t%0, #%B1\\t%@ movhi
3028    ldr%?h\\t%0, %1\\t%@ movhi
3029    str%?h\\t%1, %0\\t%@ movhi"
3030 [(set_attr "type" "*,*,load,store1")])
3032 (define_insn "*movhi_insn_littleend"
3033   [(set (match_operand:HI 0 "general_operand" "=r,r,r")
3034         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
3035   "! arm_arch4
3036    && ! BYTES_BIG_ENDIAN
3037    && ! TARGET_SHORT_BY_BYTES
3038    && (GET_CODE (operands[1]) != CONST_INT
3039        || const_ok_for_arm (INTVAL (operands[1]))
3040        || const_ok_for_arm (~INTVAL (operands[1])))"
3041   "@
3042    mov%?\\t%0, %1\\t%@ movhi
3043    mvn%?\\t%0, #%B1\\t%@ movhi
3044    ldr%?\\t%0, %1\\t%@ movhi"
3045 [(set_attr "type" "*,*,load")])
3047 (define_insn "*movhi_insn_bigend"
3048   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3049         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
3050   "! arm_arch4
3051    && BYTES_BIG_ENDIAN
3052    && ! TARGET_SHORT_BY_BYTES
3053    && (GET_CODE (operands[1]) != CONST_INT
3054        || const_ok_for_arm (INTVAL (operands[1]))
3055        || const_ok_for_arm (~INTVAL (operands[1])))"
3056   "@
3057    mov%?\\t%0, %1\\t%@ movhi
3058    mvn%?\\t%0, #%B1\\t%@ movhi
3059    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
3060 [(set_attr "type" "*,*,load")
3061  (set_attr "length" "4,4,8")])
3063 (define_insn "*loadhi_si_bigend"
3064   [(set (match_operand:SI 0 "s_register_operand" "=r")
3065         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
3066                    (const_int 16)))]
3067   "BYTES_BIG_ENDIAN
3068    && ! TARGET_SHORT_BY_BYTES"
3069   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
3070 [(set_attr "type" "load")])
3072 (define_insn "*movhi_bytes"
3073   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
3074         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
3075   "TARGET_SHORT_BY_BYTES"
3076   "@
3077    mov%?\\t%0, %1\\t%@ movhi
3078    mvn%?\\t%0, #%B1\\t%@ movhi")
3081 (define_expand "reload_outhi"
3082   [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
3083               (match_operand:HI 1 "s_register_operand" "r")
3084               (match_operand:SI 2 "s_register_operand" "=&r")])]
3085   ""
3086   "
3087   arm_reload_out_hi (operands);
3088   DONE;
3091 (define_expand "reload_inhi"
3092   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
3093               (match_operand:HI 1 "reload_memory_operand" "o")
3094               (match_operand:SI 2 "s_register_operand" "=&r")])]
3095   "TARGET_SHORT_BY_BYTES"
3096   "
3097   arm_reload_in_hi (operands);
3098   DONE;
3101 (define_expand "movqi"
3102   [(set (match_operand:QI 0 "general_operand" "")
3103         (match_operand:QI 1 "general_operand" ""))]
3104   ""
3105   "
3106   /* Everything except mem = const or mem = mem can be done easily */
3108   if (!(reload_in_progress || reload_completed))
3109     {
3110       if (GET_CODE (operands[1]) == CONST_INT)
3111         {
3112           rtx reg = gen_reg_rtx (SImode);
3114           emit_insn (gen_movsi (reg, operands[1]));
3115           operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
3116         }
3117       if (GET_CODE (operands[0]) == MEM)
3118         operands[1] = force_reg (QImode, operands[1]);
3119     }
3123 (define_insn "*movqi_insn"
3124   [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
3125         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
3126   "register_operand (operands[0], QImode)
3127    || register_operand (operands[1], QImode)"
3128   "@
3129    mov%?\\t%0, %1
3130    mvn%?\\t%0, #%B1
3131    ldr%?b\\t%0, %1
3132    str%?b\\t%1, %0"
3133 [(set_attr "type" "*,*,load,store1")])
3135 (define_expand "movsf"
3136   [(set (match_operand:SF 0 "general_operand" "")
3137         (match_operand:SF 1 "general_operand" ""))]
3138   ""
3139   "
3140   if (GET_CODE (operands[0]) == MEM)
3141     operands[1] = force_reg (SFmode, operands[1]);
3144 (define_insn "*movsf_hard_insn"
3145   [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
3146         (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
3147   "TARGET_HARD_FLOAT
3148    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3149   "@
3150    mvf%?s\\t%0, %1
3151    mnf%?s\\t%0, #%N1
3152    ldf%?s\\t%0, %1
3153    stf%?s\\t%1, %0
3154    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
3155    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
3156    mov%?\\t%0, %1
3157    ldr%?\\t%0, %1\\t%@ float
3158    str%?\\t%1, %0\\t%@ float"
3159 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
3160  (set_attr "type"
3161          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
3163 ;; Exactly the same as above, except that all `f' cases are deleted.
3164 ;; This is necessary to prevent reload from ever trying to use a `f' reg
3165 ;; when -msoft-float.
3167 (define_insn "*movsf_soft_insn"
3168   [(set (match_operand:SF 0 "general_operand" "=r,r,m")
3169         (match_operand:SF 1 "general_operand" "r,mE,r"))]
3170   "TARGET_SOFT_FLOAT
3171    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3172   "@
3173    mov%?\\t%0, %1
3174    ldr%?\\t%0, %1\\t%@ float
3175    str%?\\t%1, %0\\t%@ float"
3176 [(set_attr "length" "4,4,4")
3177  (set_attr "type" "*,load,store1")])
3179 (define_expand "movdf"
3180   [(set (match_operand:DF 0 "general_operand" "")
3181         (match_operand:DF 1 "general_operand" ""))]
3182   ""
3183   "
3184   if (GET_CODE (operands[0]) == MEM)
3185     operands[1] = force_reg (DFmode, operands[1]);
3188 ;; Reloading a df mode value stored in integer regs to memory can require a
3189 ;; scratch reg.
3190 (define_expand "reload_outdf"
3191   [(match_operand:DF 0 "reload_memory_operand" "=o")
3192    (match_operand:DF 1 "s_register_operand" "r")
3193    (match_operand:SI 2 "s_register_operand" "=&r")]
3194   ""
3195   "
3197   enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
3199   if (code == REG)
3200     operands[2] = XEXP (operands[0], 0);
3201   else if (code == POST_INC || code == PRE_DEC)
3202     {
3203       operands[0] = gen_rtx (SUBREG, DImode, operands[0], 0);
3204       operands[1] = gen_rtx (SUBREG, DImode, operands[1], 0);
3205       emit_insn (gen_movdi (operands[0], operands[1]));
3206       DONE;
3207     }
3208   else if (code == PRE_INC)
3209     {
3210       rtx reg = XEXP (XEXP (operands[0], 0), 0);
3211       emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
3212       operands[2] = reg;
3213     }
3214   else if (code == POST_DEC)
3215     operands[2] = XEXP (XEXP (operands[0], 0), 0);
3216   else
3217     emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
3218                            XEXP (XEXP (operands[0], 0), 1)));
3220   emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DFmode, operands[2]),
3221                       operands[1]));
3223   if (code == POST_DEC)
3224     emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
3226   DONE;
3230 (define_insn "*movdf_hard_insn"
3231   [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
3232         (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
3233   "TARGET_HARD_FLOAT
3234    && (GET_CODE (operands[0]) != MEM
3235        || register_operand (operands[1], DFmode))"
3236   "*
3238   rtx ops[3];
3240   switch (which_alternative)
3241     {
3242     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3243     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3244     case 2: case 3: case 4: return output_move_double (operands);
3245     case 5: return \"mvf%?d\\t%0, %1\";
3246     case 6: return \"mnf%?d\\t%0, #%N1\";
3247     case 7: return \"ldf%?d\\t%0, %1\";
3248     case 8: return \"stf%?d\\t%1, %0\";
3249     case 9: return output_mov_double_fpu_from_arm (operands);
3250     case 10: return output_mov_double_arm_from_fpu (operands);
3251     }
3254 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3255  (set_attr "type"
3256 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
3258 ;; Software floating point version.  This is essentially the same as movdi.
3259 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
3260 ;; an `f' reg.
3262 (define_insn "*movdf_soft_insn"
3263   [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3264         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3265   "TARGET_SOFT_FLOAT"
3266   "* return output_move_double (operands);"
3267 [(set_attr "length" "8,8,8")
3268  (set_attr "type" "*,load,store2")])
3270 (define_expand "movxf"
3271   [(set (match_operand:XF 0 "general_operand" "")
3272         (match_operand:XF 1 "general_operand" ""))]
3273   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3274   "")
3276 ;; Even when the XFmode patterns aren't enabled, we enable this after
3277 ;; reloading so that we can push floating point registers in the prologue.
3279 (define_insn "*movxf_hard_insn"
3280   [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3281         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3282   "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3283   "*
3284   switch (which_alternative)
3285     {
3286     case 0: return \"mvf%?e\\t%0, %1\";
3287     case 1: return \"mnf%?e\\t%0, #%N1\";
3288     case 2: return \"ldf%?e\\t%0, %1\";
3289     case 3: return \"stf%?e\\t%1, %0\";
3290     case 4: return output_mov_long_double_fpu_from_arm (operands);
3291     case 5: return output_mov_long_double_arm_from_fpu (operands);
3292     case 6: return output_mov_long_double_arm_from_arm (operands);
3293     }
3295 [(set_attr "length" "4,4,4,4,8,8,12")
3296  (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
3299 ;; load- and store-multiple insns
3300 ;; The arm can load/store any set of registers, provided that they are in
3301 ;; ascending order; but that is beyond GCC so stick with what it knows.
3303 (define_expand "load_multiple"
3304   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3305                           (match_operand:SI 1 "" ""))
3306                      (use (match_operand:SI 2 "" ""))])]
3307   ""
3308   "
3309   /* Support only fixed point registers */
3310   if (GET_CODE (operands[2]) != CONST_INT
3311       || INTVAL (operands[2]) > 14
3312       || INTVAL (operands[2]) < 2
3313       || GET_CODE (operands[1]) != MEM
3314       || GET_CODE (operands[0]) != REG
3315       || REGNO (operands[0]) > 14
3316       || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
3317     FAIL;
3319   operands[3]
3320     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
3321                              force_reg (SImode, XEXP (operands[1], 0)),
3322                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
3323                              MEM_IN_STRUCT_P(operands[1]));
3326 ;; Load multiple with write-back
3328 (define_insn "*ldmsi_postinc"
3329   [(match_parallel 0 "load_multiple_operation"
3330     [(set (match_operand:SI 1 "s_register_operand" "+r")
3331           (plus:SI (match_dup 1)
3332                    (match_operand:SI 2 "const_int_operand" "n")))
3333      (set (match_operand:SI 3 "s_register_operand" "=r")
3334           (mem:SI (match_dup 1)))])]
3335   "(INTVAL (operands[2])  == 4 * (XVECLEN (operands[0], 0) - 2))"
3336   "*
3338   rtx ops[3];
3339   int count = XVECLEN (operands[0], 0);
3341   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3342   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
3343   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
3345   output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
3346   return \"\";
3349 [(set_attr "type" "load")])
3351 ;; Ordinary load multiple
3353 (define_insn "*ldmsi"
3354   [(match_parallel 0 "load_multiple_operation"
3355     [(set (match_operand:SI 1 "s_register_operand" "=r")
3356           (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3357   ""
3358   "*
3360   rtx ops[3];
3361   int count = XVECLEN (operands[0], 0);
3363   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3364   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3365   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3367   output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3368   return \"\";
3371 [(set_attr "type" "load")])
3373 (define_expand "store_multiple"
3374   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3375                           (match_operand:SI 1 "" ""))
3376                      (use (match_operand:SI 2 "" ""))])]
3377   ""
3378   "
3379   /* Support only fixed point registers */
3380   if (GET_CODE (operands[2]) != CONST_INT
3381       || INTVAL (operands[2]) > 14
3382       || INTVAL (operands[2]) < 2
3383       || GET_CODE (operands[1]) != REG
3384       || GET_CODE (operands[0]) != MEM
3385       || REGNO (operands[1]) > 14
3386       || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3387     FAIL;
3389   operands[3]
3390     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3391                               force_reg (SImode, XEXP (operands[0], 0)),
3392                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
3393                               MEM_IN_STRUCT_P(operands[0]));
3396 ;; Store multiple with write-back
3398 (define_insn "*stmsi_postinc"
3399   [(match_parallel 0 "store_multiple_operation"
3400     [(set (match_operand:SI 1 "s_register_operand" "+r")
3401           (plus:SI (match_dup 1)
3402                    (match_operand:SI 2 "const_int_operand" "n")))
3403      (set (mem:SI (match_dup 1))
3404           (match_operand:SI 3 "s_register_operand" "r"))])]
3405   "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3406   "*
3408   rtx ops[3];
3409   int count = XVECLEN (operands[0], 0);
3411   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3412   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3413   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3415   output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3416   return \"\";
3419 [(set (attr "type")
3420       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3421                 (const_string "store2")
3422              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3423                 (const_string "store3")]
3424           (const_string "store4")))])
3426 ;; Ordinary store multiple
3428 (define_insn "*stmsi"
3429   [(match_parallel 0 "store_multiple_operation"
3430     [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3431           (match_operand:SI 1 "s_register_operand" "r"))])]
3432   ""
3433   "*
3435   rtx ops[3];
3436   int count = XVECLEN (operands[0], 0);
3438   ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3439   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3440   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3442   output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3443   return \"\";
3446 [(set (attr "type")
3447       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3448                 (const_string "store2")
3449              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3450                 (const_string "store3")]
3451           (const_string "store4")))])
3453 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
3454 ;; We could let this apply for blocks of less than this, but it clobbers so
3455 ;; many registers that there is then probably a better way.
3457 (define_expand "movstrqi"
3458   [(match_operand:BLK 0 "general_operand" "")
3459    (match_operand:BLK 1 "general_operand" "")
3460    (match_operand:SI 2 "const_int_operand" "")
3461    (match_operand:SI 3 "const_int_operand" "")]
3462   ""
3463   "
3464   if (arm_gen_movstrqi (operands))
3465     DONE;
3466   FAIL;
3470 ;; Comparison and test insns
3472 (define_expand "cmpsi"
3473   [(match_operand:SI 0 "s_register_operand" "")
3474    (match_operand:SI 1 "arm_add_operand" "")]
3475   ""
3476   "
3478   arm_compare_op0 = operands[0];
3479   arm_compare_op1 = operands[1];
3480   arm_compare_fp = 0;
3481   DONE;
3485 (define_expand "cmpsf"
3486   [(match_operand:SF 0 "s_register_operand" "")
3487    (match_operand:SF 1 "fpu_rhs_operand" "")]
3488   "TARGET_HARD_FLOAT"
3489   "
3491   arm_compare_op0 = operands[0];
3492   arm_compare_op1 = operands[1];
3493   arm_compare_fp = 1;
3494   DONE;
3498 (define_expand "cmpdf"
3499   [(match_operand:DF 0 "s_register_operand" "")
3500    (match_operand:DF 1 "fpu_rhs_operand" "")]
3501   "TARGET_HARD_FLOAT"
3502   "
3504   arm_compare_op0 = operands[0];
3505   arm_compare_op1 = operands[1];
3506   arm_compare_fp = 1;
3507   DONE;
3511 (define_expand "cmpxf"
3512   [(match_operand:XF 0 "s_register_operand" "")
3513    (match_operand:XF 1 "fpu_rhs_operand" "")]
3514   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3515   "
3517   arm_compare_op0 = operands[0];
3518   arm_compare_op1 = operands[1];
3519   arm_compare_fp = 1;
3520   DONE;
3524 (define_insn "*cmpsi_insn"
3525   [(set (reg:CC 24)
3526         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3527                     (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3528   ""
3529   "@
3530    cmp%?\\t%0, %1
3531    cmn%?\\t%0, #%n1"
3532 [(set_attr "conds" "set")])
3534 (define_insn "*cmpsi_shiftsi"
3535   [(set (reg:CC 24)
3536         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3537                     (match_operator:SI 3 "shift_operator"
3538                      [(match_operand:SI 1 "s_register_operand" "r")
3539                       (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3540   ""
3541   "cmp%?\\t%0, %1%S3"
3542 [(set_attr "conds" "set")])
3544 (define_insn "*cmpsi_shiftsi_swp"
3545   [(set (reg:CC_SWP 24)
3546         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3547                          [(match_operand:SI 1 "s_register_operand" "r")
3548                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
3549                         (match_operand:SI 0 "s_register_operand" "r")))]
3550   ""
3551   "cmp%?\\t%0, %1%S3"
3552 [(set_attr "conds" "set")])
3554 (define_insn "*cmpsi_neg_shiftsi"
3555   [(set (reg:CC 24)
3556         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3557                     (neg:SI (match_operator:SI 3 "shift_operator"
3558                              [(match_operand:SI 1 "s_register_operand" "r")
3559                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3560   ""
3561   "cmn%?\\t%0, %1%S3"
3562 [(set_attr "conds" "set")])
3564 (define_insn "*cmpsf_insn"
3565   [(set (reg:CCFP 24)
3566         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3567                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3568   "TARGET_HARD_FLOAT"
3569   "@
3570    cmf%?\\t%0, %1
3571    cnf%?\\t%0, #%N1"
3572 [(set_attr "conds" "set")
3573  (set_attr "type" "f_2_r")])
3575 (define_insn "*cmpdf_insn"
3576   [(set (reg:CCFP 24)
3577         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3578                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3579   "TARGET_HARD_FLOAT"
3580   "@
3581    cmf%?\\t%0, %1
3582    cnf%?\\t%0, #%N1"
3583 [(set_attr "conds" "set")
3584  (set_attr "type" "f_2_r")])
3586 (define_insn "*cmpesfdf_df"
3587   [(set (reg:CCFP 24)
3588         (compare:CCFP (float_extend:DF
3589                        (match_operand:SF 0 "s_register_operand" "f,f"))
3590                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3591   "TARGET_HARD_FLOAT"
3592   "@
3593    cmf%?\\t%0, %1
3594    cnf%?\\t%0, #%N1"
3595 [(set_attr "conds" "set")
3596  (set_attr "type" "f_2_r")])
3598 (define_insn "*cmpdf_esfdf"
3599   [(set (reg:CCFP 24)
3600         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3601                       (float_extend:DF
3602                        (match_operand:SF 1 "s_register_operand" "f"))))]
3603   "TARGET_HARD_FLOAT"
3604   "cmf%?\\t%0, %1"
3605 [(set_attr "conds" "set")
3606  (set_attr "type" "f_2_r")])
3608 (define_insn "*cmpxf_insn"
3609   [(set (reg:CCFP 24)
3610         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3611                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3612   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3613   "@
3614    cmf%?\\t%0, %1
3615    cnf%?\\t%0, #%N1"
3616 [(set_attr "conds" "set")
3617  (set_attr "type" "f_2_r")])
3619 (define_insn "*cmpsf_trap"
3620   [(set (reg:CCFPE 24)
3621         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3622                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3623   "TARGET_HARD_FLOAT"
3624   "@
3625    cmf%?e\\t%0, %1
3626    cnf%?e\\t%0, #%N1"
3627 [(set_attr "conds" "set")
3628  (set_attr "type" "f_2_r")])
3630 (define_insn "*cmpdf_trap"
3631   [(set (reg:CCFPE 24)
3632         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3633                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3634   "TARGET_HARD_FLOAT"
3635   "@
3636    cmf%?e\\t%0, %1
3637    cnf%?e\\t%0, #%N1"
3638 [(set_attr "conds" "set")
3639  (set_attr "type" "f_2_r")])
3641 (define_insn "*cmp_esfdf_df_trap"
3642   [(set (reg:CCFPE 24)
3643         (compare:CCFPE (float_extend:DF
3644                         (match_operand:SF 0 "s_register_operand" "f,f"))
3645                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3646   "TARGET_HARD_FLOAT"
3647   "@
3648    cmf%?e\\t%0, %1
3649    cnf%?e\\t%0, #%N1"
3650 [(set_attr "conds" "set")
3651  (set_attr "type" "f_2_r")])
3653 (define_insn "*cmp_df_esfdf_trap"
3654   [(set (reg:CCFPE 24)
3655         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3656                        (float_extend:DF
3657                         (match_operand:SF 1 "s_register_operand" "f"))))]
3658   "TARGET_HARD_FLOAT"
3659   "cmf%?e\\t%0, %1"
3660 [(set_attr "conds" "set")
3661  (set_attr "type" "f_2_r")])
3663 (define_insn "*cmpxf_trap"
3664   [(set (reg:CCFPE 24)
3665         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3666                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3667   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3668   "@
3669    cmf%?e\\t%0, %1
3670    cnf%?e\\t%0, #%N1"
3671 [(set_attr "conds" "set")
3672  (set_attr "type" "f_2_r")])
3674 ; This insn allows redundant compares to be removed by cse, nothing should
3675 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3676 ; is deleted later on. The match_dup will match the mode here, so that
3677 ; mode changes of the condition codes aren't lost by this even though we don't
3678 ; specify what they are.
3680 (define_insn "*deleted_compare"
3681   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3682   ""
3683   "\\t%@ deleted compare"
3684 [(set_attr "conds" "set")
3685  (set_attr "length" "0")])
3688 ;; Conditional branch insns
3690 (define_expand "beq"
3691   [(set (pc)
3692         (if_then_else (eq (match_dup 1) (const_int 0))
3693                       (label_ref (match_operand 0 "" ""))
3694                       (pc)))]
3695   ""
3696   "
3698   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3699                                  arm_compare_fp);
3703 (define_expand "bne"
3704   [(set (pc)
3705         (if_then_else (ne (match_dup 1) (const_int 0))
3706                       (label_ref (match_operand 0 "" ""))
3707                       (pc)))]
3708   ""
3709   "
3711   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3712                                  arm_compare_fp);
3716 (define_expand "bgt"
3717   [(set (pc)
3718         (if_then_else (gt (match_dup 1) (const_int 0))
3719                       (label_ref (match_operand 0 "" ""))
3720                       (pc)))]
3721   ""
3722   "
3724   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3725                                  arm_compare_fp);
3729 (define_expand "ble"
3730   [(set (pc)
3731         (if_then_else (le (match_dup 1) (const_int 0))
3732                       (label_ref (match_operand 0 "" ""))
3733                       (pc)))]
3734   ""
3735   "
3737   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3738                                  arm_compare_fp);
3742 (define_expand "bge"
3743   [(set (pc)
3744         (if_then_else (ge (match_dup 1) (const_int 0))
3745                       (label_ref (match_operand 0 "" ""))
3746                       (pc)))]
3747   ""
3748   "
3750   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3751                                  arm_compare_fp);
3755 (define_expand "blt"
3756   [(set (pc)
3757         (if_then_else (lt (match_dup 1) (const_int 0))
3758                       (label_ref (match_operand 0 "" ""))
3759                       (pc)))]
3760   ""
3761   "
3763   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3764                                  arm_compare_fp);
3768 (define_expand "bgtu"
3769   [(set (pc)
3770         (if_then_else (gtu (match_dup 1) (const_int 0))
3771                       (label_ref (match_operand 0 "" ""))
3772                       (pc)))]
3773   ""
3774   "
3776   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3777                                  arm_compare_fp);
3781 (define_expand "bleu"
3782   [(set (pc)
3783         (if_then_else (leu (match_dup 1) (const_int 0))
3784                       (label_ref (match_operand 0 "" ""))
3785                       (pc)))]
3786   ""
3787   "
3789   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3790                                  arm_compare_fp);
3794 (define_expand "bgeu"
3795   [(set (pc)
3796         (if_then_else (geu (match_dup 1) (const_int 0))
3797                       (label_ref (match_operand 0 "" ""))
3798                       (pc)))]
3799   ""
3800   "
3802   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3803                                  arm_compare_fp);
3807 (define_expand "bltu"
3808   [(set (pc)
3809         (if_then_else (ltu (match_dup 1) (const_int 0))
3810                       (label_ref (match_operand 0 "" ""))
3811                       (pc)))]
3812   ""
3813   "
3815   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3816                                  arm_compare_fp);
3820 ;; patterns to match conditional branch insns
3822 (define_insn "*condbranch"
3823   [(set (pc)
3824         (if_then_else (match_operator 1 "comparison_operator"
3825                        [(match_operand 2 "cc_register" "") (const_int 0)])
3826                       (label_ref (match_operand 0 "" ""))
3827                       (pc)))]
3828   ""
3829   "*
3831   extern int arm_ccfsm_state;
3833   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3834   {
3835     arm_ccfsm_state += 2;
3836     return \"\";
3837   }
3838   return \"b%d1\\t%l0\";
3840 [(set_attr "conds" "use")])
3842 (define_insn "*condbranch_reversed"
3843   [(set (pc)
3844         (if_then_else (match_operator 1 "comparison_operator"
3845                        [(match_operand 2 "cc_register" "") (const_int 0)])
3846                       (pc)
3847                       (label_ref (match_operand 0 "" ""))))]
3848   ""
3849   "*
3851   extern int arm_ccfsm_state;
3853   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3854   {
3855     arm_ccfsm_state += 2;
3856     return \"\";
3857   }
3858   return \"b%D1\\t%l0\";
3860 [(set_attr "conds" "use")])
3863 ; scc insns
3865 (define_expand "seq"
3866   [(set (match_operand:SI 0 "s_register_operand" "=r")
3867         (eq:SI (match_dup 1) (const_int 0)))]
3868   ""
3869   "
3871   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3872                                  arm_compare_fp);
3876 (define_expand "sne"
3877   [(set (match_operand:SI 0 "s_register_operand" "=r")
3878         (ne:SI (match_dup 1) (const_int 0)))]
3879   ""
3880   "
3882   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3883                                  arm_compare_fp);
3887 (define_expand "sgt"
3888   [(set (match_operand:SI 0 "s_register_operand" "=r")
3889         (gt:SI (match_dup 1) (const_int 0)))]
3890   ""
3891   "
3893   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3894                                  arm_compare_fp);
3898 (define_expand "sle"
3899   [(set (match_operand:SI 0 "s_register_operand" "=r")
3900         (le:SI (match_dup 1) (const_int 0)))]
3901   ""
3902   "
3904   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3905                                  arm_compare_fp);
3909 (define_expand "sge"
3910   [(set (match_operand:SI 0 "s_register_operand" "=r")
3911         (ge:SI (match_dup 1) (const_int 0)))]
3912   ""
3913   "
3915   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3916                                  arm_compare_fp);
3920 (define_expand "slt"
3921   [(set (match_operand:SI 0 "s_register_operand" "=r")
3922         (lt:SI (match_dup 1) (const_int 0)))]
3923   ""
3924   "
3926   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3927                                  arm_compare_fp);
3931 (define_expand "sgtu"
3932   [(set (match_operand:SI 0 "s_register_operand" "=r")
3933         (gtu:SI (match_dup 1) (const_int 0)))]
3934   ""
3935   "
3937   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3938                                  arm_compare_fp);
3942 (define_expand "sleu"
3943   [(set (match_operand:SI 0 "s_register_operand" "=r")
3944         (leu:SI (match_dup 1) (const_int 0)))]
3945   ""
3946   "
3948   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3949                                  arm_compare_fp);
3953 (define_expand "sgeu"
3954   [(set (match_operand:SI 0 "s_register_operand" "=r")
3955         (geu:SI (match_dup 1) (const_int 0)))]
3956   ""
3957   "
3959   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3960                                  arm_compare_fp);
3964 (define_expand "sltu"
3965   [(set (match_operand:SI 0 "s_register_operand" "=r")
3966         (ltu:SI (match_dup 1) (const_int 0)))]
3967   ""
3968   "
3970   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3971                                  arm_compare_fp);
3975 (define_insn "*mov_scc"
3976   [(set (match_operand:SI 0 "s_register_operand" "=r")
3977         (match_operator:SI 1 "comparison_operator"
3978          [(match_operand 2 "cc_register" "") (const_int 0)]))]
3979   ""
3980   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
3981 [(set_attr "conds" "use")
3982  (set_attr "length" "8")])
3984 (define_insn "*mov_negscc"
3985   [(set (match_operand:SI 0 "s_register_operand" "=r")
3986         (neg:SI (match_operator:SI 1 "comparison_operator"
3987                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
3988   ""
3989   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
3990 [(set_attr "conds" "use")
3991  (set_attr "length" "8")])
3993 (define_insn "*mov_notscc"
3994   [(set (match_operand:SI 0 "s_register_operand" "=r")
3995         (not:SI (match_operator:SI 1 "comparison_operator"
3996                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
3997   ""
3998   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
3999 [(set_attr "conds" "use")
4000  (set_attr "length" "8")])
4003 ;; Conditional move insns
4005 (define_expand "movsicc"
4006   [(set (match_operand:SI 0 "s_register_operand" "")
4007         (if_then_else:SI (match_operand 1 "comparison_operator" "")
4008                          (match_operand:SI 2 "arm_not_operand" "")
4009                          (match_operand:SI 3 "arm_not_operand" "")))]
4010   ""
4011   "
4013   enum rtx_code code = GET_CODE (operands[1]);
4014   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4015                                arm_compare_fp);
4017   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4020 (define_expand "movsfcc"
4021   [(set (match_operand:SF 0 "s_register_operand" "")
4022         (if_then_else:SF (match_operand 1 "comparison_operator" "")
4023                          (match_operand:SF 2 "s_register_operand" "")
4024                          (match_operand:SF 3 "nonmemory_operand" "")))]
4025   ""
4026   "
4028   enum rtx_code code = GET_CODE (operands[1]);
4029   rtx ccreg;
4031   /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
4032      Otherwise, ensure it is a valid FP add operand */
4033   if ((! TARGET_HARD_FLOAT)
4034       || (! fpu_add_operand (operands[3], SFmode)))
4035     operands[3] = force_reg (SFmode, operands[3]);
4037   ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4038                            arm_compare_fp);
4040   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4043 (define_expand "movdfcc"
4044   [(set (match_operand:DF 0 "s_register_operand" "")
4045         (if_then_else:DF (match_operand 1 "comparison_operator" "")
4046                          (match_operand:DF 2 "s_register_operand" "")
4047                          (match_operand:DF 3 "fpu_add_operand" "")))]
4048   "TARGET_HARD_FLOAT"
4049   "
4051   enum rtx_code code = GET_CODE (operands[1]);
4052   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4053                                arm_compare_fp);
4055   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4058 (define_insn "*movsicc_insn"
4059   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
4060         (if_then_else:SI
4061          (match_operator 3 "comparison_operator"
4062           [(match_operand 4 "cc_register" "") (const_int 0)])
4063          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
4064          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
4065   ""
4066   "@
4067    mov%D3\\t%0, %2
4068    mvn%D3\\t%0, #%B2
4069    mov%d3\\t%0, %1
4070    mvn%d3\\t%0, #%B1
4071    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
4072    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
4073    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
4074    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
4075   [(set_attr "length" "4,4,4,4,8,8,8,8")
4076    (set_attr "conds" "use")])
4078 (define_insn "*movsfcc_hard_insn"
4079   [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4080         (if_then_else:SF
4081          (match_operator 3 "comparison_operator" 
4082           [(match_operand 4 "cc_register" "") (const_int 0)])
4083          (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4084          (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4085   "TARGET_HARD_FLOAT"
4086   "@
4087    mvf%D3s\\t%0, %2
4088    mnf%D3s\\t%0, #%N2
4089    mvf%d3s\\t%0, %1
4090    mnf%d3s\\t%0, #%N1
4091    mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
4092    mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
4093    mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
4094    mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
4095   [(set_attr "length" "4,4,4,4,8,8,8,8")
4096    (set_attr "type" "ffarith")
4097    (set_attr "conds" "use")])
4099 (define_insn "*movsfcc_soft_insn"
4100   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
4101         (if_then_else:SF (match_operator 3 "comparison_operator"
4102                           [(match_operand 4 "cc_register" "") (const_int 0)])
4103                          (match_operand:SF 1 "s_register_operand" "0,r")
4104                          (match_operand:SF 2 "s_register_operand" "r,0")))]
4105   "TARGET_SOFT_FLOAT"
4106   "@
4107    mov%D3\\t%0, %2
4108    mov%d3\\t%0, %1"
4109   [(set_attr "conds" "use")])
4111 (define_insn "*movdfcc_insn"
4112   [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4113         (if_then_else:DF
4114          (match_operator 3 "comparison_operator"
4115           [(match_operand 4 "cc_register" "") (const_int 0)])
4116          (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4117          (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4118   "TARGET_HARD_FLOAT"
4119   "@
4120    mvf%D3d\\t%0, %2
4121    mnf%D3d\\t%0, #%N2
4122    mvf%d3d\\t%0, %1
4123    mnf%d3d\\t%0, #%N1
4124    mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
4125    mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
4126    mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
4127    mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
4128   [(set_attr "length" "4,4,4,4,8,8,8,8")
4129    (set_attr "type" "ffarith")
4130    (set_attr "conds" "use")])
4132 ;; Jump and linkage insns
4134 (define_insn "jump"
4135   [(set (pc)
4136         (label_ref (match_operand 0 "" "")))]
4137   ""
4138   "*
4140   extern int arm_ccfsm_state;
4142   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4143   {
4144     arm_ccfsm_state += 2;
4145     return \"\";
4146   }
4147   return \"b%?\\t%l0\";
4150 (define_expand "call"
4151   [(parallel [(call (match_operand 0 "memory_operand" "")
4152                     (match_operand 1 "general_operand" ""))
4153               (clobber (reg:SI 14))])]
4154   ""
4155   "")
4157 (define_insn "*call_reg"
4158   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
4159          (match_operand 1 "" "g"))
4160    (clobber (reg:SI 14))]
4161   ""
4162   "*
4163   return output_call (operands);
4165 ;; length is worst case, normally it is only two
4166 [(set_attr "length" "12")
4167  (set_attr "type" "call")])
4169 (define_insn "*call_mem"
4170   [(call (mem:SI (match_operand 0 "memory_operand" "m"))
4171          (match_operand 1 "general_operand" "g"))
4172    (clobber (reg:SI 14))]
4173   ""
4174   "*
4175   return output_call_mem (operands);
4177 [(set_attr "length" "12")
4178  (set_attr "type" "call")])
4180 (define_expand "call_value"
4181   [(parallel [(set (match_operand 0 "" "=rf")
4182                    (call (match_operand 1 "memory_operand" "m")
4183                          (match_operand 2 "general_operand" "g")))
4184               (clobber (reg:SI 14))])]
4185   ""
4186   "")
4188 (define_insn "*call_value_reg"
4189   [(set (match_operand 0 "" "=rf")
4190         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4191               (match_operand 2 "general_operand" "g")))
4192    (clobber (reg:SI 14))]
4193   ""
4194   "*
4195   return output_call (&operands[1]);
4197 [(set_attr "length" "12")
4198  (set_attr "type" "call")])
4200 (define_insn "*call_value_mem"
4201   [(set (match_operand 0 "" "=rf")
4202         (call (mem:SI (match_operand 1 "memory_operand" "m"))
4203         (match_operand 2 "general_operand" "g")))
4204    (clobber (reg:SI 14))]
4205   "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4206   "*
4207   return output_call_mem (&operands[1]);
4209 [(set_attr "length" "12")
4210  (set_attr "type" "call")])
4212 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4213 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4215 (define_insn "*call_symbol"
4216   [(call (mem:SI (match_operand:SI 0 "" "X"))
4217          (match_operand:SI 1 "general_operand" "g"))
4218    (clobber (reg:SI 14))]
4219   "GET_CODE (operands[0]) == SYMBOL_REF"
4220   "bl%?\\t%a0"
4221 [(set_attr "type" "call")])
4223 (define_insn "*call_value_symbol"
4224   [(set (match_operand 0 "s_register_operand" "=rf")
4225         (call (mem:SI (match_operand:SI 1 "" "X"))
4226         (match_operand:SI 2 "general_operand" "g")))
4227    (clobber (reg:SI 14))]
4228   "GET_CODE(operands[1]) == SYMBOL_REF"
4229   "bl%?\\t%a1"
4230 [(set_attr "type" "call")])
4232 ;; Often the return insn will be the same as loading from memory, so set attr
4233 (define_insn "return"
4234   [(return)]
4235   "USE_RETURN_INSN"
4236   "*
4238   extern int arm_ccfsm_state;
4240   if (arm_ccfsm_state == 2)
4241   {
4242     arm_ccfsm_state += 2;
4243     return \"\";
4244   }
4245   return output_return_instruction (NULL, TRUE, FALSE);
4247 [(set_attr "type" "load")])
4249 (define_insn "*cond_return"
4250   [(set (pc)
4251         (if_then_else (match_operator 0 "comparison_operator"
4252                        [(match_operand 1 "cc_register" "") (const_int 0)])
4253                       (return)
4254                       (pc)))]
4255   "USE_RETURN_INSN"
4256   "*
4258   extern int arm_ccfsm_state;
4260   if (arm_ccfsm_state == 2)
4261   {
4262     arm_ccfsm_state += 2;
4263     return \"\";
4264   }
4265   return output_return_instruction (operands[0], TRUE, FALSE);
4267 [(set_attr "conds" "use")
4268  (set_attr "type" "load")])
4270 (define_insn "*cond_return_inverted"
4271   [(set (pc)
4272         (if_then_else (match_operator 0 "comparison_operator"
4273                        [(match_operand 1 "cc_register" "") (const_int 0)])
4274                       (pc)
4275                       (return)))]
4276   "USE_RETURN_INSN"
4277   "*
4279   extern int arm_ccfsm_state;
4281   if (arm_ccfsm_state == 2)
4282   {
4283     arm_ccfsm_state += 2;
4284     return \"\";
4285   }
4286   return output_return_instruction (operands[0], TRUE, TRUE);
4288 [(set_attr "conds" "use")
4289  (set_attr "type" "load")])
4291 ;; Call subroutine returning any type.
4293 (define_expand "untyped_call"
4294   [(parallel [(call (match_operand 0 "" "")
4295                     (const_int 0))
4296               (match_operand 1 "" "")
4297               (match_operand 2 "" "")])]
4298   ""
4299   "
4301   int i;
4303   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4305   for (i = 0; i < XVECLEN (operands[2], 0); i++)
4306     {
4307       rtx set = XVECEXP (operands[2], 0, i);
4308       emit_move_insn (SET_DEST (set), SET_SRC (set));
4309     }
4311   /* The optimizer does not know that the call sets the function value
4312      registers we stored in the result block.  We avoid problems by
4313      claiming that all hard registers are used and clobbered at this
4314      point.  */
4315   emit_insn (gen_blockage ());
4317   DONE;
4320 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4321 ;; all of memory.  This blocks insns from being moved across this point.
4323 (define_insn "blockage"
4324   [(unspec_volatile [(const_int 0)] 0)]
4325   ""
4326   ""
4327 [(set_attr "length" "0")
4328  (set_attr "type" "block")])
4330 (define_expand "casesi"
4331   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
4332    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
4333    (match_operand:SI 2 "const_int_operand" "")  ; total range
4334    (match_operand:SI 3 "" "")                   ; table label
4335    (match_operand:SI 4 "" "")]                  ; Out of range label
4336   ""
4337   "
4339   rtx reg;
4340   if (operands[1] != const0_rtx)
4341     {
4342       reg = gen_reg_rtx (SImode);
4343       emit_insn (gen_addsi3 (reg, operands[0],
4344                              GEN_INT (-INTVAL (operands[1]))));
4345       operands[0] = reg;
4346     }
4348   if (! const_ok_for_arm (INTVAL (operands[2])))
4349     operands[2] = force_reg (SImode, operands[2]);
4351   emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4352                                        operands[4]));
4353   DONE;
4356 ;; The USE in this pattern is needed to tell flow analysis that this is
4357 ;; a CASESI insn.  It has no other purpose.
4358 (define_insn "casesi_internal"
4359   [(parallel [(set (pc)
4360                (if_then_else
4361                 (leu (match_operand:SI 0 "s_register_operand" "r")
4362                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
4363                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4364                                  (label_ref (match_operand 2 "" ""))))
4365                 (label_ref (match_operand 3 "" ""))))
4366               (use (label_ref (match_dup 2)))])]
4367   ""
4368   "*
4369   if (flag_pic)
4370     return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4371   return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4373 [(set_attr "conds" "clob")
4374  (set_attr "length" "12")])
4376 (define_insn "indirect_jump"
4377   [(set (pc)
4378         (match_operand:SI 0 "s_register_operand" "r"))]
4379   ""
4380   "mov%?\\t%|pc, %0\\t%@ indirect jump")
4382 (define_insn "*load_indirect_jump"
4383   [(set (pc)
4384         (match_operand:SI 0 "memory_operand" "m"))]
4385   ""
4386   "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4387 [(set_attr "type" "load")])
4389 ;; Misc insns
4391 (define_insn "nop"
4392   [(const_int 0)]
4393   ""
4394   "mov%?\\tr0, r0\\t%@ nop")
4396 ;; Patterns to allow combination of arithmetic, cond code and shifts
4398 (define_insn "*arith_shiftsi"
4399   [(set (match_operand:SI 0 "s_register_operand" "=r")
4400         (match_operator:SI 1 "shiftable_operator"
4401           [(match_operator:SI 3 "shift_operator"
4402              [(match_operand:SI 4 "s_register_operand" "r")
4403               (match_operand:SI 5 "reg_or_int_operand" "rI")])
4404            (match_operand:SI 2 "s_register_operand" "r")]))]
4405   ""
4406   "%i1%?\\t%0, %2, %4%S3")
4408 (define_insn "*arith_shiftsi_compare0"
4409   [(set (reg:CC_NOOV 24)
4410         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4411                           [(match_operator:SI 3 "shift_operator"
4412                             [(match_operand:SI 4 "s_register_operand" "r")
4413                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4414                            (match_operand:SI 2 "s_register_operand" "r")])
4415                          (const_int 0)))
4416    (set (match_operand:SI 0 "s_register_operand" "=r")
4417         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4418                          (match_dup 2)]))]
4419   ""
4420   "%i1%?s\\t%0, %2, %4%S3"
4421 [(set_attr "conds" "set")])
4423 (define_insn "*arith_shiftsi_compare0_scratch"
4424   [(set (reg:CC_NOOV 24)
4425         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4426                           [(match_operator:SI 3 "shift_operator"
4427                             [(match_operand:SI 4 "s_register_operand" "r")
4428                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4429                            (match_operand:SI 2 "s_register_operand" "r")])
4430                          (const_int 0)))
4431    (clobber (match_scratch:SI 0 "=r"))]
4432   ""
4433   "%i1%?s\\t%0, %2, %4%S3"
4434 [(set_attr "conds" "set")])
4436 (define_insn "*sub_shiftsi"
4437   [(set (match_operand:SI 0 "s_register_operand" "=r")
4438         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4439                   (match_operator:SI 2 "shift_operator"
4440                    [(match_operand:SI 3 "s_register_operand" "r")
4441                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4442   ""
4443   "sub%?\\t%0, %1, %3%S2")
4445 (define_insn "*sub_shiftsi_compare0"
4446   [(set (reg:CC_NOOV 24)
4447         (compare:CC_NOOV
4448          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4449                    (match_operator:SI 2 "shift_operator"
4450                     [(match_operand:SI 3 "s_register_operand" "r")
4451                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4452          (const_int 0)))
4453    (set (match_operand:SI 0 "s_register_operand" "=r")
4454         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4455                                                  (match_dup 4)])))]
4456   ""
4457   "sub%?s\\t%0, %1, %3%S2"
4458 [(set_attr "conds" "set")])
4460 (define_insn "*sub_shiftsi_compare0_scratch"
4461   [(set (reg:CC_NOOV 24)
4462         (compare:CC_NOOV
4463          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4464                    (match_operator:SI 2 "shift_operator"
4465                     [(match_operand:SI 3 "s_register_operand" "r")
4466                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4467          (const_int 0)))
4468    (clobber (match_scratch:SI 0 "=r"))]
4469   ""
4470   "sub%?s\\t%0, %1, %3%S2"
4471 [(set_attr "conds" "set")])
4473 ;; These variants of the above insns can occur if the first operand is the
4474 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
4475 ;; seem to be a way around it.  Most of the predicates have to be null
4476 ;; because the format can be generated part way through reload, so
4477 ;; if we don't match it as soon as it becomes available, reload doesn't know
4478 ;; how to reload pseudos that haven't got hard registers; the constraints will
4479 ;; sort everything out.
4481 (define_insn "*reload_mulsi3"
4482   [(set (match_operand:SI 0 "" "=&r")
4483         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4484                            [(match_operand:SI 3 "" "r")
4485                             (match_operand:SI 4 "" "rM")])
4486                           (match_operand:SI 2 "" "r"))
4487                  (match_operand:SI 1 "const_int_operand" "n")))]
4488   "reload_in_progress"
4489   "*
4490   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4491   operands[2] = operands[1];
4492   operands[1] = operands[0];
4493   return output_add_immediate (operands);
4495 ; we have no idea how long the add_immediate is, it could be up to 4.
4496 [(set_attr "length" "20")])
4498 (define_insn "*reload_mulsi_compare0"
4499   [(set (reg:CC_NOOV 24)
4500         (compare:CC_NOOV (plus:SI
4501                           (plus:SI 
4502                            (match_operator:SI 5 "shift_operator"
4503                             [(match_operand:SI 3 "" "r")
4504                              (match_operand:SI 4 "" "rM")])
4505                            (match_operand:SI 1 "" "r"))
4506                           (match_operand:SI 2 "const_int_operand" "n"))
4507                          (const_int 0)))
4508    (set (match_operand:SI 0 "" "=&r")
4509         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4510                           (match_dup 1))
4511                  (match_dup 2)))]
4512   "reload_in_progress"
4513   "*
4514   output_add_immediate (operands);
4515   return \"add%?s\\t%0, %0, %3%S5\";
4517 [(set_attr "conds" "set")
4518  (set_attr "length" "20")])
4520 (define_insn "*reload_mulsi_compare0_scratch"
4521   [(set (reg:CC_NOOV 24)
4522         (compare:CC_NOOV (plus:SI
4523                           (plus:SI 
4524                            (match_operator:SI 5 "shift_operator"
4525                             [(match_operand:SI 3 "" "r")
4526                              (match_operand:SI 4 "" "rM")])
4527                            (match_operand:SI 1 "" "r"))
4528                           (match_operand:SI 2 "const_int_operand" "n"))
4529                          (const_int 0)))
4530    (clobber (match_scratch:SI 0 "=&r"))]
4531   "reload_in_progress"
4532   "*
4533   output_add_immediate (operands);
4534   return \"add%?s\\t%0, %0, %3%S5\";
4536 [(set_attr "conds" "set")
4537  (set_attr "length" "20")])
4539 ;; These are similar, but are needed when the mla pattern contains the
4540 ;; eliminated register as operand 3.
4542 (define_insn "*reload_muladdsi"
4543   [(set (match_operand:SI 0 "" "=&r,&r")
4544         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4545                                    (match_operand:SI 2 "" "r,r"))
4546                           (match_operand:SI 3 "" "r,r"))
4547                  (match_operand:SI 4 "const_int_operand" "n,n")))]
4548   "reload_in_progress"
4549   "*
4550   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4551   operands[2] = operands[4];
4552   operands[1] = operands[0];
4553   return output_add_immediate (operands);
4555 [(set_attr "length" "20")
4556  (set_attr "type" "mult")])
4558 (define_insn "*reload_muladdsi_compare0"
4559   [(set (reg:CC_NOOV 24)
4560         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4561                                             (match_operand:SI 3 "" "r")
4562                                             (match_operand:SI 4 "" "r"))
4563                                            (match_operand:SI 1 "" "r"))
4564                                   (match_operand:SI 2 "const_int_operand" "n"))
4565                          (const_int 0)))
4566    (set (match_operand:SI 0 "" "=&r")
4567         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4568                  (match_dup 2)))]
4569   "reload_in_progress"
4570   "*
4571   output_add_immediate (operands);
4572   output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4573   return \"\";
4575 [(set_attr "length" "20")
4576  (set_attr "conds" "set")
4577  (set_attr "type" "mult")])
4579 (define_insn "*reload_muladdsi_compare0_scratch"
4580   [(set (reg:CC_NOOV 24)
4581         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4582                                             (match_operand:SI 3 "" "r")
4583                                             (match_operand:SI 4 "" "r"))
4584                                            (match_operand:SI 1 "" "r"))
4585                                   (match_operand:SI 2 "const_int_operand" "n"))
4586                          (const_int 0)))
4587    (clobber (match_scratch:SI 0 "=&r"))]
4588   "reload_in_progress"
4589   "*
4590   output_add_immediate (operands);
4591   return \"mla%?s\\t%0, %3, %4, %0\";
4593 [(set_attr "length" "20")
4594  (set_attr "conds" "set")
4595  (set_attr "type" "mult")])
4599 (define_insn "*and_scc"
4600   [(set (match_operand:SI 0 "s_register_operand" "=r")
4601         (and:SI (match_operator 1 "comparison_operator"
4602                  [(match_operand 3 "cc_register" "") (const_int 0)])
4603                 (match_operand:SI 2 "s_register_operand" "r")))]
4604   ""
4605   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
4606 [(set_attr "conds" "use")
4607  (set_attr "length" "8")])
4609 (define_insn "*ior_scc"
4610   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4611         (ior:SI (match_operator 2 "comparison_operator"
4612                  [(match_operand 3 "cc_register" "") (const_int 0)])
4613                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
4614   ""
4615   "@
4616    orr%d2\\t%0, %1, #1
4617    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
4618 [(set_attr "conds" "use")
4619  (set_attr "length" "4,8")])
4621 (define_insn "*compare_scc"
4622   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4623         (match_operator 1 "comparison_operator"
4624          [(match_operand:SI 2 "s_register_operand" "r,r")
4625           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4626    (clobber (reg 24))]
4627   ""
4628   "*
4629   if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4630     return \"mov\\t%0, %2, lsr #31\";
4632   if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4633     return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4635   if (GET_CODE (operands[1]) == NE)
4636     {
4637       if (which_alternative == 1)
4638         return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4639       return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4640     }
4641   if (which_alternative == 1)
4642     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4643   else
4644     output_asm_insn (\"cmp\\t%2, %3\", operands);
4645   return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4647 [(set_attr "conds" "clob")
4648  (set_attr "length" "12")])
4650 (define_insn "*cond_move"
4651   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4652         (if_then_else:SI (match_operator 3 "equality_operator"
4653                           [(match_operator 4 "comparison_operator"
4654                             [(match_operand 5 "cc_register" "") (const_int 0)])
4655                            (const_int 0)])
4656                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4657                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4658   ""
4659   "*
4660   if (GET_CODE (operands[3]) == NE)
4661     {
4662       if (which_alternative != 1)
4663         output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4664       if (which_alternative != 0)
4665         output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4666       return \"\";
4667     }
4668   if (which_alternative != 0)
4669     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4670   if (which_alternative != 1)
4671     output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4672   return \"\";
4674 [(set_attr "conds" "use")
4675  (set_attr "length" "4,4,8")])
4677 (define_insn "*cond_arith"
4678   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4679         (match_operator:SI 5 "shiftable_operator" 
4680          [(match_operator:SI 4 "comparison_operator"
4681            [(match_operand:SI 2 "s_register_operand" "r,r")
4682             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4683           (match_operand:SI 1 "s_register_operand" "0,?r")]))
4684    (clobber (reg 24))]
4685   ""
4686   "*
4687   if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4688     return \"%i5\\t%0, %1, %2, lsr #31\";
4690   output_asm_insn (\"cmp\\t%2, %3\", operands);
4691   if (GET_CODE (operands[5]) == AND)
4692     output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4693   else if (GET_CODE (operands[5]) == MINUS)
4694     output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4695   else if (which_alternative != 0)
4696     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4697   return \"%i5%d4\\t%0, %1, #1\";
4699 [(set_attr "conds" "clob")
4700  (set_attr "length" "12")])
4702 (define_insn "*cond_sub"
4703   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4704         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4705                   (match_operator:SI 4 "comparison_operator"
4706                    [(match_operand:SI 2 "s_register_operand" "r,r")
4707                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4708    (clobber (reg 24))]
4709   ""
4710   "*
4711   output_asm_insn (\"cmp\\t%2, %3\", operands);
4712   if (which_alternative != 0)
4713     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4714   return \"sub%d4\\t%0, %1, #1\";
4716 [(set_attr "conds" "clob")
4717  (set_attr "length" "8,12")])
4719 (define_insn "*cmp_ite0"
4720   [(set (match_operand 6 "dominant_cc_register" "")
4721         (compare
4722          (if_then_else:SI
4723           (match_operator 4 "comparison_operator"
4724            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4725             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4726           (match_operator:SI 5 "comparison_operator"
4727            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4728             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4729           (const_int 0))
4730          (const_int 0)))]
4731   ""
4732   "*
4734   char* opcodes[4][2] =
4735   {
4736     {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
4737     {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
4738     {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
4739     {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
4740      \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
4741   };
4742   int swap =
4743     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
4745   return opcodes[which_alternative][swap];
4748 [(set_attr "conds" "set")
4749  (set_attr "length" "8")])
4751 (define_insn "*cmp_ite1"
4752   [(set (match_operand 6 "dominant_cc_register" "")
4753         (compare
4754          (if_then_else:SI
4755           (match_operator 4 "comparison_operator"
4756            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4757             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4758           (match_operator:SI 5 "comparison_operator"
4759            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4760             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4761           (const_int 1))
4762          (const_int 0)))]
4763   ""
4764   "*
4766   char* opcodes[4][2] =
4767   {
4768     {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
4769     {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
4770     {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
4771     {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
4772      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
4773   };
4774   int swap =
4775     comparison_dominates_p (GET_CODE (operands[5]),
4776                             reverse_condition (GET_CODE (operands[4])));
4778   return opcodes[which_alternative][swap];
4781 [(set_attr "conds" "set")
4782  (set_attr "length" "8")])
4784 (define_insn "*negscc"
4785   [(set (match_operand:SI 0 "s_register_operand" "=r")
4786         (neg:SI (match_operator 3 "comparison_operator"
4787                  [(match_operand:SI 1 "s_register_operand" "r")
4788                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4789    (clobber (reg 24))]
4790   ""
4791   "*
4792   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4793     return \"mov\\t%0, %1, asr #31\";
4795   if (GET_CODE (operands[3]) == NE)
4796     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4798   if (GET_CODE (operands[3]) == GT)
4799     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4801   output_asm_insn (\"cmp\\t%1, %2\", operands);
4802   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4803   return \"mvn%d3\\t%0, #0\";
4805 [(set_attr "conds" "clob")
4806  (set_attr "length" "12")])
4808 (define_insn "movcond"
4809   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4810         (if_then_else:SI
4811          (match_operator 5 "comparison_operator"
4812           [(match_operand:SI 3 "s_register_operand" "r,r,r")
4813            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4814          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4815          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4816    (clobber (reg 24))]
4817   ""
4818   "*
4819   if (GET_CODE (operands[5]) == LT
4820       && (operands[4] == const0_rtx))
4821     {
4822       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4823         {
4824           if (operands[2] == const0_rtx)
4825             return \"and\\t%0, %1, %3, asr #31\";
4826           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4827         }
4828       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4829         {
4830           if (operands[1] == const0_rtx)
4831             return \"bic\\t%0, %2, %3, asr #31\";
4832           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4833         }
4834       /* The only case that falls through to here is when both ops 1 & 2
4835          are constants */
4836     }
4838   if (GET_CODE (operands[5]) == GE
4839       && (operands[4] == const0_rtx))
4840     {
4841       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4842         {
4843           if (operands[2] == const0_rtx)
4844             return \"bic\\t%0, %1, %3, asr #31\";
4845           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4846         }
4847       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4848         {
4849           if (operands[1] == const0_rtx)
4850             return \"and\\t%0, %2, %3, asr #31\";
4851           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4852         }
4853       /* The only case that falls through to here is when both ops 1 & 2
4854          are constants */
4855     }
4856   if (GET_CODE (operands[4]) == CONST_INT
4857       && !const_ok_for_arm (INTVAL (operands[4])))
4858     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4859   else
4860     output_asm_insn (\"cmp\\t%3, %4\", operands);
4861   if (which_alternative != 0)
4862     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4863   if (which_alternative != 1)
4864     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4865   return \"\";
4867 [(set_attr "conds" "clob")
4868  (set_attr "length" "8,8,12")])
4870 (define_insn "*ifcompare_plus_move"
4871   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4872         (if_then_else:SI (match_operator 6 "comparison_operator"
4873                           [(match_operand:SI 4 "s_register_operand" "r,r")
4874                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4875                          (plus:SI
4876                           (match_operand:SI 2 "s_register_operand" "r,r")
4877                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
4878                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4879    (clobber (reg 24))]
4880   ""
4881   "#"
4882 [(set_attr "conds" "clob")
4883  (set_attr "length" "8,12")])
4885 (define_insn "*if_plus_move"
4886   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r")
4887         (if_then_else:SI
4888          (match_operator 4 "comparison_operator"
4889           [(match_operand 5 "cc_register" "") (const_int 0)])
4890          (plus:SI
4891           (match_operand:SI 2 "s_register_operand" "r,r,r,r,r,r")
4892           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L,rI,L"))
4893          (match_operand:SI 1 "arm_rhsm_operand" "0,0,?rI,?rI,m,m")))]
4894   ""
4895   "@
4896    add%d4\\t%0, %2, %3
4897    sub%d4\\t%0, %2, #%n3
4898    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4899    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1
4900    add%d4\\t%0, %2, %3\;ldr%D4\\t%0, %1
4901    sub%d4\\t%0, %2, #%n3\;ldr%D4\\t%0, %1"
4902 [(set_attr "conds" "use")
4903  (set_attr "length" "4,4,8,8,8,8")
4904  (set_attr "type" "*,*,*,*,load,load")])
4906 (define_insn "*ifcompare_move_plus"
4907   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4908         (if_then_else:SI (match_operator 6 "comparison_operator"
4909                           [(match_operand:SI 4 "s_register_operand" "r,r")
4910                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4911                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4912                          (plus:SI
4913                           (match_operand:SI 2 "s_register_operand" "r,r")
4914                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4915    (clobber (reg 24))]
4916   ""
4917   "#"
4918 [(set_attr "conds" "clob")
4919  (set_attr "length" "8,12")])
4921 (define_insn "*if_move_plus"
4922   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r")
4923         (if_then_else:SI
4924          (match_operator 4 "comparison_operator"
4925           [(match_operand 5 "cc_register" "") (const_int 0)])
4926          (match_operand:SI 1 "arm_rhsm_operand" "0,0,?rI,?rI,m,m")
4927          (plus:SI
4928           (match_operand:SI 2 "s_register_operand" "r,r,r,r,r,r")
4929           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L,rI,L"))))]
4930   ""
4931   "@
4932    add%D4\\t%0, %2, %3
4933    sub%D4\\t%0, %2, #%n3
4934    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4935    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1
4936    add%D4\\t%0, %2, %3\;ldr%d4\\t%0, %1
4937    sub%D4\\t%0, %2, #%n3\;ldr%d4\\t%0, %1"
4938 [(set_attr "conds" "use")
4939  (set_attr "length" "4,4,8,8,8,8")
4940  (set_attr "type" "*,*,*,*,load,load")])
4942 (define_insn "*ifcompare_arith_arith"
4943   [(set (match_operand:SI 0 "s_register_operand" "=r")
4944         (if_then_else:SI (match_operator 9 "comparison_operator"
4945                           [(match_operand:SI 5 "s_register_operand" "r")
4946                            (match_operand:SI 6 "arm_add_operand" "rIL")])
4947                          (match_operator:SI 8 "shiftable_operator"
4948                           [(match_operand:SI 1 "s_register_operand" "r")
4949                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
4950                          (match_operator:SI 7 "shiftable_operator"
4951                           [(match_operand:SI 3 "s_register_operand" "r")
4952                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
4953    (clobber (reg 24))]
4954   ""
4955   "#"
4956 [(set_attr "conds" "clob")
4957  (set_attr "length" "12")])
4959 (define_insn "*if_arith_arith"
4960   [(set (match_operand:SI 0 "s_register_operand" "=r")
4961         (if_then_else:SI (match_operator 5 "comparison_operator"
4962                           [(match_operand 8 "cc_register" "") (const_int 0)])
4963                          (match_operator:SI 6 "shiftable_operator"
4964                           [(match_operand:SI 1 "s_register_operand" "r")
4965                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
4966                          (match_operator:SI 7 "shiftable_operator"
4967                           [(match_operand:SI 3 "s_register_operand" "r")
4968                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
4969   ""
4970   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
4971 [(set_attr "conds" "use")
4972  (set_attr "length" "8")])
4974 (define_insn "*ifcompare_arith_move"
4975   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4976         (if_then_else:SI (match_operator 6 "comparison_operator"
4977                           [(match_operand:SI 2 "s_register_operand" "r,r")
4978                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
4979                          (match_operator:SI 7 "shiftable_operator"
4980                           [(match_operand:SI 4 "s_register_operand" "r,r")
4981                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
4982                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4983    (clobber (reg 24))]
4984   ""
4985   "*
4986   /* If we have an operation where (op x 0) is the identity operation and
4987      the conditional operator is LT or GE and we are comparing against zero and
4988      everything is in registers then we can do this in two instructions */
4989   if (operands[3] == const0_rtx
4990       && GET_CODE (operands[7]) != AND
4991       && GET_CODE (operands[5]) == REG
4992       && GET_CODE (operands[1]) == REG 
4993       && REGNO (operands[1]) == REGNO (operands[4])
4994       && REGNO (operands[4]) != REGNO (operands[0]))
4995     {
4996       if (GET_CODE (operands[6]) == LT)
4997         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4998       else if (GET_CODE (operands[6]) == GE)
4999         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5000     }
5001   if (GET_CODE (operands[3]) == CONST_INT
5002       && !const_ok_for_arm (INTVAL (operands[3])))
5003     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
5004   else
5005     output_asm_insn (\"cmp\\t%2, %3\", operands);
5006   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
5007   if (which_alternative != 0)
5008     {
5009       if (GET_CODE (operands[1]) == MEM)
5010         return \"ldr%D6\\t%0, %1\";
5011       else
5012         return \"mov%D6\\t%0, %1\";
5013     }
5014   return \"\";
5016 [(set_attr "conds" "clob")
5017  (set_attr "length" "8,12")])
5019 (define_insn "*if_arith_move"
5020   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5021         (if_then_else:SI (match_operator 4 "comparison_operator"
5022                           [(match_operand 6 "cc_register" "") (const_int 0)])
5023                          (match_operator:SI 5 "shiftable_operator"
5024                           [(match_operand:SI 2 "s_register_operand" "r,r,r")
5025                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI")])
5026                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rI,m")))]
5027   ""
5028   "@
5029    %I5%d4\\t%0, %2, %3
5030    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
5031    %I5%d4\\t%0, %2, %3\;ldr%D4\\t%0, %1"
5032 [(set_attr "conds" "use")
5033  (set_attr "length" "4,8,8")
5034  (set_attr "type" "*,*,load")])
5036 (define_insn "*ifcompare_move_arith"
5037   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5038         (if_then_else:SI (match_operator 6 "comparison_operator"
5039                           [(match_operand:SI 4 "s_register_operand" "r,r")
5040                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5041                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
5042                          (match_operator:SI 7 "shiftable_operator"
5043                           [(match_operand:SI 2 "s_register_operand" "r,r")
5044                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
5045    (clobber (reg 24))]
5046   ""
5047   "*
5048   /* If we have an operation where (op x 0) is the identity operation and
5049      the conditional operator is LT or GE and we are comparing against zero and
5050      everything is in registers then we can do this in two instructions */
5051   if (operands[5] == const0_rtx
5052       && GET_CODE (operands[7]) != AND
5053       && GET_CODE (operands[3]) == REG
5054       && GET_CODE (operands[1]) == REG 
5055       && REGNO (operands[1]) == REGNO (operands[2])
5056       && REGNO (operands[2]) != REGNO (operands[0]))
5057     {
5058       if (GET_CODE (operands[6]) == GE)
5059         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5060       else if (GET_CODE (operands[6]) == LT)
5061         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5062     }
5064   if (GET_CODE (operands[5]) == CONST_INT
5065       && !const_ok_for_arm (INTVAL (operands[5])))
5066     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5067   else
5068     output_asm_insn (\"cmp\\t%4, %5\", operands);
5070   if (which_alternative != 0)
5071     {
5072       if (GET_CODE (operands[1]) == MEM)
5073         output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
5074       else
5075         output_asm_insn (\"mov%d6\\t%0, %1\", operands);
5076     }
5077   return \"%I7%D6\\t%0, %2, %3\";
5079 [(set_attr "conds" "clob")
5080  (set_attr "length" "8,12")])
5082 (define_insn "*if_move_arith"
5083   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5084         (if_then_else:SI
5085          (match_operator 4 "comparison_operator"
5086           [(match_operand 6 "cc_register" "") (const_int 0)])
5087          (match_operand:SI 1 "arm_rhsm_operand" "0,?rI,m")
5088          (match_operator:SI 5 "shiftable_operator"
5089           [(match_operand:SI 2 "s_register_operand" "r,r,r")
5090            (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI")])))]
5091   ""
5092   "@
5093    %I5%D4\\t%0, %2, %3
5094    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
5095    %I5%D4\\t%0, %2, %3\;ldr%d4\\t%0, %1"
5096 [(set_attr "conds" "use")
5097  (set_attr "length" "4,8,8")
5098  (set_attr "type" "*,*,load")])
5100 (define_insn "*ifcompare_move_not"
5101   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5102         (if_then_else:SI
5103          (match_operator 5 "comparison_operator"
5104           [(match_operand:SI 3 "s_register_operand" "r,r")
5105            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5106          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5107          (not:SI
5108           (match_operand:SI 2 "s_register_operand" "r,r"))))
5109    (clobber (reg 24))]
5110   ""
5111   "#"
5112 [(set_attr "conds" "clob")
5113  (set_attr "length" "8,12")])
5115 (define_insn "*if_move_not"
5116   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5117         (if_then_else:SI
5118          (match_operator 4 "comparison_operator"
5119           [(match_operand 3 "cc_register" "") (const_int 0)])
5120          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5121          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5122   ""
5123   "@
5124    mvn%D4\\t%0, %2
5125    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
5126    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
5127 [(set_attr "conds" "use")
5128  (set_attr "length" "4,8,8")])
5130 (define_insn "*ifcompare_not_move"
5131   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5132         (if_then_else:SI 
5133          (match_operator 5 "comparison_operator"
5134           [(match_operand:SI 3 "s_register_operand" "r,r")
5135            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5136          (not:SI
5137           (match_operand:SI 2 "s_register_operand" "r,r"))
5138          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5139    (clobber (reg 24))]
5140   ""
5141   "#"
5142 [(set_attr "conds" "clob")
5143  (set_attr "length" "8,12")])
5145 (define_insn "*if_not_move"
5146   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5147         (if_then_else:SI
5148          (match_operator 4 "comparison_operator"
5149           [(match_operand 3 "cc_register" "") (const_int 0)])
5150          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5151          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5152   ""
5153   "@
5154    mvn%d4\\t%0, %2
5155    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
5156    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
5157 [(set_attr "conds" "use")
5158  (set_attr "length" "4,8,8")])
5160 (define_insn "*ifcompare_shift_move"
5161   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5162         (if_then_else:SI
5163          (match_operator 6 "comparison_operator"
5164           [(match_operand:SI 4 "s_register_operand" "r,r")
5165            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5166          (match_operator:SI 7 "shift_operator"
5167           [(match_operand:SI 2 "s_register_operand" "r,r")
5168            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
5169          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5170    (clobber (reg 24))]
5171   ""
5172   "#"
5173 [(set_attr "conds" "clob")
5174  (set_attr "length" "8,12")])
5176 (define_insn "*if_shift_move"
5177   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5178         (if_then_else:SI
5179          (match_operator 5 "comparison_operator"
5180           [(match_operand 6 "cc_register" "") (const_int 0)])
5181          (match_operator:SI 4 "shift_operator"
5182           [(match_operand:SI 2 "s_register_operand" "r,r,r")
5183            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
5184          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5185   ""
5186   "@
5187    mov%d5\\t%0, %2%S4
5188    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
5189    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
5190 [(set_attr "conds" "use")
5191  (set_attr "length" "4,8,8")])
5193 (define_insn "*ifcompare_move_shift"
5194   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5195         (if_then_else:SI
5196          (match_operator 6 "comparison_operator"
5197           [(match_operand:SI 4 "s_register_operand" "r,r")
5198            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5199          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5200          (match_operator:SI 7 "shift_operator"
5201           [(match_operand:SI 2 "s_register_operand" "r,r")
5202            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5203    (clobber (reg 24))]
5204   ""
5205   "#"
5206 [(set_attr "conds" "clob")
5207  (set_attr "length" "8,12")])
5209 (define_insn "*if_move_shift"
5210   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5211         (if_then_else:SI
5212          (match_operator 5 "comparison_operator"
5213           [(match_operand 6 "cc_register" "") (const_int 0)])
5214          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5215          (match_operator:SI 4 "shift_operator"
5216           [(match_operand:SI 2 "s_register_operand" "r,r,r")
5217            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5218   ""
5219   "@
5220    mov%D5\\t%0, %2%S4
5221    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5222    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5223 [(set_attr "conds" "use")
5224  (set_attr "length" "4,8,8")])
5226 (define_insn "*ifcompare_shift_shift"
5227   [(set (match_operand:SI 0 "s_register_operand" "=r")
5228         (if_then_else:SI
5229          (match_operator 7 "comparison_operator"
5230           [(match_operand:SI 5 "s_register_operand" "r")
5231            (match_operand:SI 6 "arm_add_operand" "rIL")])
5232          (match_operator:SI 8 "shift_operator"
5233           [(match_operand:SI 1 "s_register_operand" "r")
5234            (match_operand:SI 2 "arm_rhs_operand" "rM")])
5235          (match_operator:SI 9 "shift_operator"
5236           [(match_operand:SI 3 "s_register_operand" "r")
5237            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5238    (clobber (reg 24))]
5239   ""
5240   "#"
5241 [(set_attr "conds" "clob")
5242  (set_attr "length" "12")])
5244 (define_insn "*if_shift_shift"
5245   [(set (match_operand:SI 0 "s_register_operand" "=r")
5246         (if_then_else:SI
5247          (match_operator 5 "comparison_operator"
5248           [(match_operand 8 "cc_register" "") (const_int 0)])
5249          (match_operator:SI 6 "shift_operator"
5250           [(match_operand:SI 1 "s_register_operand" "r")
5251            (match_operand:SI 2 "arm_rhs_operand" "rM")])
5252          (match_operator:SI 7 "shift_operator"
5253           [(match_operand:SI 3 "s_register_operand" "r")
5254            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5255   ""
5256   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5257 [(set_attr "conds" "use")
5258  (set_attr "length" "8")])
5260 (define_insn "*ifcompare_not_arith"
5261   [(set (match_operand:SI 0 "s_register_operand" "=r")
5262         (if_then_else:SI
5263          (match_operator 6 "comparison_operator"
5264           [(match_operand:SI 4 "s_register_operand" "r")
5265            (match_operand:SI 5 "arm_add_operand" "rIL")])
5266          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5267          (match_operator:SI 7 "shiftable_operator"
5268           [(match_operand:SI 2 "s_register_operand" "r")
5269            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5270    (clobber (reg 24))]
5271   ""
5272   "#"
5273 [(set_attr "conds" "clob")
5274  (set_attr "length" "12")])
5276 (define_insn "*if_not_arith"
5277   [(set (match_operand:SI 0 "s_register_operand" "=r")
5278         (if_then_else:SI
5279          (match_operator 5 "comparison_operator"
5280           [(match_operand 4 "cc_register" "") (const_int 0)])
5281          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5282          (match_operator:SI 6 "shiftable_operator"
5283           [(match_operand:SI 2 "s_register_operand" "r")
5284            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5285   ""
5286   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5287 [(set_attr "conds" "use")
5288  (set_attr "length" "8")])
5290 (define_insn "*ifcompare_arith_not"
5291   [(set (match_operand:SI 0 "s_register_operand" "=r")
5292         (if_then_else:SI
5293          (match_operator 6 "comparison_operator"
5294           [(match_operand:SI 4 "s_register_operand" "r")
5295            (match_operand:SI 5 "arm_add_operand" "rIL")])
5296          (match_operator:SI 7 "shiftable_operator"
5297           [(match_operand:SI 2 "s_register_operand" "r")
5298            (match_operand:SI 3 "arm_rhs_operand" "rI")])
5299          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5300    (clobber (reg 24))]
5301   ""
5302   "#"
5303 [(set_attr "conds" "clob")
5304  (set_attr "length" "12")])
5306 (define_insn "*if_arith_not"
5307   [(set (match_operand:SI 0 "s_register_operand" "=r")
5308         (if_then_else:SI
5309          (match_operator 5 "comparison_operator"
5310           [(match_operand 4 "cc_register" "") (const_int 0)])
5311          (match_operator:SI 6 "shiftable_operator"
5312           [(match_operand:SI 2 "s_register_operand" "r")
5313            (match_operand:SI 3 "arm_rhs_operand" "rI")])
5314          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5315   ""
5316   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5317 [(set_attr "conds" "use")
5318  (set_attr "length" "8")])
5320 (define_insn "*ifcompare_neg_move"
5321   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5322         (if_then_else:SI
5323          (match_operator 5 "comparison_operator"
5324           [(match_operand:SI 3 "s_register_operand" "r,r")
5325            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5326          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5327          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5328    (clobber (reg:CC 24))]
5329   ""
5330   "#"
5331 [(set_attr "conds" "clob")
5332  (set_attr "length" "8,12")])
5334 (define_insn "*if_neg_move"
5335   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5336         (if_then_else:SI
5337          (match_operator 4 "comparison_operator"
5338           [(match_operand 3 "cc_register" "") (const_int 0)])
5339          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5340          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5341   ""
5342   "@
5343    rsb%d4\\t%0, %2, #0
5344    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5345    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5346 [(set_attr "conds" "use")
5347  (set_attr "length" "4,8,8")])
5349 (define_insn "*ifcompare_move_neg"
5350   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5351         (if_then_else:SI
5352          (match_operator 5 "comparison_operator"
5353           [(match_operand:SI 3 "s_register_operand" "r,r")
5354            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5355          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5356          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5357    (clobber (reg:CC 24))]
5358   ""
5359   "#"
5360 [(set_attr "conds" "clob")
5361  (set_attr "length" "8,12")])
5363 (define_insn "*if_move_neg"
5364   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5365         (if_then_else:SI
5366          (match_operator 4 "comparison_operator"
5367           [(match_operand 3 "cc_register" "") (const_int 0)])
5368          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5369          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5370   ""
5371   "@
5372    rsb%D4\\t%0, %2, #0
5373    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5374    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5375 [(set_attr "conds" "use")
5376  (set_attr "length" "4,8,8")])
5378 (define_insn "*arith_adjacentmem"
5379   [(set (match_operand:SI 0 "s_register_operand" "=r")
5380         (match_operator:SI 1 "shiftable_operator"
5381          [(match_operand:SI 2 "memory_operand" "m")
5382           (match_operand:SI 3 "memory_operand" "m")]))
5383    (clobber (match_scratch:SI 4 "=r"))]
5384   "adjacent_mem_locations (operands[2], operands[3])"
5385   "*
5387   rtx ldm[3];
5388   rtx arith[4];
5389   int val1 = 0, val2 = 0;
5391   if (REGNO (operands[0]) > REGNO (operands[4]))
5392     {
5393       ldm[1] = operands[4];
5394       ldm[2] = operands[0];
5395     }
5396   else
5397     {
5398       ldm[1] = operands[0];
5399       ldm[2] = operands[4];
5400     }
5401   if (GET_CODE (XEXP (operands[2], 0)) != REG)
5402     val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5403   if (GET_CODE (XEXP (operands[3], 0)) != REG)
5404     val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5405   arith[0] = operands[0];
5406   arith[3] = operands[1];
5407   if (val1 < val2)
5408     {
5409       arith[1] = ldm[1];
5410       arith[2] = ldm[2];
5411     }
5412   else
5413     {
5414       arith[1] = ldm[2];
5415       arith[2] = ldm[1];
5416     }
5417   if (val1 && val2)
5418     {
5419       rtx ops[3];
5420       ldm[0] = ops[0] = operands[4];
5421       ops[1] = XEXP (XEXP (operands[2], 0), 0);
5422       ops[2] = XEXP (XEXP (operands[2], 0), 1);
5423       output_add_immediate (ops);
5424       if (val1 < val2)
5425         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5426       else
5427         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5428     }
5429   else if (val1)
5430     {
5431       ldm[0] = XEXP (operands[3], 0);
5432       if (val1 < val2)
5433         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5434       else
5435         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5436     }
5437   else
5438     {
5439       ldm[0] = XEXP (operands[2], 0);
5440       if (val1 < val2)
5441         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5442       else
5443         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5444     }
5445   output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5446   return \"\";
5449 [(set_attr "length" "12")
5450  (set_attr "type" "load")])
5452 ;; the arm can support extended pre-inc instructions
5454 ;; In all these cases, we use operands 0 and 1 for the register being
5455 ;; incremented because those are the operands that local-alloc will
5456 ;; tie and these are the pair most likely to be tieable (and the ones
5457 ;; that will benefit the most).
5459 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5460 ;; elimination will cause too many headaches.
5462 (define_insn "*strqi_preinc"
5463   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5464                          (match_operand:SI 2 "index_operand" "rJ")))
5465         (match_operand:QI 3 "s_register_operand" "r"))
5466    (set (match_operand:SI 0 "s_register_operand" "=r")
5467         (plus:SI (match_dup 1) (match_dup 2)))]
5468   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5469    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5470    && (GET_CODE (operands[2]) != REG
5471        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5472   "str%?b\\t%3, [%0, %2]!"
5473 [(set_attr "type" "store1")])
5475 (define_insn "*strqi_predec"
5476   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5477                           (match_operand:SI 2 "s_register_operand" "r")))
5478         (match_operand:QI 3 "s_register_operand" "r"))
5479    (set (match_operand:SI 0 "s_register_operand" "=r")
5480         (minus:SI (match_dup 1) (match_dup 2)))]
5481   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5482    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5483    && (GET_CODE (operands[2]) != REG
5484        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5485   "str%?b\\t%3, [%0, -%2]!"
5486 [(set_attr "type" "store1")])
5488 (define_insn "*loadqi_preinc"
5489   [(set (match_operand:QI 3 "s_register_operand" "=r")
5490         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5491                          (match_operand:SI 2 "index_operand" "rJ"))))
5492    (set (match_operand:SI 0 "s_register_operand" "=r")
5493         (plus:SI (match_dup 1) (match_dup 2)))]
5494   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5495    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5496    && (GET_CODE (operands[2]) != REG
5497        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5498   "ldr%?b\\t%3, [%0, %2]!"
5499 [(set_attr "type" "load")])
5501 (define_insn "*loadqi_predec"
5502   [(set (match_operand:QI 3 "s_register_operand" "=r")
5503         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5504                           (match_operand:SI 2 "s_register_operand" "r"))))
5505    (set (match_operand:SI 0 "s_register_operand" "=r")
5506         (minus:SI (match_dup 1) (match_dup 2)))]
5507   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5508    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5509    && (GET_CODE (operands[2]) != REG
5510        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5511   "ldr%?b\\t%3, [%0, -%2]!"
5512 [(set_attr "type" "load")])
5514 (define_insn "*loadqisi_preinc"
5515   [(set (match_operand:SI 3 "s_register_operand" "=r")
5516         (zero_extend:SI
5517          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5518                           (match_operand:SI 2 "index_operand" "rJ")))))
5519    (set (match_operand:SI 0 "s_register_operand" "=r")
5520         (plus:SI (match_dup 1) (match_dup 2)))]
5521   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5522    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5523    && (GET_CODE (operands[2]) != REG
5524        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5525   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5526 [(set_attr "type" "load")])
5528 (define_insn "*loadqisi_predec"
5529   [(set (match_operand:SI 3 "s_register_operand" "=r")
5530         (zero_extend:SI
5531          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5532                            (match_operand:SI 2 "s_register_operand" "r")))))
5533    (set (match_operand:SI 0 "s_register_operand" "=r")
5534         (minus:SI (match_dup 1) (match_dup 2)))]
5535   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5536    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5537    && (GET_CODE (operands[2]) != REG
5538        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5539   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5540 [(set_attr "type" "load")])
5542 (define_insn "*strsi_preinc"
5543   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5544                          (match_operand:SI 2 "index_operand" "rJ")))
5545         (match_operand:SI 3 "s_register_operand" "r"))
5546    (set (match_operand:SI 0 "s_register_operand" "=r")
5547         (plus:SI (match_dup 1) (match_dup 2)))]
5548   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5549    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5550    && (GET_CODE (operands[2]) != REG
5551        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5552   "str%?\\t%3, [%0, %2]!"
5553 [(set_attr "type" "store1")])
5555 (define_insn "*strqi_predec"
5556   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5557                           (match_operand:SI 2 "s_register_operand" "r")))
5558         (match_operand:SI 3 "s_register_operand" "r"))
5559    (set (match_operand:SI 0 "s_register_operand" "=r")
5560         (minus:SI (match_dup 1) (match_dup 2)))]
5561   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5562    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5563    && (GET_CODE (operands[2]) != REG
5564        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5565   "str%?\\t%3, [%0, -%2]!"
5566 [(set_attr "type" "store1")])
5568 (define_insn "*loadsi_preinc"
5569   [(set (match_operand:SI 3 "s_register_operand" "=r")
5570         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5571                          (match_operand:SI 2 "index_operand" "rJ"))))
5572    (set (match_operand:SI 0 "s_register_operand" "=r")
5573         (plus:SI (match_dup 1) (match_dup 2)))]
5574   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5575    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5576    && (GET_CODE (operands[2]) != REG
5577        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5578   "ldr%?\\t%3, [%0, %2]!"
5579 [(set_attr "type" "load")])
5581 (define_insn "*loadsi_predec"
5582   [(set (match_operand:SI 3 "s_register_operand" "=r")
5583         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5584                           (match_operand:SI 2 "s_register_operand" "r"))))
5585    (set (match_operand:SI 0 "s_register_operand" "=r")
5586         (minus:SI (match_dup 1) (match_dup 2)))]
5587   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5588    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5589    && (GET_CODE (operands[2]) != REG
5590        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5591   "ldr%?\\t%3, [%0, -%2]!"
5592 [(set_attr "type" "load")])
5594 (define_insn "*loadhi_preinc"
5595   [(set (match_operand:HI 3 "s_register_operand" "=r")
5596         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5597                          (match_operand:SI 2 "index_operand" "rJ"))))
5598    (set (match_operand:SI 0 "s_register_operand" "=r")
5599         (plus:SI (match_dup 1) (match_dup 2)))]
5600   "(! BYTES_BIG_ENDIAN)
5601    && ! TARGET_SHORT_BY_BYTES
5602    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5603    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5604    && (GET_CODE (operands[2]) != REG
5605        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5606   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5607 [(set_attr "type" "load")])
5609 (define_insn "*loadhi_predec"
5610   [(set (match_operand:HI 3 "s_register_operand" "=r")
5611         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5612                           (match_operand:SI 2 "s_register_operand" "r"))))
5613    (set (match_operand:SI 0 "s_register_operand" "=r")
5614         (minus:SI (match_dup 1) (match_dup 2)))]
5615   "(!BYTES_BIG_ENDIAN)
5616    && ! TARGET_SHORT_BY_BYTES
5617    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5618    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5619    && (GET_CODE (operands[2]) != REG
5620        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5621   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5622 [(set_attr "type" "load")])
5624 (define_insn "*strqi_shiftpreinc"
5625   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5626                           [(match_operand:SI 3 "s_register_operand" "r")
5627                            (match_operand:SI 4 "const_shift_operand" "n")])
5628                          (match_operand:SI 1 "s_register_operand" "0")))
5629         (match_operand:QI 5 "s_register_operand" "r"))
5630    (set (match_operand:SI 0 "s_register_operand" "=r")
5631         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5632                  (match_dup 1)))]
5633   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5634    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5635    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5636   "str%?b\\t%5, [%0, %3%S2]!"
5637 [(set_attr "type" "store1")])
5639 (define_insn "*strqi_shiftpredec"
5640   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5641                           (match_operator:SI 2 "shift_operator"
5642                            [(match_operand:SI 3 "s_register_operand" "r")
5643                             (match_operand:SI 4 "const_shift_operand" "n")])))
5644         (match_operand:QI 5 "s_register_operand" "r"))
5645    (set (match_operand:SI 0 "s_register_operand" "=r")
5646         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5647                                                  (match_dup 4)])))]
5648   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5649    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5650    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5651   "str%?b\\t%5, [%0, -%3%S2]!"
5652 [(set_attr "type" "store1")])
5654 (define_insn "*loadqi_shiftpreinc"
5655   [(set (match_operand:QI 5 "s_register_operand" "=r")
5656         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5657                           [(match_operand:SI 3 "s_register_operand" "r")
5658                            (match_operand:SI 4 "const_shift_operand" "n")])
5659                          (match_operand:SI 1 "s_register_operand" "0"))))
5660    (set (match_operand:SI 0 "s_register_operand" "=r")
5661         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5662                  (match_dup 1)))]
5663   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5664    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5665    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5666   "ldr%?b\\t%5, [%0, %3%S2]!"
5667 [(set_attr "type" "load")])
5669 (define_insn "*loadqi_shiftpredec"
5670   [(set (match_operand:QI 5 "s_register_operand" "=r")
5671         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5672                           (match_operator:SI 2 "shift_operator"
5673                            [(match_operand:SI 3 "s_register_operand" "r")
5674                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5675    (set (match_operand:SI 0 "s_register_operand" "=r")
5676         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5677                                                  (match_dup 4)])))]
5678   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5679    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5680    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5681   "ldr%?b\\t%5, [%0, -%3%S2]!"
5682 [(set_attr "type" "load")])
5684 (define_insn "*strsi_shiftpreinc"
5685   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5686                           [(match_operand:SI 3 "s_register_operand" "r")
5687                            (match_operand:SI 4 "const_shift_operand" "n")])
5688                          (match_operand:SI 1 "s_register_operand" "0")))
5689         (match_operand:SI 5 "s_register_operand" "r"))
5690    (set (match_operand:SI 0 "s_register_operand" "=r")
5691         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5692                  (match_dup 1)))]
5693   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5694    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5695    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5696   "str%?\\t%5, [%0, %3%S2]!"
5697 [(set_attr "type" "store1")])
5699 (define_insn "*strsi_shiftpredec"
5700   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5701                           (match_operator:SI 2 "shift_operator"
5702                            [(match_operand:SI 3 "s_register_operand" "r")
5703                             (match_operand:SI 4 "const_shift_operand" "n")])))
5704         (match_operand:SI 5 "s_register_operand" "r"))
5705    (set (match_operand:SI 0 "s_register_operand" "=r")
5706         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5707                                                  (match_dup 4)])))]
5708   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5709    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5710    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5711   "str%?\\t%5, [%0, -%3%S2]!"
5712 [(set_attr "type" "store1")])
5714 (define_insn "*loadqi_shiftpreinc"
5715   [(set (match_operand:SI 5 "s_register_operand" "=r")
5716         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5717                           [(match_operand:SI 3 "s_register_operand" "r")
5718                            (match_operand:SI 4 "const_shift_operand" "n")])
5719                          (match_operand:SI 1 "s_register_operand" "0"))))
5720    (set (match_operand:SI 0 "s_register_operand" "=r")
5721         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5722                  (match_dup 1)))]
5723   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5724    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5725    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5726   "ldr%?\\t%5, [%0, %3%S2]!"
5727 [(set_attr "type" "load")])
5729 (define_insn "*loadqi_shiftpredec"
5730   [(set (match_operand:SI 5 "s_register_operand" "=r")
5731         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5732                           (match_operator:SI 2 "shift_operator"
5733                            [(match_operand:SI 3 "s_register_operand" "r")
5734                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5735    (set (match_operand:SI 0 "s_register_operand" "=r")
5736         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5737                                                  (match_dup 4)])))]
5738   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5739    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5740    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5741   "ldr%?\\t%5, [%0, -%3%S2]!"
5742 [(set_attr "type" "load")])
5744 (define_insn "*loadhi_shiftpreinc"
5745   [(set (match_operand:HI 5 "s_register_operand" "=r")
5746         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5747                           [(match_operand:SI 3 "s_register_operand" "r")
5748                            (match_operand:SI 4 "const_shift_operand" "n")])
5749                          (match_operand:SI 1 "s_register_operand" "0"))))
5750    (set (match_operand:SI 0 "s_register_operand" "=r")
5751         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5752                  (match_dup 1)))]
5753   "(! BYTES_BIG_ENDIAN)
5754    && ! TARGET_SHORT_BY_BYTES
5755    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5756    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5757    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5758   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5759 [(set_attr "type" "load")])
5761 (define_insn "*loadhi_shiftpredec"
5762   [(set (match_operand:HI 5 "s_register_operand" "=r")
5763         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5764                           (match_operator:SI 2 "shift_operator"
5765                            [(match_operand:SI 3 "s_register_operand" "r")
5766                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5767    (set (match_operand:SI 0 "s_register_operand" "=r")
5768         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5769                                                  (match_dup 4)])))]
5770   "(! BYTES_BIG_ENDIAN)
5771    && ! TARGET_SHORT_BY_BYTES
5772    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5773    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5774    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5775   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5776 [(set_attr "type" "load")])
5778 ; It can also support extended post-inc expressions, but combine doesn't
5779 ; try these....
5780 ; It doesn't seem worth adding peepholes for anything but the most common
5781 ; cases since, unlike combine, the increment must immediately follow the load
5782 ; for this pattern to match.
5783 ; When loading we must watch to see that the base register isn't trampled by
5784 ; the load.  In such cases this isn't a post-inc expression.
5786 (define_peephole
5787   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5788         (match_operand:QI 2 "s_register_operand" "r"))
5789    (set (match_dup 0)
5790         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5791   ""
5792   "str%?b\\t%2, [%0], %1")
5794 (define_peephole
5795   [(set (match_operand:QI 0 "s_register_operand" "=r")
5796         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5797    (set (match_dup 1)
5798         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5799   "REGNO(operands[0]) != REGNO(operands[1])
5800    && (GET_CODE (operands[2]) != REG
5801        || REGNO(operands[0]) != REGNO (operands[2]))"
5802   "ldr%?b\\t%0, [%1], %2")
5804 (define_peephole
5805   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5806         (match_operand:SI 2 "s_register_operand" "r"))
5807    (set (match_dup 0)
5808         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5809   ""
5810   "str%?\\t%2, [%0], %1")
5812 (define_peephole
5813   [(set (match_operand:HI 0 "s_register_operand" "=r")
5814         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5815    (set (match_dup 1)
5816         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5817   "(! BYTES_BIG_ENDIAN)
5818    && ! TARGET_SHORT_BY_BYTES
5819    && REGNO(operands[0]) != REGNO(operands[1])
5820    && (GET_CODE (operands[2]) != REG
5821        || REGNO(operands[0]) != REGNO (operands[2]))"
5822   "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5824 (define_peephole
5825   [(set (match_operand:SI 0 "s_register_operand" "=r")
5826         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5827    (set (match_dup 1)
5828         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5829   "REGNO(operands[0]) != REGNO(operands[1])
5830    && (GET_CODE (operands[2]) != REG
5831        || REGNO(operands[0]) != REGNO (operands[2]))"
5832   "ldr%?\\t%0, [%1], %2")
5834 (define_peephole
5835   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5836                          (match_operand:SI 1 "index_operand" "rJ")))
5837         (match_operand:QI 2 "s_register_operand" "r"))
5838    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5839   ""
5840   "str%?b\\t%2, [%0, %1]!")
5842 (define_peephole
5843   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5844                           [(match_operand:SI 0 "s_register_operand" "r")
5845                            (match_operand:SI 1 "const_int_operand" "n")])
5846                          (match_operand:SI 2 "s_register_operand" "+r")))
5847         (match_operand:QI 3 "s_register_operand" "r"))
5848    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5849                                (match_dup 2)))]
5850   ""
5851   "str%?b\\t%3, [%2, %0%S4]!")
5853 ; This pattern is never tried by combine, so do it as a peephole
5855 (define_peephole
5856   [(set (match_operand:SI 0 "s_register_operand" "=r")
5857         (match_operand:SI 1 "s_register_operand" "r"))
5858    (set (reg:CC 24)
5859         (compare:CC (match_dup 1) (const_int 0)))]
5860   ""
5861   "sub%?s\\t%0, %1, #0"
5862 [(set_attr "conds" "set")])
5864 ; Peepholes to spot possible load- and store-multiples.
5866 (define_peephole
5867   [(set (match_operand:SI 0 "s_register_operand" "=r")
5868         (match_operand:SI 4 "memory_operand" "m"))
5869    (set (match_operand:SI 1 "s_register_operand" "=r")
5870         (match_operand:SI 5 "memory_operand" "m"))
5871    (set (match_operand:SI 2 "s_register_operand" "=r")
5872         (match_operand:SI 6 "memory_operand" "m"))
5873    (set (match_operand:SI 3 "s_register_operand" "=r")
5874         (match_operand:SI 7 "memory_operand" "m"))]
5875   "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5876   "*
5877   return emit_ldm_seq (operands, 4);
5880 (define_peephole
5881   [(set (match_operand:SI 0 "s_register_operand" "=r")
5882         (match_operand:SI 3 "memory_operand" "m"))
5883    (set (match_operand:SI 1 "s_register_operand" "=r")
5884         (match_operand:SI 4 "memory_operand" "m"))
5885    (set (match_operand:SI 2 "s_register_operand" "=r")
5886         (match_operand:SI 5 "memory_operand" "m"))]
5887   "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5888   "*
5889   return emit_ldm_seq (operands, 3);
5892 (define_peephole
5893   [(set (match_operand:SI 0 "s_register_operand" "=r")
5894         (match_operand:SI 2 "memory_operand" "m"))
5895    (set (match_operand:SI 1 "s_register_operand" "=r")
5896         (match_operand:SI 3 "memory_operand" "m"))]
5897   "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5898   "*
5899   return emit_ldm_seq (operands, 2);
5902 (define_peephole
5903   [(set (match_operand:SI 4 "memory_operand" "=m")
5904         (match_operand:SI 0 "s_register_operand" "r"))
5905    (set (match_operand:SI 5 "memory_operand" "=m")
5906         (match_operand:SI 1 "s_register_operand" "r"))
5907    (set (match_operand:SI 6 "memory_operand" "=m")
5908         (match_operand:SI 2 "s_register_operand" "r"))
5909    (set (match_operand:SI 7 "memory_operand" "=m")
5910         (match_operand:SI 3 "s_register_operand" "r"))]
5911   "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5912   "*
5913   return emit_stm_seq (operands, 4);
5916 (define_peephole
5917   [(set (match_operand:SI 3 "memory_operand" "=m")
5918         (match_operand:SI 0 "s_register_operand" "r"))
5919    (set (match_operand:SI 4 "memory_operand" "=m")
5920         (match_operand:SI 1 "s_register_operand" "r"))
5921    (set (match_operand:SI 5 "memory_operand" "=m")
5922         (match_operand:SI 2 "s_register_operand" "r"))]
5923   "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5924   "*
5925   return emit_stm_seq (operands, 3);
5928 (define_peephole
5929   [(set (match_operand:SI 2 "memory_operand" "=m")
5930         (match_operand:SI 0 "s_register_operand" "r"))
5931    (set (match_operand:SI 3 "memory_operand" "=m")
5932         (match_operand:SI 1 "s_register_operand" "r"))]
5933   "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5934   "*
5935   return emit_stm_seq (operands, 2);
5938 ;; A call followed by return can be replaced by restoring the regs and
5939 ;; jumping to the subroutine, provided we aren't passing the address of
5940 ;; any of our local variables.  If we call alloca then this is unsafe
5941 ;; since restoring the frame frees the memory, which is not what we want.
5942 ;; Sometimes the return might have been targeted by the final prescan:
5943 ;; if so then emit a proper return insn as well.
5944 ;; Unfortunately, if the frame pointer is required, we don't know if the
5945 ;; current function has any implicit stack pointer adjustments that will 
5946 ;; be restored by the return: we can't therefore do a tail call.
5947 ;; Another unfortunate that we can't handle is if current_function_args_size
5948 ;; is non-zero: in this case elimination of the argument pointer assumed
5949 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5950 ;; calculations.
5952 (define_peephole
5953   [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5954                           (match_operand:SI 1 "general_operand" "g"))
5955                     (clobber (reg:SI 14))])
5956    (return)]
5957   "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN
5958     && !get_frame_size () && !current_function_calls_alloca
5959     && !frame_pointer_needed && !current_function_args_size)"
5960   "*
5962   extern rtx arm_target_insn;
5963   extern int arm_ccfsm_state;
5965   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5966   {
5967     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5968     output_return_instruction (NULL, TRUE, FALSE);
5969     arm_ccfsm_state = 0;
5970     arm_target_insn = NULL;
5971   }
5973   output_return_instruction (NULL, FALSE, FALSE);
5974   return \"b%?\\t%a0\";
5976 [(set_attr "type" "call")
5977  (set_attr "length" "8")])
5979 (define_peephole
5980   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5981                    (call (mem:SI (match_operand:SI 1 "" "X"))
5982                          (match_operand:SI 2 "general_operand" "g")))
5983               (clobber (reg:SI 14))])
5984    (return)]
5985   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5986     && !get_frame_size () && !current_function_calls_alloca
5987     && !frame_pointer_needed && !current_function_args_size)"
5988   "*
5990   extern rtx arm_target_insn;
5991   extern int arm_ccfsm_state;
5993   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5994   {
5995     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5996     output_return_instruction (NULL, TRUE, FALSE);
5997     arm_ccfsm_state = 0;
5998     arm_target_insn = NULL;
5999   }
6001   output_return_instruction (NULL, FALSE, FALSE);
6002   return \"b%?\\t%a1\";
6004 [(set_attr "type" "call")
6005  (set_attr "length" "8")])
6007 ;; As above but when this function is not void, we must be returning the
6008 ;; result of the called subroutine.
6010 (define_peephole
6011   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6012                    (call (mem:SI (match_operand:SI 1 "" "X"))
6013                          (match_operand:SI 2 "general_operand" "g")))
6014               (clobber (reg:SI 14))])
6015    (use (match_dup 0))
6016    (return)]
6017   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
6018     && !get_frame_size () && !current_function_calls_alloca
6019     && !frame_pointer_needed && !current_function_args_size)"
6020   "*
6022   extern rtx arm_target_insn;
6023   extern int arm_ccfsm_state;
6025   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6026   {
6027     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6028     output_return_instruction (NULL, TRUE, FALSE);
6029     arm_ccfsm_state = 0;
6030     arm_target_insn = NULL;
6031   }
6033   output_return_instruction (NULL, FALSE, FALSE);
6034   return \"b%?\\t%a1\";
6036 [(set_attr "type" "call")
6037  (set_attr "length" "8")])
6039 (define_split
6040   [(set (match_operand:SI 0 "s_register_operand" "")
6041         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
6042                        (const_int 0))
6043                 (neg:SI (match_operator:SI 2 "comparison_operator"
6044                          [(match_operand:SI 3 "s_register_operand" "")
6045                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
6046    (clobber (match_operand:SI 5 "s_register_operand" ""))]
6047   ""
6048   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
6049    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6050                               (match_dup 5)))]
6051   "")
6053 ;; This split can be used because CC_Z mode implies that the following
6054 ;; branch will be an equality, or an unsigned inequality, so the sign
6055 ;; extension is not needed.
6057 (define_split
6058   [(set (reg:CC_Z 24)
6059         (compare:CC_Z
6060          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
6061                     (const_int 24))
6062          (match_operand 1 "const_int_operand" "")))
6063    (clobber (match_scratch:SI 2 ""))]
6064   "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
6065    == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
6066   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
6067    (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
6068   "
6069   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
6072 (define_expand "prologue"
6073   [(clobber (const_int 0))]
6074   ""
6075   "
6076   arm_expand_prologue ();
6077   DONE;
6080 ;; This split is only used during output to reduce the number of patterns
6081 ;; that need assembler instructions adding to them.  We allowed the setting
6082 ;; of the conditions to be implicit during rtl generation so that
6083 ;; the conditional compare patterns would work.  However this conflicts to
6084 ;; some extent with the conditional data operations, so we have to split them
6085 ;; up again here.
6087 (define_split
6088   [(set (match_operand:SI 0 "s_register_operand" "")
6089         (if_then_else:SI (match_operator 1 "comparison_operator"
6090                           [(match_operand 2 "" "") (match_operand 3 "" "")])
6091                          (match_operand 4 "" "")
6092                          (match_operand 5 "" "")))
6093    (clobber (reg 24))]
6094   "reload_completed"
6095   [(set (match_dup 6) (match_dup 7))
6096    (set (match_dup 0) 
6097         (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
6098                          (match_dup 4)
6099                          (match_dup 5)))]
6100   "
6102   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
6103                                            operands[3]);
6105   operands[6] = gen_rtx (REG, mode, 24);
6106   operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
6111 ;; The next two patterns occur when an AND operation is followed by a
6112 ;; scc insn sequence 
6114 (define_insn "*sign_extract_onebit"
6115   [(set (match_operand:SI 0 "s_register_operand" "=r")
6116         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6117                          (const_int 1)
6118                          (match_operand:SI 2 "const_int_operand" "n")))]
6119   ""
6120   "*
6121   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6122   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6123   return \"mvnne\\t%0, #0\";
6125 [(set_attr "conds" "clob")
6126  (set_attr "length" "8")])
6128 (define_insn "*not_signextract_onebit"
6129   [(set (match_operand:SI 0 "s_register_operand" "=r")
6130         (not:SI
6131          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6132                           (const_int 1)
6133                           (match_operand:SI 2 "const_int_operand" "n"))))]
6134   ""
6135   "*
6136   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6137   output_asm_insn (\"tst\\t%1, %2\", operands);
6138   output_asm_insn (\"mvneq\\t%0, #0\", operands);
6139   return \"movne\\t%0, #0\";
6141 [(set_attr "conds" "clob")
6142  (set_attr "length" "12")])
6144 ;; Push multiple registers to the stack.  The first register is in the
6145 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
6146 ;; expressions.
6147 (define_insn "*push_multi"
6148   [(match_parallel 2 "multi_register_push"
6149     [(set (match_operand:BLK 0 "memory_operand" "=m")
6150           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
6151   ""
6152   "*
6154   char pattern[100];
6155   int i;
6156   extern int lr_save_eliminated;
6158   if (lr_save_eliminated)
6159     {
6160       if (XVECLEN (operands[2], 0) > 1)
6161         abort ();
6162       return \"\";
6163     }
6164   strcpy (pattern, \"stmfd\\t%m0!, {%1\");
6165   for (i = 1; i < XVECLEN (operands[2], 0); i++)
6166     {
6167       strcat (pattern, \", %|\");
6168       strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
6169                                               0))]);
6170     }
6171   strcat (pattern, \"}\");
6172   output_asm_insn (pattern, operands);
6173   return \"\";
6175 [(set_attr "type" "store4")])
6177 ;; Similarly for the floating point registers
6178 (define_insn "*push_fp_multi"
6179   [(match_parallel 2 "multi_register_push"
6180     [(set (match_operand:BLK 0 "memory_operand" "=m")
6181           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
6182   ""
6183   "*
6185   char pattern[100];
6186   int i;
6188   sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
6189   output_asm_insn (pattern, operands);
6190   return \"\";
6192 [(set_attr "type" "f_store")])
6194 ;; Special patterns for dealing with the constant pool
6196 (define_insn "consttable_4"
6197   [(unspec_volatile [(match_operand 0 "" "")] 2)]
6198   ""
6199   "*
6201   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6202     {
6203     case MODE_FLOAT:
6204     {
6205       union real_extract u;
6206       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6207       assemble_real (u.d, GET_MODE (operands[0]));
6208       break;
6209     }
6210     default:
6211       assemble_integer (operands[0], 4, 1);
6212       break;
6213     }
6214   return \"\";
6216 [(set_attr "length" "4")])
6218 (define_insn "consttable_8"
6219   [(unspec_volatile [(match_operand 0 "" "")] 3)]
6220   ""
6221   "*
6223   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6224     {
6225     case MODE_FLOAT:
6226     {
6227       union real_extract u;
6228       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6229       assemble_real (u.d, GET_MODE (operands[0]));
6230       break;
6231     }
6232     default:
6233       assemble_integer (operands[0], 8, 1);
6234       break;
6235     }
6236   return \"\";
6238 [(set_attr "length" "8")])
6240 (define_insn "consttable_end"
6241   [(unspec_volatile [(const_int 0)] 4)]
6242   ""
6243   "*
6244   /* Nothing to do (currently).  */
6245   return \"\";
6248 (define_insn "align_4"
6249   [(unspec_volatile [(const_int 0)] 5)]
6250   ""
6251   "*
6252   assemble_align (32);
6253   return \"\";