import of gcc-2.8
[official-gcc.git] / gcc / config / arm / arm.md
blob332ec35593b0e209f271b3e9627ac57d65fa03f5
1 ;;- Machine description for Advanced RISC Machines' ARM for GNU compiler
2 ;;  Copyright (C) 1991, 93, 94, 95, 96, 1997 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 (mem:QI (match_operand:HI 1 "" ""))))
2262    (set (match_dup 3)
2263         (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
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   "
2269   operands[0] = gen_lowpart (SImode, operands[0]);
2270   operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2271   operands[2] = gen_reg_rtx (SImode);
2272   operands[3] = gen_reg_rtx (SImode);
2273   operands[6] = gen_reg_rtx (SImode);
2275   if (BYTES_BIG_ENDIAN)
2276     {
2277       operands[4] = operands[2];
2278       operands[5] = operands[3];
2279     }
2280   else
2281     {
2282       operands[4] = operands[3];
2283       operands[5] = operands[2];
2284     }
2287 (define_insn "*extendhisi_insn"
2288   [(set (match_operand:SI 0 "s_register_operand" "=r")
2289         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2290   "arm_arch4"
2291   "ldr%?sh\\t%0, %1"
2292 [(set_attr "type" "load")])
2294 (define_split
2295   [(set (match_operand:SI 0 "s_register_operand" "")
2296         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2297    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2298   "! arm_arch4"
2299   [(set (match_dup 2) (match_dup 1))
2300    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2301   "
2303   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2304     FAIL;
2307 (define_split
2308   [(set (match_operand:SI 0 "s_register_operand" "")
2309         (match_operator:SI 3 "shiftable_operator"
2310          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2311           (match_operand:SI 4 "s_register_operand" "")]))
2312    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2313   "! arm_arch4"
2314   [(set (match_dup 2) (match_dup 1))
2315    (set (match_dup 0)
2316         (match_op_dup 3
2317          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2318   "
2320   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2321     FAIL;
2324 (define_expand "extendqihi2"
2325   [(set (match_dup 2)
2326         (ashift:SI (match_operand:QI 1 "general_operand" "")
2327                    (const_int 24)))
2328    (set (match_operand:HI 0 "s_register_operand" "")
2329         (ashiftrt:SI (match_dup 2)
2330                      (const_int 24)))]
2331   ""
2332   "
2334   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2335     {
2336       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2337                           gen_rtx (SIGN_EXTEND, HImode, operands[1])));
2338       DONE;
2339     }
2340   if (! s_register_operand (operands[1], QImode))
2341     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2342   operands[0] = gen_lowpart (SImode, operands[0]);
2343   operands[1] = gen_lowpart (SImode, operands[1]);
2344   operands[2] = gen_reg_rtx (SImode);
2347 (define_insn "*extendqihi_insn"
2348   [(set (match_operand:HI 0 "s_register_operand" "=r")
2349         (sign_extend:HI (match_operand:QI 1 "memory_operand" "o<>")))]
2350   "arm_arch4"
2351   "ldr%?sb\\t%0, %1"
2352 [(set_attr "type" "load")])
2354 (define_expand "extendqisi2"
2355   [(set (match_dup 2)
2356         (ashift:SI (match_operand:QI 1 "s_register_operand" "")
2357                    (const_int 24)))
2358    (set (match_operand:SI 0 "s_register_operand" "")
2359         (ashiftrt:SI (match_dup 2)
2360                      (const_int 24)))]
2361   ""
2362   "
2364   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2365     {
2366       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2367                           gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2368       DONE;
2369     }
2370   if (! s_register_operand (operands[1], QImode))
2371     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2372   operands[1] = gen_lowpart (SImode, operands[1]);
2373   operands[2] = gen_reg_rtx (SImode);
2376 (define_insn "*extendqisi_insn"
2377   [(set (match_operand:SI 0 "s_register_operand" "=r")
2378         (sign_extend:SI (match_operand:QI 1 "memory_operand" "o<>")))]
2379   "arm_arch4"
2380   "ldr%?sb\\t%0, %1"
2381 [(set_attr "type" "load")])
2383 (define_insn "extendsfdf2"
2384   [(set (match_operand:DF 0 "s_register_operand" "=f")
2385         (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2386   "TARGET_HARD_FLOAT"
2387   "mvf%?d\\t%0, %1"
2388 [(set_attr "type" "ffarith")])
2390 (define_insn "extendsfxf2"
2391   [(set (match_operand:XF 0 "s_register_operand" "=f")
2392         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2393   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2394   "mvf%?e\\t%0, %1"
2395 [(set_attr "type" "ffarith")])
2397 (define_insn "extenddfxf2"
2398   [(set (match_operand:XF 0 "s_register_operand" "=f")
2399         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2400   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2401   "mvf%?e\\t%0, %1"
2402 [(set_attr "type" "ffarith")])
2405 ;; Move insns (including loads and stores)
2407 ;; XXX Just some ideas about movti.
2408 ;; I don't think these are a good idea on the arm, there just aren't enough
2409 ;; registers
2410 ;;(define_expand "loadti"
2411 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
2412 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
2413 ;;  "" "")
2415 ;;(define_expand "storeti"
2416 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2417 ;;      (match_operand:TI 1 "s_register_operand" ""))]
2418 ;;  "" "")
2420 ;;(define_expand "movti"
2421 ;;  [(set (match_operand:TI 0 "general_operand" "")
2422 ;;      (match_operand:TI 1 "general_operand" ""))]
2423 ;;  ""
2424 ;;  "
2426 ;;  rtx insn;
2428 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2429 ;;    operands[1] = copy_to_reg (operands[1]);
2430 ;;  if (GET_CODE (operands[0]) == MEM)
2431 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2432 ;;  else if (GET_CODE (operands[1]) == MEM)
2433 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2434 ;;  else
2435 ;;    FAIL;
2437 ;;  emit_insn (insn);
2438 ;;  DONE;
2439 ;;}")
2441 ;; Recognise garbage generated above.
2443 ;;(define_insn ""
2444 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2445 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2446 ;;  ""
2447 ;;  "*
2448 ;;  {
2449 ;;    register mem = (which_alternative < 3);
2450 ;;    register char *template;
2452 ;;    operands[mem] = XEXP (operands[mem], 0);
2453 ;;    switch (which_alternative)
2454 ;;      {
2455 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2456 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
2457 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
2458 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
2459 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
2460 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
2461 ;;      }
2462 ;;    output_asm_insn (template, operands);
2463 ;;    return \"\";
2464 ;;  }")
2467 (define_insn "movdi"
2468   [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2469         (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2470   ""
2471   "*
2472   return (output_move_double (operands));
2474 [(set_attr "length" "8,8,8")
2475  (set_attr "type" "*,load,store2")])
2477 (define_expand "movsi"
2478   [(set (match_operand:SI 0 "general_operand" "")
2479         (match_operand:SI 1 "general_operand" ""))]
2480   ""
2481   "
2482   /* Everything except mem = const or mem = mem can be done easily */
2483   if (GET_CODE (operands[0]) == MEM)
2484     operands[1] = force_reg (SImode, operands[1]);
2485   if (GET_CODE (operands[1]) == CONST_INT
2486       && !(const_ok_for_arm (INTVAL (operands[1]))
2487            || const_ok_for_arm (~INTVAL (operands[1]))))
2488     {
2489       arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2490                           NULL_RTX,
2491                           (reload_in_progress || reload_completed ? 0
2492                            : preserve_subexpressions_p ()));
2493       DONE;
2494     }
2495   if (CONSTANT_P (operands[1]) && flag_pic)
2496     operands[1] = legitimize_pic_address (operands[1], SImode,
2497                                           ((reload_in_progress
2498                                             || reload_completed)
2499                                            ? operands[0] : 0));
2502 (define_insn "*movsi_insn"
2503   [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2504         (match_operand:SI 1 "general_operand"  "rI,K,mi,r"))]
2505   "register_operand (operands[0], SImode)
2506    || register_operand (operands[1], SImode)"
2507   "@
2508    mov%?\\t%0, %1
2509    mvn%?\\t%0, #%B1
2510    ldr%?\\t%0, %1
2511    str%?\\t%1, %0"
2512 [(set_attr "type" "*,*,load,store1")])
2514 (define_split
2515   [(set (match_operand:SI 0 "s_register_operand" "")
2516         (match_operand:SI 1 "const_int_operand" ""))]
2517   "! (const_ok_for_arm (INTVAL (operands[1]))
2518       || const_ok_for_arm (~INTVAL (operands[1])))"
2519   [(clobber (const_int 0))]
2520   "
2521   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2522                       NULL_RTX, 0);
2523   DONE;
2526 (define_expand "movaddr"
2527   [(set (match_operand:SI 0 "s_register_operand" "")
2528         (match_operand:DI 1 "address_operand" ""))]
2529   ""
2530   "")
2532 (define_insn "*movaddr_insn"
2533   [(set (match_operand:SI 0 "s_register_operand" "=r")
2534         (match_operand:DI 1 "address_operand" "p"))]
2535   "reload_completed
2536    && (GET_CODE (operands[1]) == LABEL_REF
2537        || (GET_CODE (operands[1]) == CONST
2538            && GET_CODE (XEXP (operands[1], 0)) == PLUS
2539            && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2540            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2541   "adr%?\\t%0, %a1")
2543 /* When generating pic, we need to load the symbol offset into a register.
2544    So that the optimizer does not confuse this with a normal symbol load
2545    we use an unspec.  The offset will be loaded from a constant pool entry,
2546    since that is the only type of relocation we can use.  */
2548 (define_insn "pic_load_addr"
2549   [(set (match_operand:SI 0 "s_register_operand" "=r")
2550         (unspec:SI [(match_operand 1 "" "")] 3))]
2551   "flag_pic"
2552   "ldr%?\\t%0, %a1"
2553  [(set_attr "type" "load")])
2555 ;; This variant is used for AOF assembly, since it needs to mention the
2556 ;; pic register in the rtl.
2557 (define_expand "pic_load_addr_based"
2558   [(set (match_operand:SI 0 "s_register_operand" "=r")
2559         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
2560   "flag_pic"
2561   "operands[2] = pic_offset_table_rtx;")
2563 (define_insn "*pic_load_addr_based_insn"
2564   [(set (match_operand:SI 0 "s_register_operand" "=r")
2565         (unspec:SI [(match_operand 1 "" "")
2566                     (match_operand 2 "s_register_operand" "r")] 3))]
2567   "flag_pic && operands[2] == pic_offset_table_rtx"
2568   "*
2569 #ifdef AOF_ASSEMBLER
2570   operands[1] = aof_pic_entry (operands[1]);
2571 #endif
2572   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
2573   return \"\";
2574 " [(set_attr "type" "load")])
2576 (define_insn "pic_add_dot_plus_eight"
2577   [(set (pc) (label_ref (match_operand 0 "" "")))
2578    (set (match_operand 1 "register_operand" "+r")
2579         (plus:SI (match_dup 1) (const (plus:SI (pc) (const_int 8)))))]
2580   "flag_pic"
2581   "add%?\\t%1, %|pc, %1")
2583 ;; If copying one reg to another we can set the condition codes according to
2584 ;; its value.  Such a move is common after a return from subroutine and the
2585 ;; result is being tested against zero.
2587 (define_insn "*movsi_compare0"
2588   [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
2589                                 (const_int 0)))
2590    (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2591   ""
2592   "@
2593    cmp%?\\t%0, #0
2594    sub%?s\\t%0, %1, #0"
2595 [(set_attr "conds" "set")])
2597 ;; Subroutine to store a half word from a register into memory.
2598 ;; Operand 0 is the source register (HImode)
2599 ;; Operand 1 is the destination address in a register (SImode)
2601 ;; In both this routine and the next, we must be careful not to spill
2602 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2603 ;; can generate unrecognizable rtl.
2605 (define_expand "storehi"
2606   [;; store the low byte
2607    (set (match_operand 1 "" "") (match_dup 3))
2608    ;; extract the high byte
2609    (set (match_dup 2)
2610         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2611    ;; store the high byte
2612    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
2613   ""
2614   "
2616   rtx addr = XEXP (operands[1], 0);
2617   enum rtx_code code = GET_CODE (addr);
2619   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2620       || code == MINUS)
2621     addr = force_reg (SImode, addr);
2623   operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2624   operands[1] = change_address (operands[1], QImode, NULL_RTX);
2625   operands[3] = gen_lowpart (QImode, operands[0]);
2626   operands[0] = gen_lowpart (SImode, operands[0]);
2627   operands[2] = gen_reg_rtx (SImode); 
2631 (define_expand "storehi_bigend"
2632   [(set (match_dup 4) (match_dup 3))
2633    (set (match_dup 2)
2634         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2635    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
2636   ""
2637   "
2639   rtx addr = XEXP (operands[1], 0);
2640   enum rtx_code code = GET_CODE (addr);
2642   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2643       || code == MINUS)
2644     addr = force_reg (SImode, addr);
2646   operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2647   operands[1] = change_address (operands[1], QImode, NULL_RTX);
2648   operands[3] = gen_lowpart (QImode, operands[0]);
2649   operands[0] = gen_lowpart (SImode, operands[0]);
2650   operands[2] = gen_reg_rtx (SImode);
2654 ;; Subroutine to store a half word integer constant into memory.
2655 (define_expand "storeinthi"
2656   [(set (match_operand 0 "" "")
2657         (subreg:QI (match_operand 1 "" "") 0))
2658    (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
2659   ""
2660   "
2662   HOST_WIDE_INT value = INTVAL (operands[1]);
2663   rtx addr = XEXP (operands[0], 0);
2664   enum rtx_code code = GET_CODE (addr);
2666   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2667       || code == MINUS)
2668     addr = force_reg (SImode, addr);
2670   operands[1] = gen_reg_rtx (SImode);
2671   if (BYTES_BIG_ENDIAN)
2672     {
2673       emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2674       if ((value & 255) == ((value >> 8) & 255))
2675         operands[2] = operands[1];
2676       else
2677         {
2678           operands[2] = gen_reg_rtx (SImode);
2679           emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2680         }
2681     }
2682   else
2683     {
2684       emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2685       if ((value & 255) == ((value >> 8) & 255))
2686         operands[2] = operands[1];
2687       else
2688         {
2689           operands[2] = gen_reg_rtx (SImode);
2690           emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2691         }
2692     }
2694   operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
2695   operands[0] = change_address (operands[0], QImode, NULL_RTX);
2699 (define_expand "storehi_single_op"
2700   [(set (match_operand:HI 0 "memory_operand" "")
2701         (match_operand:HI 1 "general_operand" ""))]
2702   "arm_arch4"
2703   "
2704   if (! s_register_operand (operands[1], HImode))
2705     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2708 (define_expand "movhi"
2709   [(set (match_operand:HI 0 "general_operand" "")
2710         (match_operand:HI 1 "general_operand" ""))]
2711   ""
2712   "
2714   rtx insn;
2716   if (! (reload_in_progress || reload_completed))
2717     {
2718       if (GET_CODE (operands[0]) == MEM)
2719         {
2720           if (arm_arch4)
2721             {
2722               emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2723               DONE;
2724             }
2725           if (GET_CODE (operands[1]) == CONST_INT)
2726             emit_insn (gen_storeinthi (operands[0], operands[1]));
2727           else
2728             {
2729               if (GET_CODE (operands[1]) == MEM)
2730                 operands[1] = force_reg (HImode, operands[1]);
2731               if (BYTES_BIG_ENDIAN)
2732                 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
2733               else
2734                 emit_insn (gen_storehi (operands[1], operands[0]));
2735             }
2736           DONE;
2737         }
2738       /* Sign extend a constant, and keep it in an SImode reg.  */
2739       else if (GET_CODE (operands[1]) == CONST_INT)
2740         {
2741           rtx reg = gen_reg_rtx (SImode);
2742           HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2744           /* If the constant is already valid, leave it alone.  */
2745           if (! const_ok_for_arm (val))
2746             {
2747               /* If setting all the top bits will make the constant 
2748                  loadable in a single instruction, then set them.  
2749                  Otherwise, sign extend the number.  */
2751               if (const_ok_for_arm (~ (val | ~0xffff)))
2752                 val |= ~0xffff;
2753               else if (val & 0x8000)
2754                 val |= ~0xffff;
2755             }
2757           emit_insn (gen_movsi (reg, GEN_INT (val)));
2758           operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
2759         }
2760       else if (! arm_arch4)
2761         {
2762           if (GET_CODE (operands[1]) == MEM)
2763             {
2764               if (TARGET_SHORT_BY_BYTES)
2765                 {
2766                   rtx base;
2767                   rtx offset = const0_rtx;
2768                   rtx reg = gen_reg_rtx (SImode);
2770                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2771                        || (GET_CODE (base) == PLUS
2772                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2773                            && GET_CODE (base = XEXP (base, 0)) == REG))
2774                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2775                     {
2776                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~2;
2778                       emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode,
2779                                            plus_constant (base, new_offset))));
2780                       if (((INTVAL (offset) & 2) != 0)
2781                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
2782                         {
2783                           rtx reg2 = gen_reg_rtx (SImode);
2785                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
2786                           reg = reg2;
2787                         }
2788                     }
2789                   else
2790                     emit_insn (gen_movhi_bytes (reg, operands[1]));
2792                   operands[1] = gen_lowpart (HImode, reg);
2793                 }
2794               else if (BYTES_BIG_ENDIAN)
2795                 {
2796                   rtx base;
2797                   rtx offset = const0_rtx;
2799                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2800                        || (GET_CODE (base) == PLUS
2801                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2802                            && GET_CODE (base = XEXP (base, 0)) == REG))
2803                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2804                     {
2805                       rtx reg = gen_reg_rtx (SImode);
2806                       rtx new_mem;
2808                       if ((INTVAL (offset) & 2) == 2)
2809                         {
2810                           HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
2811                           new_mem = gen_rtx (MEM, SImode,
2812                                              plus_constant (base, new_offset));
2814                           emit_insn (gen_movsi (reg, new_mem));
2815                         }
2816                       else
2817                         {
2818                           new_mem = gen_rtx (MEM, SImode,
2819                                              XEXP (operands[1], 0));
2820                           emit_insn (gen_rotated_loadsi (reg, new_mem));
2821                         }
2823                       operands[1] = gen_lowpart (HImode, reg);
2824                     }
2825                   else
2826                     {
2827                       emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2828                       DONE;
2829                     }
2830                 }
2831             }
2832         }
2833     }
2834   /* Handle loading a large integer during reload */
2835   else if (GET_CODE (operands[1]) == CONST_INT
2836            && ! const_ok_for_arm (INTVAL (operands[1]))
2837            && ! const_ok_for_arm (~INTVAL (operands[1])))
2838     {
2839       /* Writing a constant to memory needs a scratch, which should
2840          be handled with SECONDARY_RELOADs.  */
2841       if (GET_CODE (operands[0]) != REG)
2842         abort ();
2844       operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
2845       emit_insn (gen_movsi (operands[0], operands[1]));
2846       DONE;
2847     }
2851 (define_insn "rotated_loadsi"
2852   [(set (match_operand:SI 0 "s_register_operand" "=r")
2853         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
2854                    (const_int 16)))]
2855   "! TARGET_SHORT_BY_BYTES"
2856   "*
2858   rtx ops[2];
2860   ops[0] = operands[0];
2861   ops[1] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 2));
2862   output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
2863   return \"\";
2865 [(set_attr "type" "load")])
2867 (define_expand "movhi_bytes"
2868   [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" ""))))
2869    (set (match_dup 3)
2870         (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
2871    (set (match_operand:SI 0 "" "")
2872          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
2873   ""
2874   "
2875   operands[0] = gen_lowpart (SImode, operands[0]);
2876   operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2877   operands[2] = gen_reg_rtx (SImode);
2878   operands[3] = gen_reg_rtx (SImode);
2880   if (BYTES_BIG_ENDIAN)
2881     {
2882       operands[4] = operands[2];
2883       operands[5] = operands[3];
2884     }
2885   else
2886     {
2887       operands[4] = operands[3];
2888       operands[5] = operands[2];
2889     }
2892 (define_expand "movhi_bigend"
2893   [(set (match_dup 2)
2894         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
2895                    (const_int 16)))
2896    (set (match_dup 3)
2897         (ashiftrt:SI (match_dup 2) (const_int 16)))
2898    (set (match_operand:HI 0 "s_register_operand" "")
2899         (subreg:HI (match_dup 3) 0))]
2900   ""
2901   "
2902   operands[2] = gen_reg_rtx (SImode);
2903   operands[3] = gen_reg_rtx (SImode);
2906 ;; Pattern to recognise insn generated default case above
2908 (define_insn "*movhi_insn_arch4"
2909   [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
2910         (match_operand:HI 1 "general_operand"  "rI,K,m,r"))]
2911   "arm_arch4
2912    && (GET_CODE (operands[1]) != CONST_INT
2913        || const_ok_for_arm (INTVAL (operands[1]))
2914        || const_ok_for_arm (~INTVAL (operands[1])))"
2915   "@
2916    mov%?\\t%0, %1\\t%@ movhi
2917    mvn%?\\t%0, #%B1\\t%@ movhi
2918    ldr%?h\\t%0, %1\\t%@ movhi
2919    str%?h\\t%1, %0\\t%@ movhi"
2920 [(set_attr "type" "*,*,load,store1")])
2922 (define_insn "*movhi_insn_littleend"
2923   [(set (match_operand:HI 0 "general_operand" "=r,r,r")
2924         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2925   "! arm_arch4
2926    && ! BYTES_BIG_ENDIAN
2927    && ! TARGET_SHORT_BY_BYTES
2928    && (GET_CODE (operands[1]) != CONST_INT
2929        || const_ok_for_arm (INTVAL (operands[1]))
2930        || const_ok_for_arm (~INTVAL (operands[1])))"
2931   "@
2932    mov%?\\t%0, %1\\t%@ movhi
2933    mvn%?\\t%0, #%B1\\t%@ movhi
2934    ldr%?\\t%0, %1\\t%@ movhi"
2935 [(set_attr "type" "*,*,load")])
2937 (define_insn "*movhi_insn_bigend"
2938   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
2939         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2940   "! arm_arch4
2941    && BYTES_BIG_ENDIAN
2942    && ! TARGET_SHORT_BY_BYTES
2943    && (GET_CODE (operands[1]) != CONST_INT
2944        || const_ok_for_arm (INTVAL (operands[1]))
2945        || const_ok_for_arm (~INTVAL (operands[1])))"
2946   "@
2947    mov%?\\t%0, %1\\t%@ movhi
2948    mvn%?\\t%0, #%B1\\t%@ movhi
2949    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
2950 [(set_attr "type" "*,*,load")
2951  (set_attr "length" "4,4,8")])
2953 (define_insn "*loadhi_si_bigend"
2954   [(set (match_operand:SI 0 "s_register_operand" "=r")
2955         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
2956                    (const_int 16)))]
2957   "BYTES_BIG_ENDIAN
2958    && ! TARGET_SHORT_BY_BYTES"
2959   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
2960 [(set_attr "type" "load")])
2962 (define_insn "*movhi_bytes"
2963   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
2964         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
2965   "TARGET_SHORT_BY_BYTES"
2966   "@
2967    mov%?\\t%0, %1\\t%@ movhi
2968    mvn%?\\t%0, #%B1\\t%@ movhi")
2971 (define_expand "reload_outhi"
2972   [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
2973               (match_operand:HI 1 "s_register_operand" "r")
2974               (match_operand:SI 2 "s_register_operand" "=&r")])]
2975   ""
2976   "
2977   arm_reload_out_hi (operands);
2978   DONE;
2981 (define_expand "reload_inhi"
2982   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
2983               (match_operand:HI 1 "reload_memory_operand" "o")
2984               (match_operand:SI 2 "s_register_operand" "=&r")])]
2985   "TARGET_SHORT_BY_BYTES"
2986   "
2987   arm_reload_in_hi (operands);
2988   DONE;
2991 (define_expand "movqi"
2992   [(set (match_operand:QI 0 "general_operand" "")
2993         (match_operand:QI 1 "general_operand" ""))]
2994   ""
2995   "
2996   /* Everything except mem = const or mem = mem can be done easily */
2998   if (!(reload_in_progress || reload_completed))
2999     {
3000       if (GET_CODE (operands[1]) == CONST_INT)
3001         {
3002           rtx reg = gen_reg_rtx (SImode);
3004           emit_insn (gen_movsi (reg, operands[1]));
3005           operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
3006         }
3007       if (GET_CODE (operands[0]) == MEM)
3008         operands[1] = force_reg (QImode, operands[1]);
3009     }
3013 (define_insn "*movqi_insn"
3014   [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
3015         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
3016   "register_operand (operands[0], QImode)
3017    || register_operand (operands[1], QImode)"
3018   "@
3019    mov%?\\t%0, %1
3020    mvn%?\\t%0, #%B1
3021    ldr%?b\\t%0, %1
3022    str%?b\\t%1, %0"
3023 [(set_attr "type" "*,*,load,store1")])
3025 (define_expand "movsf"
3026   [(set (match_operand:SF 0 "general_operand" "")
3027         (match_operand:SF 1 "general_operand" ""))]
3028   ""
3029   "
3030   if (GET_CODE (operands[0]) == MEM)
3031     operands[1] = force_reg (SFmode, operands[1]);
3034 (define_insn "*movsf_hard_insn"
3035   [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
3036         (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
3037   "TARGET_HARD_FLOAT
3038    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3039   "@
3040    mvf%?s\\t%0, %1
3041    mnf%?s\\t%0, #%N1
3042    ldf%?s\\t%0, %1
3043    stf%?s\\t%1, %0
3044    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
3045    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
3046    mov%?\\t%0, %1
3047    ldr%?\\t%0, %1\\t%@ float
3048    str%?\\t%1, %0\\t%@ float"
3049 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
3050  (set_attr "type"
3051          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
3053 ;; Exactly the same as above, except that all `f' cases are deleted.
3054 ;; This is necessary to prevent reload from ever trying to use a `f' reg
3055 ;; when -msoft-float.
3057 (define_insn "*movsf_soft_insn"
3058   [(set (match_operand:SF 0 "general_operand" "=r,r,m")
3059         (match_operand:SF 1 "general_operand" "r,mE,r"))]
3060   "TARGET_SOFT_FLOAT
3061    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3062   "@
3063    mov%?\\t%0, %1
3064    ldr%?\\t%0, %1\\t%@ float
3065    str%?\\t%1, %0\\t%@ float"
3066 [(set_attr "length" "4,4,4")
3067  (set_attr "type" "*,load,store1")])
3069 (define_expand "movdf"
3070   [(set (match_operand:DF 0 "general_operand" "")
3071         (match_operand:DF 1 "general_operand" ""))]
3072   ""
3073   "
3074   if (GET_CODE (operands[0]) == MEM)
3075     operands[1] = force_reg (DFmode, operands[1]);
3078 ;; Reloading a df mode value stored in integer regs to memory can require a
3079 ;; scratch reg.
3080 (define_expand "reload_outdf"
3081   [(match_operand:DF 0 "reload_memory_operand" "=o")
3082    (match_operand:DF 1 "s_register_operand" "r")
3083    (match_operand:SI 2 "s_register_operand" "=&r")]
3084   ""
3085   "
3087   enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
3089   if (code == REG)
3090     operands[2] = XEXP (operands[0], 0);
3091   else if (code == POST_INC || code == PRE_DEC)
3092     {
3093       operands[0] = gen_rtx (SUBREG, DImode, operands[0], 0);
3094       operands[1] = gen_rtx (SUBREG, DImode, operands[1], 0);
3095       emit_insn (gen_movdi (operands[0], operands[1]));
3096       DONE;
3097     }
3098   else if (code == PRE_INC)
3099     {
3100       rtx reg = XEXP (XEXP (operands[0], 0), 0);
3101       emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
3102       operands[2] = reg;
3103     }
3104   else if (code == POST_DEC)
3105     operands[2] = XEXP (XEXP (operands[0], 0), 0);
3106   else
3107     emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
3108                            XEXP (XEXP (operands[0], 0), 1)));
3110   emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DFmode, operands[2]),
3111                       operands[1]));
3113   if (code == POST_DEC)
3114     emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
3116   DONE;
3120 (define_insn "*movdf_hard_insn"
3121   [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
3122         (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
3123   "TARGET_HARD_FLOAT
3124    && (GET_CODE (operands[0]) != MEM
3125        || register_operand (operands[1], DFmode))"
3126   "*
3128   rtx ops[3];
3130   switch (which_alternative)
3131     {
3132     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3133     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3134     case 2: case 3: case 4: return output_move_double (operands);
3135     case 5: return \"mvf%?d\\t%0, %1\";
3136     case 6: return \"mnf%?d\\t%0, #%N1\";
3137     case 7: return \"ldf%?d\\t%0, %1\";
3138     case 8: return \"stf%?d\\t%1, %0\";
3139     case 9: return output_mov_double_fpu_from_arm (operands);
3140     case 10: return output_mov_double_arm_from_fpu (operands);
3141     }
3144 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3145  (set_attr "type"
3146 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
3148 ;; Software floating point version.  This is essentially the same as movdi.
3149 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
3150 ;; an `f' reg.
3152 (define_insn "*movdf_soft_insn"
3153   [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3154         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3155   "TARGET_SOFT_FLOAT"
3156   "* return output_move_double (operands);"
3157 [(set_attr "length" "8,8,8")
3158  (set_attr "type" "*,load,store2")])
3160 (define_expand "movxf"
3161   [(set (match_operand:XF 0 "general_operand" "")
3162         (match_operand:XF 1 "general_operand" ""))]
3163   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3164   "")
3166 ;; Even when the XFmode patterns aren't enabled, we enable this after
3167 ;; reloading so that we can push floating point registers in the prologue.
3169 (define_insn "*movxf_hard_insn"
3170   [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3171         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3172   "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3173   "*
3174   switch (which_alternative)
3175     {
3176     case 0: return \"mvf%?e\\t%0, %1\";
3177     case 1: return \"mnf%?e\\t%0, #%N1\";
3178     case 2: return \"ldf%?e\\t%0, %1\";
3179     case 3: return \"stf%?e\\t%1, %0\";
3180     case 4: return output_mov_long_double_fpu_from_arm (operands);
3181     case 5: return output_mov_long_double_arm_from_fpu (operands);
3182     case 6: return output_mov_long_double_arm_from_arm (operands);
3183     }
3185 [(set_attr "length" "4,4,4,4,8,8,12")
3186  (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
3189 ;; load- and store-multiple insns
3190 ;; The arm can load/store any set of registers, provided that they are in
3191 ;; ascending order; but that is beyond GCC so stick with what it knows.
3193 (define_expand "load_multiple"
3194   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3195                           (match_operand:SI 1 "" ""))
3196                      (use (match_operand:SI 2 "" ""))])]
3197   ""
3198   "
3199   /* Support only fixed point registers */
3200   if (GET_CODE (operands[2]) != CONST_INT
3201       || INTVAL (operands[2]) > 14
3202       || INTVAL (operands[2]) < 2
3203       || GET_CODE (operands[1]) != MEM
3204       || GET_CODE (operands[0]) != REG
3205       || REGNO (operands[0]) > 14
3206       || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
3207     FAIL;
3209   operands[3]
3210     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
3211                              force_reg (SImode, XEXP (operands[1], 0)),
3212                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
3213                              MEM_IN_STRUCT_P(operands[1]));
3216 ;; Load multiple with write-back
3218 (define_insn "*ldmsi_postinc"
3219   [(match_parallel 0 "load_multiple_operation"
3220     [(set (match_operand:SI 1 "s_register_operand" "+r")
3221           (plus:SI (match_dup 1)
3222                    (match_operand:SI 2 "const_int_operand" "n")))
3223      (set (match_operand:SI 3 "s_register_operand" "=r")
3224           (mem:SI (match_dup 1)))])]
3225   "(INTVAL (operands[2])  == 4 * (XVECLEN (operands[0], 0) - 2))"
3226   "*
3228   rtx ops[3];
3229   int count = XVECLEN (operands[0], 0);
3231   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3232   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
3233   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
3235   output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
3236   return \"\";
3239 [(set_attr "type" "load")])
3241 ;; Ordinary load multiple
3243 (define_insn "*ldmsi"
3244   [(match_parallel 0 "load_multiple_operation"
3245     [(set (match_operand:SI 1 "s_register_operand" "=r")
3246           (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3247   ""
3248   "*
3250   rtx ops[3];
3251   int count = XVECLEN (operands[0], 0);
3253   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3254   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3255   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3257   output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3258   return \"\";
3261 [(set_attr "type" "load")])
3263 (define_expand "store_multiple"
3264   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3265                           (match_operand:SI 1 "" ""))
3266                      (use (match_operand:SI 2 "" ""))])]
3267   ""
3268   "
3269   /* Support only fixed point registers */
3270   if (GET_CODE (operands[2]) != CONST_INT
3271       || INTVAL (operands[2]) > 14
3272       || INTVAL (operands[2]) < 2
3273       || GET_CODE (operands[1]) != REG
3274       || GET_CODE (operands[0]) != MEM
3275       || REGNO (operands[1]) > 14
3276       || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3277     FAIL;
3279   operands[3]
3280     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3281                               force_reg (SImode, XEXP (operands[0], 0)),
3282                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
3283                               MEM_IN_STRUCT_P(operands[0]));
3286 ;; Store multiple with write-back
3288 (define_insn "*stmsi_postinc"
3289   [(match_parallel 0 "store_multiple_operation"
3290     [(set (match_operand:SI 1 "s_register_operand" "+r")
3291           (plus:SI (match_dup 1)
3292                    (match_operand:SI 2 "const_int_operand" "n")))
3293      (set (mem:SI (match_dup 1))
3294           (match_operand:SI 3 "s_register_operand" "r"))])]
3295   "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3296   "*
3298   rtx ops[3];
3299   int count = XVECLEN (operands[0], 0);
3301   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3302   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3303   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3305   output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3306   return \"\";
3309 [(set (attr "type")
3310       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3311                 (const_string "store2")
3312              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3313                 (const_string "store3")]
3314           (const_string "store4")))])
3316 ;; Ordinary store multiple
3318 (define_insn "*stmsi"
3319   [(match_parallel 0 "store_multiple_operation"
3320     [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3321           (match_operand:SI 1 "s_register_operand" "r"))])]
3322   ""
3323   "*
3325   rtx ops[3];
3326   int count = XVECLEN (operands[0], 0);
3328   ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3329   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3330   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3332   output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3333   return \"\";
3336 [(set (attr "type")
3337       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3338                 (const_string "store2")
3339              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3340                 (const_string "store3")]
3341           (const_string "store4")))])
3343 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
3344 ;; We could let this apply for blocks of less than this, but it clobbers so
3345 ;; many registers that there is then probably a better way.
3347 (define_expand "movstrqi"
3348   [(match_operand:BLK 0 "general_operand" "")
3349    (match_operand:BLK 1 "general_operand" "")
3350    (match_operand:SI 2 "const_int_operand" "")
3351    (match_operand:SI 3 "const_int_operand" "")]
3352   ""
3353   "
3354   if (arm_gen_movstrqi (operands))
3355     DONE;
3356   FAIL;
3360 ;; Comparison and test insns
3362 (define_expand "cmpsi"
3363   [(match_operand:SI 0 "s_register_operand" "")
3364    (match_operand:SI 1 "arm_add_operand" "")]
3365   ""
3366   "
3368   arm_compare_op0 = operands[0];
3369   arm_compare_op1 = operands[1];
3370   arm_compare_fp = 0;
3371   DONE;
3375 (define_expand "cmpsf"
3376   [(match_operand:SF 0 "s_register_operand" "")
3377    (match_operand:SF 1 "fpu_rhs_operand" "")]
3378   "TARGET_HARD_FLOAT"
3379   "
3381   arm_compare_op0 = operands[0];
3382   arm_compare_op1 = operands[1];
3383   arm_compare_fp = 1;
3384   DONE;
3388 (define_expand "cmpdf"
3389   [(match_operand:DF 0 "s_register_operand" "")
3390    (match_operand:DF 1 "fpu_rhs_operand" "")]
3391   "TARGET_HARD_FLOAT"
3392   "
3394   arm_compare_op0 = operands[0];
3395   arm_compare_op1 = operands[1];
3396   arm_compare_fp = 1;
3397   DONE;
3401 (define_expand "cmpxf"
3402   [(match_operand:XF 0 "s_register_operand" "")
3403    (match_operand:XF 1 "fpu_rhs_operand" "")]
3404   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3405   "
3407   arm_compare_op0 = operands[0];
3408   arm_compare_op1 = operands[1];
3409   arm_compare_fp = 1;
3410   DONE;
3414 (define_insn "*cmpsi_insn"
3415   [(set (reg:CC 24)
3416         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3417                     (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3418   ""
3419   "@
3420    cmp%?\\t%0, %1
3421    cmn%?\\t%0, #%n1"
3422 [(set_attr "conds" "set")])
3424 (define_insn "*cmpsi_shiftsi"
3425   [(set (reg:CC 24)
3426         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3427                     (match_operator:SI 3 "shift_operator"
3428                      [(match_operand:SI 1 "s_register_operand" "r")
3429                       (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3430   ""
3431   "cmp%?\\t%0, %1%S3"
3432 [(set_attr "conds" "set")])
3434 (define_insn "*cmpsi_shiftsi_swp"
3435   [(set (reg:CC_SWP 24)
3436         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3437                          [(match_operand:SI 1 "s_register_operand" "r")
3438                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
3439                         (match_operand:SI 0 "s_register_operand" "r")))]
3440   ""
3441   "cmp%?\\t%0, %1%S3"
3442 [(set_attr "conds" "set")])
3444 (define_insn "*cmpsi_neg_shiftsi"
3445   [(set (reg:CC 24)
3446         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3447                     (neg:SI (match_operator:SI 3 "shift_operator"
3448                              [(match_operand:SI 1 "s_register_operand" "r")
3449                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3450   ""
3451   "cmn%?\\t%0, %1%S3"
3452 [(set_attr "conds" "set")])
3454 (define_insn "*cmpsf_insn"
3455   [(set (reg:CCFP 24)
3456         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3457                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3458   "TARGET_HARD_FLOAT"
3459   "@
3460    cmf%?\\t%0, %1
3461    cnf%?\\t%0, #%N1"
3462 [(set_attr "conds" "set")
3463  (set_attr "type" "f_2_r")])
3465 (define_insn "*cmpdf_insn"
3466   [(set (reg:CCFP 24)
3467         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3468                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3469   "TARGET_HARD_FLOAT"
3470   "@
3471    cmf%?\\t%0, %1
3472    cnf%?\\t%0, #%N1"
3473 [(set_attr "conds" "set")
3474  (set_attr "type" "f_2_r")])
3476 (define_insn "*cmpesfdf_df"
3477   [(set (reg:CCFP 24)
3478         (compare:CCFP (float_extend:DF
3479                        (match_operand:SF 0 "s_register_operand" "f,f"))
3480                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3481   "TARGET_HARD_FLOAT"
3482   "@
3483    cmf%?\\t%0, %1
3484    cnf%?\\t%0, #%N1"
3485 [(set_attr "conds" "set")
3486  (set_attr "type" "f_2_r")])
3488 (define_insn "*cmpdf_esfdf"
3489   [(set (reg:CCFP 24)
3490         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3491                       (float_extend:DF
3492                        (match_operand:SF 1 "s_register_operand" "f"))))]
3493   "TARGET_HARD_FLOAT"
3494   "cmf%?\\t%0, %1"
3495 [(set_attr "conds" "set")
3496  (set_attr "type" "f_2_r")])
3498 (define_insn "*cmpxf_insn"
3499   [(set (reg:CCFP 24)
3500         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3501                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3502   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3503   "@
3504    cmf%?\\t%0, %1
3505    cnf%?\\t%0, #%N1"
3506 [(set_attr "conds" "set")
3507  (set_attr "type" "f_2_r")])
3509 (define_insn "*cmpsf_trap"
3510   [(set (reg:CCFPE 24)
3511         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3512                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3513   "TARGET_HARD_FLOAT"
3514   "@
3515    cmf%?e\\t%0, %1
3516    cnf%?e\\t%0, #%N1"
3517 [(set_attr "conds" "set")
3518  (set_attr "type" "f_2_r")])
3520 (define_insn "*cmpdf_trap"
3521   [(set (reg:CCFPE 24)
3522         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3523                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3524   "TARGET_HARD_FLOAT"
3525   "@
3526    cmf%?e\\t%0, %1
3527    cnf%?e\\t%0, #%N1"
3528 [(set_attr "conds" "set")
3529  (set_attr "type" "f_2_r")])
3531 (define_insn "*cmp_esfdf_df_trap"
3532   [(set (reg:CCFPE 24)
3533         (compare:CCFPE (float_extend:DF
3534                         (match_operand:SF 0 "s_register_operand" "f,f"))
3535                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3536   "TARGET_HARD_FLOAT"
3537   "@
3538    cmf%?e\\t%0, %1
3539    cnf%?e\\t%0, #%N1"
3540 [(set_attr "conds" "set")
3541  (set_attr "type" "f_2_r")])
3543 (define_insn "*cmp_df_esfdf_trap"
3544   [(set (reg:CCFPE 24)
3545         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3546                        (float_extend:DF
3547                         (match_operand:SF 1 "s_register_operand" "f"))))]
3548   "TARGET_HARD_FLOAT"
3549   "cmf%?e\\t%0, %1"
3550 [(set_attr "conds" "set")
3551  (set_attr "type" "f_2_r")])
3553 (define_insn "*cmpxf_trap"
3554   [(set (reg:CCFPE 24)
3555         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3556                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3557   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3558   "@
3559    cmf%?e\\t%0, %1
3560    cnf%?e\\t%0, #%N1"
3561 [(set_attr "conds" "set")
3562  (set_attr "type" "f_2_r")])
3564 ; This insn allows redundant compares to be removed by cse, nothing should
3565 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3566 ; is deleted later on. The match_dup will match the mode here, so that
3567 ; mode changes of the condition codes aren't lost by this even though we don't
3568 ; specify what they are.
3570 (define_insn "*deleted_compare"
3571   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3572   ""
3573   "\\t%@ deleted compare"
3574 [(set_attr "conds" "set")
3575  (set_attr "length" "0")])
3578 ;; Conditional branch insns
3580 (define_expand "beq"
3581   [(set (pc)
3582         (if_then_else (eq (match_dup 1) (const_int 0))
3583                       (label_ref (match_operand 0 "" ""))
3584                       (pc)))]
3585   ""
3586   "
3588   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3589                                  arm_compare_fp);
3593 (define_expand "bne"
3594   [(set (pc)
3595         (if_then_else (ne (match_dup 1) (const_int 0))
3596                       (label_ref (match_operand 0 "" ""))
3597                       (pc)))]
3598   ""
3599   "
3601   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3602                                  arm_compare_fp);
3606 (define_expand "bgt"
3607   [(set (pc)
3608         (if_then_else (gt (match_dup 1) (const_int 0))
3609                       (label_ref (match_operand 0 "" ""))
3610                       (pc)))]
3611   ""
3612   "
3614   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3615                                  arm_compare_fp);
3619 (define_expand "ble"
3620   [(set (pc)
3621         (if_then_else (le (match_dup 1) (const_int 0))
3622                       (label_ref (match_operand 0 "" ""))
3623                       (pc)))]
3624   ""
3625   "
3627   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3628                                  arm_compare_fp);
3632 (define_expand "bge"
3633   [(set (pc)
3634         (if_then_else (ge (match_dup 1) (const_int 0))
3635                       (label_ref (match_operand 0 "" ""))
3636                       (pc)))]
3637   ""
3638   "
3640   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3641                                  arm_compare_fp);
3645 (define_expand "blt"
3646   [(set (pc)
3647         (if_then_else (lt (match_dup 1) (const_int 0))
3648                       (label_ref (match_operand 0 "" ""))
3649                       (pc)))]
3650   ""
3651   "
3653   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3654                                  arm_compare_fp);
3658 (define_expand "bgtu"
3659   [(set (pc)
3660         (if_then_else (gtu (match_dup 1) (const_int 0))
3661                       (label_ref (match_operand 0 "" ""))
3662                       (pc)))]
3663   ""
3664   "
3666   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3667                                  arm_compare_fp);
3671 (define_expand "bleu"
3672   [(set (pc)
3673         (if_then_else (leu (match_dup 1) (const_int 0))
3674                       (label_ref (match_operand 0 "" ""))
3675                       (pc)))]
3676   ""
3677   "
3679   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3680                                  arm_compare_fp);
3684 (define_expand "bgeu"
3685   [(set (pc)
3686         (if_then_else (geu (match_dup 1) (const_int 0))
3687                       (label_ref (match_operand 0 "" ""))
3688                       (pc)))]
3689   ""
3690   "
3692   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3693                                  arm_compare_fp);
3697 (define_expand "bltu"
3698   [(set (pc)
3699         (if_then_else (ltu (match_dup 1) (const_int 0))
3700                       (label_ref (match_operand 0 "" ""))
3701                       (pc)))]
3702   ""
3703   "
3705   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3706                                  arm_compare_fp);
3710 ;; patterns to match conditional branch insns
3712 (define_insn "*condbranch"
3713   [(set (pc)
3714         (if_then_else (match_operator 1 "comparison_operator"
3715                        [(match_operand 2 "cc_register" "") (const_int 0)])
3716                       (label_ref (match_operand 0 "" ""))
3717                       (pc)))]
3718   ""
3719   "*
3721   extern int arm_ccfsm_state;
3723   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3724   {
3725     arm_ccfsm_state += 2;
3726     return \"\";
3727   }
3728   return \"b%d1\\t%l0\";
3730 [(set_attr "conds" "use")])
3732 (define_insn "*condbranch_reversed"
3733   [(set (pc)
3734         (if_then_else (match_operator 1 "comparison_operator"
3735                        [(match_operand 2 "cc_register" "") (const_int 0)])
3736                       (pc)
3737                       (label_ref (match_operand 0 "" ""))))]
3738   ""
3739   "*
3741   extern int arm_ccfsm_state;
3743   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3744   {
3745     arm_ccfsm_state += 2;
3746     return \"\";
3747   }
3748   return \"b%D1\\t%l0\";
3750 [(set_attr "conds" "use")])
3753 ; scc insns
3755 (define_expand "seq"
3756   [(set (match_operand:SI 0 "s_register_operand" "=r")
3757         (eq:SI (match_dup 1) (const_int 0)))]
3758   ""
3759   "
3761   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3762                                  arm_compare_fp);
3766 (define_expand "sne"
3767   [(set (match_operand:SI 0 "s_register_operand" "=r")
3768         (ne:SI (match_dup 1) (const_int 0)))]
3769   ""
3770   "
3772   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3773                                  arm_compare_fp);
3777 (define_expand "sgt"
3778   [(set (match_operand:SI 0 "s_register_operand" "=r")
3779         (gt:SI (match_dup 1) (const_int 0)))]
3780   ""
3781   "
3783   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3784                                  arm_compare_fp);
3788 (define_expand "sle"
3789   [(set (match_operand:SI 0 "s_register_operand" "=r")
3790         (le:SI (match_dup 1) (const_int 0)))]
3791   ""
3792   "
3794   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3795                                  arm_compare_fp);
3799 (define_expand "sge"
3800   [(set (match_operand:SI 0 "s_register_operand" "=r")
3801         (ge:SI (match_dup 1) (const_int 0)))]
3802   ""
3803   "
3805   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3806                                  arm_compare_fp);
3810 (define_expand "slt"
3811   [(set (match_operand:SI 0 "s_register_operand" "=r")
3812         (lt:SI (match_dup 1) (const_int 0)))]
3813   ""
3814   "
3816   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3817                                  arm_compare_fp);
3821 (define_expand "sgtu"
3822   [(set (match_operand:SI 0 "s_register_operand" "=r")
3823         (gtu:SI (match_dup 1) (const_int 0)))]
3824   ""
3825   "
3827   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3828                                  arm_compare_fp);
3832 (define_expand "sleu"
3833   [(set (match_operand:SI 0 "s_register_operand" "=r")
3834         (leu:SI (match_dup 1) (const_int 0)))]
3835   ""
3836   "
3838   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3839                                  arm_compare_fp);
3843 (define_expand "sgeu"
3844   [(set (match_operand:SI 0 "s_register_operand" "=r")
3845         (geu:SI (match_dup 1) (const_int 0)))]
3846   ""
3847   "
3849   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3850                                  arm_compare_fp);
3854 (define_expand "sltu"
3855   [(set (match_operand:SI 0 "s_register_operand" "=r")
3856         (ltu:SI (match_dup 1) (const_int 0)))]
3857   ""
3858   "
3860   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3861                                  arm_compare_fp);
3865 (define_insn "*mov_scc"
3866   [(set (match_operand:SI 0 "s_register_operand" "=r")
3867         (match_operator:SI 1 "comparison_operator"
3868          [(match_operand 2 "cc_register" "") (const_int 0)]))]
3869   ""
3870   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
3871 [(set_attr "conds" "use")
3872  (set_attr "length" "8")])
3874 (define_insn "*mov_negscc"
3875   [(set (match_operand:SI 0 "s_register_operand" "=r")
3876         (neg:SI (match_operator:SI 1 "comparison_operator"
3877                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
3878   ""
3879   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
3880 [(set_attr "conds" "use")
3881  (set_attr "length" "8")])
3883 (define_insn "*mov_notscc"
3884   [(set (match_operand:SI 0 "s_register_operand" "=r")
3885         (not:SI (match_operator:SI 1 "comparison_operator"
3886                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
3887   ""
3888   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
3889 [(set_attr "conds" "use")
3890  (set_attr "length" "8")])
3893 ;; Conditional move insns
3895 (define_expand "movsicc"
3896   [(set (match_operand:SI 0 "s_register_operand" "")
3897         (if_then_else:SI (match_operand 1 "comparison_operator" "")
3898                          (match_operand:SI 2 "arm_not_operand" "")
3899                          (match_operand:SI 3 "arm_not_operand" "")))]
3900   ""
3901   "
3903   enum rtx_code code = GET_CODE (operands[1]);
3904   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3905                                arm_compare_fp);
3907   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3910 (define_expand "movsfcc"
3911   [(set (match_operand:SF 0 "s_register_operand" "")
3912         (if_then_else:SF (match_operand 1 "comparison_operator" "")
3913                          (match_operand:SF 2 "s_register_operand" "")
3914                          (match_operand:SF 3 "nonmemory_operand" "")))]
3915   ""
3916   "
3918   enum rtx_code code = GET_CODE (operands[1]);
3919   rtx ccreg;
3921   /* When compiling for SOFT_FLOAT, ensure both arms are in registers.  */
3922   if (! TARGET_HARD_FLOAT)
3923     operands[3] = force_reg (SFmode, operands[3]);
3925   ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3926                            arm_compare_fp);
3928   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3931 (define_expand "movdfcc"
3932   [(set (match_operand:DF 0 "s_register_operand" "")
3933         (if_then_else:DF (match_operand 1 "comparison_operator" "")
3934                          (match_operand:DF 2 "s_register_operand" "")
3935                          (match_operand:DF 3 "nonmemory_operand" "")))]
3936   "TARGET_HARD_FLOAT"
3937   "
3939   enum rtx_code code = GET_CODE (operands[1]);
3940   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3941                                arm_compare_fp);
3943   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3946 (define_insn "*movsicc_insn"
3947   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
3948         (if_then_else:SI
3949          (match_operator 3 "comparison_operator"
3950           [(match_operand 4 "cc_register" "") (const_int 0)])
3951          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
3952          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
3953   ""
3954   "@
3955    mov%D3\\t%0, %2
3956    mvn%D3\\t%0, #%B2
3957    mov%d3\\t%0, %1
3958    mvn%d3\\t%0, #%B1
3959    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
3960    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
3961    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
3962    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
3963   [(set_attr "length" "4,4,4,4,8,8,8,8")
3964    (set_attr "conds" "use")])
3966 (define_insn "*movsfcc_hard_insn"
3967   [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
3968         (if_then_else:SF
3969          (match_operator 3 "comparison_operator" 
3970           [(match_operand 4 "cc_register" "") (const_int 0)])
3971          (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
3972          (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
3973   "TARGET_HARD_FLOAT"
3974   "@
3975    mvf%D3s\\t%0, %2
3976    mnf%D3s\\t%0, #%N2
3977    mvf%d3s\\t%0, %1
3978    mnf%d3s\\t%0, #%N1
3979    mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
3980    mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
3981    mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
3982    mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
3983   [(set_attr "length" "4,4,4,4,8,8,8,8")
3984    (set_attr "type" "ffarith")
3985    (set_attr "conds" "use")])
3987 (define_insn "*movsfcc_soft_insn"
3988   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
3989         (if_then_else:SF (match_operator 3 "comparison_operator"
3990                           [(match_operand 4 "cc_register" "") (const_int 0)])
3991                          (match_operand:SF 1 "s_register_operand" "0,r")
3992                          (match_operand:SF 2 "s_register_operand" "r,0")))]
3993   "TARGET_SOFT_FLOAT"
3994   "@
3995    mov%D3\\t%0, %2
3996    mov%d3\\t%0, %1"
3997   [(set_attr "conds" "use")])
3999 (define_insn "*movdfcc_insn"
4000   [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4001         (if_then_else:DF
4002          (match_operator 3 "comparison_operator"
4003           [(match_operand 4 "cc_register" "") (const_int 0)])
4004          (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4005          (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4006   "TARGET_HARD_FLOAT"
4007   "@
4008    mvf%D3d\\t%0, %2
4009    mnf%D3d\\t%0, #%N2
4010    mvf%d3d\\t%0, %1
4011    mnf%d3d\\t%0, #%N1
4012    mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
4013    mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
4014    mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
4015    mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
4016   [(set_attr "length" "4,4,4,4,8,8,8,8")
4017    (set_attr "type" "ffarith")
4018    (set_attr "conds" "use")])
4020 ;; Jump and linkage insns
4022 (define_insn "jump"
4023   [(set (pc)
4024         (label_ref (match_operand 0 "" "")))]
4025   ""
4026   "*
4028   extern int arm_ccfsm_state;
4030   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4031   {
4032     arm_ccfsm_state += 2;
4033     return \"\";
4034   }
4035   return \"b%?\\t%l0\";
4038 (define_expand "call"
4039   [(parallel [(call (match_operand 0 "memory_operand" "")
4040                     (match_operand 1 "general_operand" ""))
4041               (clobber (reg:SI 14))])]
4042   ""
4043   "")
4045 (define_insn "*call_reg"
4046   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
4047          (match_operand 1 "" "g"))
4048    (clobber (reg:SI 14))]
4049   ""
4050   "*
4051   return output_call (operands);
4053 ;; length is worst case, normally it is only two
4054 [(set_attr "length" "12")
4055  (set_attr "type" "call")])
4057 (define_insn "*call_mem"
4058   [(call (mem:SI (match_operand 0 "memory_operand" "m"))
4059          (match_operand 1 "general_operand" "g"))
4060    (clobber (reg:SI 14))]
4061   ""
4062   "*
4063   return output_call_mem (operands);
4065 [(set_attr "length" "12")
4066  (set_attr "type" "call")])
4068 (define_expand "call_value"
4069   [(parallel [(set (match_operand 0 "" "=rf")
4070                    (call (match_operand 1 "memory_operand" "m")
4071                          (match_operand 2 "general_operand" "g")))
4072               (clobber (reg:SI 14))])]
4073   ""
4074   "")
4076 (define_insn "*call_value_reg"
4077   [(set (match_operand 0 "" "=rf")
4078         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4079               (match_operand 2 "general_operand" "g")))
4080    (clobber (reg:SI 14))]
4081   ""
4082   "*
4083   return output_call (&operands[1]);
4085 [(set_attr "length" "12")
4086  (set_attr "type" "call")])
4088 (define_insn "*call_value_mem"
4089   [(set (match_operand 0 "" "=rf")
4090         (call (mem:SI (match_operand 1 "memory_operand" "m"))
4091         (match_operand 2 "general_operand" "g")))
4092    (clobber (reg:SI 14))]
4093   "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4094   "*
4095   return output_call_mem (&operands[1]);
4097 [(set_attr "length" "12")
4098  (set_attr "type" "call")])
4100 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4101 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4103 (define_insn "*call_symbol"
4104   [(call (mem:SI (match_operand:SI 0 "" "X"))
4105          (match_operand:SI 1 "general_operand" "g"))
4106    (clobber (reg:SI 14))]
4107   "GET_CODE (operands[0]) == SYMBOL_REF"
4108   "bl%?\\t%a0"
4109 [(set_attr "type" "call")])
4111 (define_insn "*call_value_symbol"
4112   [(set (match_operand 0 "s_register_operand" "=rf")
4113         (call (mem:SI (match_operand:SI 1 "" "X"))
4114         (match_operand:SI 2 "general_operand" "g")))
4115    (clobber (reg:SI 14))]
4116   "GET_CODE(operands[1]) == SYMBOL_REF"
4117   "bl%?\\t%a1"
4118 [(set_attr "type" "call")])
4120 ;; Often the return insn will be the same as loading from memory, so set attr
4121 (define_insn "return"
4122   [(return)]
4123   "USE_RETURN_INSN"
4124   "*
4126   extern int arm_ccfsm_state;
4128   if (arm_ccfsm_state == 2)
4129   {
4130     arm_ccfsm_state += 2;
4131     return \"\";
4132   }
4133   return output_return_instruction (NULL, TRUE, FALSE);
4135 [(set_attr "type" "load")])
4137 (define_insn "*cond_return"
4138   [(set (pc)
4139         (if_then_else (match_operator 0 "comparison_operator"
4140                        [(match_operand 1 "cc_register" "") (const_int 0)])
4141                       (return)
4142                       (pc)))]
4143   "USE_RETURN_INSN"
4144   "*
4146   extern int arm_ccfsm_state;
4148   if (arm_ccfsm_state == 2)
4149   {
4150     arm_ccfsm_state += 2;
4151     return \"\";
4152   }
4153   return output_return_instruction (operands[0], TRUE, FALSE);
4155 [(set_attr "conds" "use")
4156  (set_attr "type" "load")])
4158 (define_insn "*cond_return_inverted"
4159   [(set (pc)
4160         (if_then_else (match_operator 0 "comparison_operator"
4161                        [(match_operand 1 "cc_register" "") (const_int 0)])
4162                       (pc)
4163                       (return)))]
4164   "USE_RETURN_INSN"
4165   "*
4167   extern int arm_ccfsm_state;
4169   if (arm_ccfsm_state == 2)
4170   {
4171     arm_ccfsm_state += 2;
4172     return \"\";
4173   }
4174   return output_return_instruction (operands[0], TRUE, TRUE);
4176 [(set_attr "conds" "use")
4177  (set_attr "type" "load")])
4179 ;; Call subroutine returning any type.
4181 (define_expand "untyped_call"
4182   [(parallel [(call (match_operand 0 "" "")
4183                     (const_int 0))
4184               (match_operand 1 "" "")
4185               (match_operand 2 "" "")])]
4186   ""
4187   "
4189   int i;
4191   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4193   for (i = 0; i < XVECLEN (operands[2], 0); i++)
4194     {
4195       rtx set = XVECEXP (operands[2], 0, i);
4196       emit_move_insn (SET_DEST (set), SET_SRC (set));
4197     }
4199   /* The optimizer does not know that the call sets the function value
4200      registers we stored in the result block.  We avoid problems by
4201      claiming that all hard registers are used and clobbered at this
4202      point.  */
4203   emit_insn (gen_blockage ());
4205   DONE;
4208 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4209 ;; all of memory.  This blocks insns from being moved across this point.
4211 (define_insn "blockage"
4212   [(unspec_volatile [(const_int 0)] 0)]
4213   ""
4214   ""
4215 [(set_attr "length" "0")
4216  (set_attr "type" "block")])
4218 (define_expand "casesi"
4219   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
4220    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
4221    (match_operand:SI 2 "const_int_operand" "")  ; total range
4222    (match_operand:SI 3 "" "")                   ; table label
4223    (match_operand:SI 4 "" "")]                  ; Out of range label
4224   ""
4225   "
4227   rtx reg;
4228   if (operands[1] != const0_rtx)
4229     {
4230       reg = gen_reg_rtx (SImode);
4231       emit_insn (gen_addsi3 (reg, operands[0],
4232                              GEN_INT (-INTVAL (operands[1]))));
4233       operands[0] = reg;
4234     }
4236   if (! const_ok_for_arm (INTVAL (operands[2])))
4237     operands[2] = force_reg (SImode, operands[2]);
4239   emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4240                                        operands[4]));
4241   DONE;
4244 ;; The USE in this pattern is needed to tell flow analysis that this is
4245 ;; a CASESI insn.  It has no other purpose.
4246 (define_insn "casesi_internal"
4247   [(parallel [(set (pc)
4248                (if_then_else
4249                 (leu (match_operand:SI 0 "s_register_operand" "r")
4250                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
4251                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4252                                  (label_ref (match_operand 2 "" ""))))
4253                 (label_ref (match_operand 3 "" ""))))
4254               (use (label_ref (match_dup 2)))])]
4255   ""
4256   "*
4257   if (flag_pic)
4258     return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4259   return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4261 [(set_attr "conds" "clob")
4262  (set_attr "length" "12")])
4264 (define_insn "indirect_jump"
4265   [(set (pc)
4266         (match_operand:SI 0 "s_register_operand" "r"))]
4267   ""
4268   "mov%?\\t%|pc, %0\\t%@ indirect jump")
4270 (define_insn "*load_indirect_jump"
4271   [(set (pc)
4272         (match_operand:SI 0 "memory_operand" "m"))]
4273   ""
4274   "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4275 [(set_attr "type" "load")])
4277 ;; Misc insns
4279 (define_insn "nop"
4280   [(const_int 0)]
4281   ""
4282   "mov%?\\tr0, r0\\t%@ nop")
4284 ;; Patterns to allow combination of arithmetic, cond code and shifts
4286 (define_insn "*arith_shiftsi"
4287   [(set (match_operand:SI 0 "s_register_operand" "=r")
4288         (match_operator:SI 1 "shiftable_operator"
4289           [(match_operator:SI 3 "shift_operator"
4290              [(match_operand:SI 4 "s_register_operand" "r")
4291               (match_operand:SI 5 "reg_or_int_operand" "rI")])
4292            (match_operand:SI 2 "s_register_operand" "r")]))]
4293   ""
4294   "%i1%?\\t%0, %2, %4%S3")
4296 (define_insn "*arith_shiftsi_compare0"
4297   [(set (reg:CC_NOOV 24)
4298         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4299                           [(match_operator:SI 3 "shift_operator"
4300                             [(match_operand:SI 4 "s_register_operand" "r")
4301                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4302                            (match_operand:SI 2 "s_register_operand" "r")])
4303                          (const_int 0)))
4304    (set (match_operand:SI 0 "s_register_operand" "=r")
4305         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4306                          (match_dup 2)]))]
4307   ""
4308   "%i1%?s\\t%0, %2, %4%S3"
4309 [(set_attr "conds" "set")])
4311 (define_insn "*arith_shiftsi_compare0_scratch"
4312   [(set (reg:CC_NOOV 24)
4313         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4314                           [(match_operator:SI 3 "shift_operator"
4315                             [(match_operand:SI 4 "s_register_operand" "r")
4316                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4317                            (match_operand:SI 2 "s_register_operand" "r")])
4318                          (const_int 0)))
4319    (clobber (match_scratch:SI 0 "=r"))]
4320   ""
4321   "%i1%?s\\t%0, %2, %4%S3"
4322 [(set_attr "conds" "set")])
4324 (define_insn "*sub_shiftsi"
4325   [(set (match_operand:SI 0 "s_register_operand" "=r")
4326         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4327                   (match_operator:SI 2 "shift_operator"
4328                    [(match_operand:SI 3 "s_register_operand" "r")
4329                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4330   ""
4331   "sub%?\\t%0, %1, %3%S2")
4333 (define_insn "*sub_shiftsi_compare0"
4334   [(set (reg:CC_NOOV 24)
4335         (compare:CC_NOOV
4336          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4337                    (match_operator:SI 2 "shift_operator"
4338                     [(match_operand:SI 3 "s_register_operand" "r")
4339                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4340          (const_int 0)))
4341    (set (match_operand:SI 0 "s_register_operand" "=r")
4342         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4343                                                  (match_dup 4)])))]
4344   ""
4345   "sub%?s\\t%0, %1, %3%S2"
4346 [(set_attr "conds" "set")])
4348 (define_insn "*sub_shiftsi_compare0_scratch"
4349   [(set (reg:CC_NOOV 24)
4350         (compare:CC_NOOV
4351          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4352                    (match_operator:SI 2 "shift_operator"
4353                     [(match_operand:SI 3 "s_register_operand" "r")
4354                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4355          (const_int 0)))
4356    (clobber (match_scratch:SI 0 "=r"))]
4357   ""
4358   "sub%?s\\t%0, %1, %3%S2"
4359 [(set_attr "conds" "set")])
4361 ;; These variants of the above insns can occur if the first operand is the
4362 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
4363 ;; seem to be a way around it.  Most of the predicates have to be null
4364 ;; because the format can be generated part way through reload, so
4365 ;; if we don't match it as soon as it becomes available, reload doesn't know
4366 ;; how to reload pseudos that haven't got hard registers; the constraints will
4367 ;; sort everything out.
4369 (define_insn "*reload_mulsi3"
4370   [(set (match_operand:SI 0 "" "=&r")
4371         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4372                            [(match_operand:SI 3 "" "r")
4373                             (match_operand:SI 4 "" "rM")])
4374                           (match_operand:SI 2 "" "r"))
4375                  (match_operand:SI 1 "const_int_operand" "n")))]
4376   "reload_in_progress"
4377   "*
4378   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4379   operands[2] = operands[1];
4380   operands[1] = operands[0];
4381   return output_add_immediate (operands);
4383 ; we have no idea how long the add_immediate is, it could be up to 4.
4384 [(set_attr "length" "20")])
4386 (define_insn "*reload_mulsi_compare0"
4387   [(set (reg:CC_NOOV 24)
4388         (compare:CC_NOOV (plus:SI
4389                           (plus:SI 
4390                            (match_operator:SI 5 "shift_operator"
4391                             [(match_operand:SI 3 "" "r")
4392                              (match_operand:SI 4 "" "rM")])
4393                            (match_operand:SI 1 "" "r"))
4394                           (match_operand:SI 2 "const_int_operand" "n"))
4395                          (const_int 0)))
4396    (set (match_operand:SI 0 "" "=&r")
4397         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4398                           (match_dup 1))
4399                  (match_dup 2)))]
4400   "reload_in_progress"
4401   "*
4402   output_add_immediate (operands);
4403   return \"add%?s\\t%0, %0, %3%S5\";
4405 [(set_attr "conds" "set")
4406  (set_attr "length" "20")])
4408 (define_insn "*reload_mulsi_compare0_scratch"
4409   [(set (reg:CC_NOOV 24)
4410         (compare:CC_NOOV (plus:SI
4411                           (plus:SI 
4412                            (match_operator:SI 5 "shift_operator"
4413                             [(match_operand:SI 3 "" "r")
4414                              (match_operand:SI 4 "" "rM")])
4415                            (match_operand:SI 1 "" "r"))
4416                           (match_operand:SI 2 "const_int_operand" "n"))
4417                          (const_int 0)))
4418    (clobber (match_scratch:SI 0 "=&r"))]
4419   "reload_in_progress"
4420   "*
4421   output_add_immediate (operands);
4422   return \"add%?s\\t%0, %0, %3%S5\";
4424 [(set_attr "conds" "set")
4425  (set_attr "length" "20")])
4427 ;; These are similar, but are needed when the mla pattern contains the
4428 ;; eliminated register as operand 3.
4430 (define_insn "*reload_muladdsi"
4431   [(set (match_operand:SI 0 "" "=&r,&r")
4432         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4433                                    (match_operand:SI 2 "" "r,r"))
4434                           (match_operand:SI 3 "" "r,r"))
4435                  (match_operand:SI 4 "const_int_operand" "n,n")))]
4436   "reload_in_progress"
4437   "*
4438   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4439   operands[2] = operands[4];
4440   operands[1] = operands[0];
4441   return output_add_immediate (operands);
4443 [(set_attr "length" "20")
4444  (set_attr "type" "mult")])
4446 (define_insn "*reload_muladdsi_compare0"
4447   [(set (reg:CC_NOOV 24)
4448         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4449                                             (match_operand:SI 3 "" "r")
4450                                             (match_operand:SI 4 "" "r"))
4451                                            (match_operand:SI 1 "" "r"))
4452                                   (match_operand:SI 2 "const_int_operand" "n"))
4453                          (const_int 0)))
4454    (set (match_operand:SI 0 "" "=&r")
4455         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4456                  (match_dup 2)))]
4457   "reload_in_progress"
4458   "*
4459   output_add_immediate (operands);
4460   output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4461   return \"\";
4463 [(set_attr "length" "20")
4464  (set_attr "conds" "set")
4465  (set_attr "type" "mult")])
4467 (define_insn "*reload_muladdsi_compare0_scratch"
4468   [(set (reg:CC_NOOV 24)
4469         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4470                                             (match_operand:SI 3 "" "r")
4471                                             (match_operand:SI 4 "" "r"))
4472                                            (match_operand:SI 1 "" "r"))
4473                                   (match_operand:SI 2 "const_int_operand" "n"))
4474                          (const_int 0)))
4475    (clobber (match_scratch:SI 0 "=&r"))]
4476   "reload_in_progress"
4477   "*
4478   output_add_immediate (operands);
4479   return \"mla%?s\\t%0, %3, %4, %0\";
4481 [(set_attr "length" "20")
4482  (set_attr "conds" "set")
4483  (set_attr "type" "mult")])
4487 (define_insn "*and_scc"
4488   [(set (match_operand:SI 0 "s_register_operand" "=r")
4489         (and:SI (match_operator 1 "comparison_operator"
4490                  [(match_operand 3 "cc_register" "") (const_int 0)])
4491                 (match_operand:SI 2 "s_register_operand" "r")))]
4492   ""
4493   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
4494 [(set_attr "conds" "use")
4495  (set_attr "length" "8")])
4497 (define_insn "*ior_scc"
4498   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4499         (ior:SI (match_operator 2 "comparison_operator"
4500                  [(match_operand 3 "cc_register" "") (const_int 0)])
4501                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
4502   ""
4503   "@
4504    orr%d2\\t%0, %1, #1
4505    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
4506 [(set_attr "conds" "use")
4507  (set_attr "length" "4,8")])
4509 (define_insn "*compare_scc"
4510   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4511         (match_operator 1 "comparison_operator"
4512          [(match_operand:SI 2 "s_register_operand" "r,r")
4513           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4514    (clobber (reg 24))]
4515   ""
4516   "*
4517   if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4518     return \"mov\\t%0, %2, lsr #31\";
4520   if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4521     return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4523   if (GET_CODE (operands[1]) == NE)
4524     {
4525       if (which_alternative == 1)
4526         return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4527       return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4528     }
4529   if (which_alternative == 1)
4530     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4531   else
4532     output_asm_insn (\"cmp\\t%2, %3\", operands);
4533   return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4535 [(set_attr "conds" "clob")
4536  (set_attr "length" "12")])
4538 (define_insn "*cond_move"
4539   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4540         (if_then_else:SI (match_operator 3 "equality_operator"
4541                           [(match_operator 4 "comparison_operator"
4542                             [(match_operand 5 "cc_register" "") (const_int 0)])
4543                            (const_int 0)])
4544                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4545                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4546   ""
4547   "*
4548   if (GET_CODE (operands[3]) == NE)
4549     {
4550       if (which_alternative != 1)
4551         output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4552       if (which_alternative != 0)
4553         output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4554       return \"\";
4555     }
4556   if (which_alternative != 0)
4557     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4558   if (which_alternative != 1)
4559     output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4560   return \"\";
4562 [(set_attr "conds" "use")
4563  (set_attr "length" "4,4,8")])
4565 (define_insn "*cond_arith"
4566   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4567         (match_operator:SI 5 "shiftable_operator" 
4568          [(match_operator:SI 4 "comparison_operator"
4569            [(match_operand:SI 2 "s_register_operand" "r,r")
4570             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4571           (match_operand:SI 1 "s_register_operand" "0,?r")]))
4572    (clobber (reg 24))]
4573   ""
4574   "*
4575   if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4576     return \"%i5\\t%0, %1, %2, lsr #31\";
4578   output_asm_insn (\"cmp\\t%2, %3\", operands);
4579   if (GET_CODE (operands[5]) == AND)
4580     output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4581   else if (GET_CODE (operands[5]) == MINUS)
4582     output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4583   else if (which_alternative != 0)
4584     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4585   return \"%i5%d4\\t%0, %1, #1\";
4587 [(set_attr "conds" "clob")
4588  (set_attr "length" "12")])
4590 (define_insn "*cond_sub"
4591   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4592         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4593                   (match_operator:SI 4 "comparison_operator"
4594                    [(match_operand:SI 2 "s_register_operand" "r,r")
4595                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4596    (clobber (reg 24))]
4597   ""
4598   "*
4599   output_asm_insn (\"cmp\\t%2, %3\", operands);
4600   if (which_alternative != 0)
4601     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4602   return \"sub%d4\\t%0, %1, #1\";
4604 [(set_attr "conds" "clob")
4605  (set_attr "length" "8,12")])
4607 (define_insn "*cmp_ite0"
4608   [(set (match_operand 6 "dominant_cc_register" "")
4609         (compare
4610          (if_then_else:SI
4611           (match_operator 4 "comparison_operator"
4612            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4613             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4614           (match_operator:SI 5 "comparison_operator"
4615            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4616             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4617           (const_int 0))
4618          (const_int 0)))]
4619   ""
4620   "*
4622   char* opcodes[4][2] =
4623   {
4624     {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
4625     {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
4626     {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
4627     {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
4628      \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
4629   };
4630   int swap =
4631     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
4633   return opcodes[which_alternative][swap];
4636 [(set_attr "conds" "set")
4637  (set_attr "length" "8")])
4639 (define_insn "*cmp_ite1"
4640   [(set (match_operand 6 "dominant_cc_register" "")
4641         (compare
4642          (if_then_else:SI
4643           (match_operator 4 "comparison_operator"
4644            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4645             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4646           (match_operator:SI 5 "comparison_operator"
4647            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4648             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4649           (const_int 1))
4650          (const_int 0)))]
4651   ""
4652   "*
4654   char* opcodes[4][2] =
4655   {
4656     {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
4657     {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
4658     {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
4659     {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
4660      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
4661   };
4662   int swap =
4663     comparison_dominates_p (GET_CODE (operands[5]),
4664                             reverse_condition (GET_CODE (operands[4])));
4666   return opcodes[which_alternative][swap];
4669 [(set_attr "conds" "set")
4670  (set_attr "length" "8")])
4672 (define_insn "*negscc"
4673   [(set (match_operand:SI 0 "s_register_operand" "=r")
4674         (neg:SI (match_operator 3 "comparison_operator"
4675                  [(match_operand:SI 1 "s_register_operand" "r")
4676                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4677    (clobber (reg 24))]
4678   ""
4679   "*
4680   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4681     return \"mov\\t%0, %1, asr #31\";
4683   if (GET_CODE (operands[3]) == NE)
4684     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4686   if (GET_CODE (operands[3]) == GT)
4687     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4689   output_asm_insn (\"cmp\\t%1, %2\", operands);
4690   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4691   return \"mvn%d3\\t%0, #0\";
4693 [(set_attr "conds" "clob")
4694  (set_attr "length" "12")])
4696 (define_insn "movcond"
4697   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4698         (if_then_else:SI
4699          (match_operator 5 "comparison_operator"
4700           [(match_operand:SI 3 "s_register_operand" "r,r,r")
4701            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4702          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4703          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4704    (clobber (reg 24))]
4705   ""
4706   "*
4707   if (GET_CODE (operands[5]) == LT
4708       && (operands[4] == const0_rtx))
4709     {
4710       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4711         {
4712           if (operands[2] == const0_rtx)
4713             return \"and\\t%0, %1, %3, asr #31\";
4714           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4715         }
4716       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4717         {
4718           if (operands[1] == const0_rtx)
4719             return \"bic\\t%0, %2, %3, asr #31\";
4720           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4721         }
4722       /* The only case that falls through to here is when both ops 1 & 2
4723          are constants */
4724     }
4726   if (GET_CODE (operands[5]) == GE
4727       && (operands[4] == const0_rtx))
4728     {
4729       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4730         {
4731           if (operands[2] == const0_rtx)
4732             return \"bic\\t%0, %1, %3, asr #31\";
4733           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4734         }
4735       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4736         {
4737           if (operands[1] == const0_rtx)
4738             return \"and\\t%0, %2, %3, asr #31\";
4739           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4740         }
4741       /* The only case that falls through to here is when both ops 1 & 2
4742          are constants */
4743     }
4744   if (GET_CODE (operands[4]) == CONST_INT
4745       && !const_ok_for_arm (INTVAL (operands[4])))
4746     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4747   else
4748     output_asm_insn (\"cmp\\t%3, %4\", operands);
4749   if (which_alternative != 0)
4750     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4751   if (which_alternative != 1)
4752     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4753   return \"\";
4755 [(set_attr "conds" "clob")
4756  (set_attr "length" "8,8,12")])
4758 (define_insn "*ifcompare_plus_move"
4759   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4760         (if_then_else:SI (match_operator 6 "comparison_operator"
4761                           [(match_operand:SI 4 "s_register_operand" "r,r")
4762                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4763                          (plus:SI
4764                           (match_operand:SI 2 "s_register_operand" "r,r")
4765                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
4766                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4767    (clobber (reg 24))]
4768   ""
4769   "#"
4770 [(set_attr "conds" "clob")
4771  (set_attr "length" "8,12")])
4773 (define_insn "*if_plus_move"
4774   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r")
4775         (if_then_else:SI
4776          (match_operator 4 "comparison_operator"
4777           [(match_operand 5 "cc_register" "") (const_int 0)])
4778          (plus:SI
4779           (match_operand:SI 2 "s_register_operand" "r,r,r,r,r,r")
4780           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L,rI,L"))
4781          (match_operand:SI 1 "arm_rhsm_operand" "0,0,?rI,?rI,m,m")))]
4782   ""
4783   "@
4784    add%d4\\t%0, %2, %3
4785    sub%d4\\t%0, %2, #%n3
4786    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4787    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1
4788    add%d4\\t%0, %2, %3\;ldr%D4\\t%0, %1
4789    sub%d4\\t%0, %2, #%n3\;ldr%D4\\t%0, %1"
4790 [(set_attr "conds" "use")
4791  (set_attr "length" "4,4,8,8,8,8")
4792  (set_attr "type" "*,*,*,*,load,load")])
4794 (define_insn "*ifcompare_move_plus"
4795   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4796         (if_then_else:SI (match_operator 6 "comparison_operator"
4797                           [(match_operand:SI 4 "s_register_operand" "r,r")
4798                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4799                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4800                          (plus:SI
4801                           (match_operand:SI 2 "s_register_operand" "r,r")
4802                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4803    (clobber (reg 24))]
4804   ""
4805   "#"
4806 [(set_attr "conds" "clob")
4807  (set_attr "length" "8,12")])
4809 (define_insn "*if_move_plus"
4810   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r")
4811         (if_then_else:SI
4812          (match_operator 4 "comparison_operator"
4813           [(match_operand 5 "cc_register" "") (const_int 0)])
4814          (match_operand:SI 1 "arm_rhsm_operand" "0,0,?rI,?rI,m,m")
4815          (plus:SI
4816           (match_operand:SI 2 "s_register_operand" "r,r,r,r,r,r")
4817           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L,rI,L"))))]
4818   ""
4819   "@
4820    add%D4\\t%0, %2, %3
4821    sub%D4\\t%0, %2, #%n3
4822    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4823    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1
4824    add%D4\\t%0, %2, %3\;ldr%d4\\t%0, %1
4825    sub%D4\\t%0, %2, #%n3\;ldr%d4\\t%0, %1"
4826 [(set_attr "conds" "use")
4827  (set_attr "length" "4,4,8,8,8,8")
4828  (set_attr "type" "*,*,*,*,load,load")])
4830 (define_insn "*ifcompare_arith_arith"
4831   [(set (match_operand:SI 0 "s_register_operand" "=r")
4832         (if_then_else:SI (match_operator 9 "comparison_operator"
4833                           [(match_operand:SI 5 "s_register_operand" "r")
4834                            (match_operand:SI 6 "arm_add_operand" "rIL")])
4835                          (match_operator:SI 8 "shiftable_operator"
4836                           [(match_operand:SI 1 "s_register_operand" "r")
4837                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
4838                          (match_operator:SI 7 "shiftable_operator"
4839                           [(match_operand:SI 3 "s_register_operand" "r")
4840                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
4841    (clobber (reg 24))]
4842   ""
4843   "#"
4844 [(set_attr "conds" "clob")
4845  (set_attr "length" "12")])
4847 (define_insn "*if_arith_arith"
4848   [(set (match_operand:SI 0 "s_register_operand" "=r")
4849         (if_then_else:SI (match_operator 5 "comparison_operator"
4850                           [(match_operand 8 "cc_register" "") (const_int 0)])
4851                          (match_operator:SI 6 "shiftable_operator"
4852                           [(match_operand:SI 1 "s_register_operand" "r")
4853                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
4854                          (match_operator:SI 7 "shiftable_operator"
4855                           [(match_operand:SI 3 "s_register_operand" "r")
4856                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
4857   ""
4858   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
4859 [(set_attr "conds" "use")
4860  (set_attr "length" "8")])
4862 (define_insn "*ifcompare_arith_move"
4863   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4864         (if_then_else:SI (match_operator 6 "comparison_operator"
4865                           [(match_operand:SI 2 "s_register_operand" "r,r")
4866                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
4867                          (match_operator:SI 7 "shiftable_operator"
4868                           [(match_operand:SI 4 "s_register_operand" "r,r")
4869                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
4870                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4871    (clobber (reg 24))]
4872   ""
4873   "*
4874   /* If we have an operation where (op x 0) is the identity operation and
4875      the conditional operator is LT or GE and we are comparing against zero and
4876      everything is in registers then we can do this in two instructions */
4877   if (operands[3] == const0_rtx
4878       && GET_CODE (operands[7]) != AND
4879       && GET_CODE (operands[5]) == REG
4880       && GET_CODE (operands[1]) == REG 
4881       && REGNO (operands[1]) == REGNO (operands[4])
4882       && REGNO (operands[4]) != REGNO (operands[0]))
4883     {
4884       if (GET_CODE (operands[6]) == LT)
4885         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4886       else if (GET_CODE (operands[6]) == GE)
4887         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4888     }
4889   if (GET_CODE (operands[3]) == CONST_INT
4890       && !const_ok_for_arm (INTVAL (operands[3])))
4891     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4892   else
4893     output_asm_insn (\"cmp\\t%2, %3\", operands);
4894   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
4895   if (which_alternative != 0)
4896     {
4897       if (GET_CODE (operands[1]) == MEM)
4898         return \"ldr%D6\\t%0, %1\";
4899       else
4900         return \"mov%D6\\t%0, %1\";
4901     }
4902   return \"\";
4904 [(set_attr "conds" "clob")
4905  (set_attr "length" "8,12")])
4907 (define_insn "*if_arith_move"
4908   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4909         (if_then_else:SI (match_operator 4 "comparison_operator"
4910                           [(match_operand 6 "cc_register" "") (const_int 0)])
4911                          (match_operator:SI 5 "shiftable_operator"
4912                           [(match_operand:SI 2 "s_register_operand" "r,r,r")
4913                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI")])
4914                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rI,m")))]
4915   ""
4916   "@
4917    %I5%d4\\t%0, %2, %3
4918    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4919    %I5%d4\\t%0, %2, %3\;ldr%D4\\t%0, %1"
4920 [(set_attr "conds" "use")
4921  (set_attr "length" "4,8,8")
4922  (set_attr "type" "*,*,load")])
4924 (define_insn "*ifcompare_move_arith"
4925   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4926         (if_then_else:SI (match_operator 6 "comparison_operator"
4927                           [(match_operand:SI 4 "s_register_operand" "r,r")
4928                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4929                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4930                          (match_operator:SI 7 "shiftable_operator"
4931                           [(match_operand:SI 2 "s_register_operand" "r,r")
4932                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4933    (clobber (reg 24))]
4934   ""
4935   "*
4936   /* If we have an operation where (op x 0) is the identity operation and
4937      the conditional operator is LT or GE and we are comparing against zero and
4938      everything is in registers then we can do this in two instructions */
4939   if (operands[5] == const0_rtx
4940       && GET_CODE (operands[7]) != AND
4941       && GET_CODE (operands[3]) == REG
4942       && GET_CODE (operands[1]) == REG 
4943       && REGNO (operands[1]) == REGNO (operands[2])
4944       && REGNO (operands[2]) != REGNO (operands[0]))
4945     {
4946       if (GET_CODE (operands[6]) == GE)
4947         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4948       else if (GET_CODE (operands[6]) == LT)
4949         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4950     }
4952   if (GET_CODE (operands[5]) == CONST_INT
4953       && !const_ok_for_arm (INTVAL (operands[5])))
4954     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4955   else
4956     output_asm_insn (\"cmp\\t%4, %5\", operands);
4958   if (which_alternative != 0)
4959     {
4960       if (GET_CODE (operands[1]) == MEM)
4961         output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4962       else
4963         output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4964     }
4965   return \"%I7%D6\\t%0, %2, %3\";
4967 [(set_attr "conds" "clob")
4968  (set_attr "length" "8,12")])
4970 (define_insn "*if_move_arith"
4971   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4972         (if_then_else:SI
4973          (match_operator 4 "comparison_operator"
4974           [(match_operand 6 "cc_register" "") (const_int 0)])
4975          (match_operand:SI 1 "arm_rhsm_operand" "0,?rI,m")
4976          (match_operator:SI 5 "shiftable_operator"
4977           [(match_operand:SI 2 "s_register_operand" "r,r,r")
4978            (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI")])))]
4979   ""
4980   "@
4981    %I5%D4\\t%0, %2, %3
4982    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4983    %I5%D4\\t%0, %2, %3\;ldr%d4\\t%0, %1"
4984 [(set_attr "conds" "use")
4985  (set_attr "length" "4,8,8")
4986  (set_attr "type" "*,*,load")])
4988 (define_insn "*ifcompare_move_not"
4989   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4990         (if_then_else:SI
4991          (match_operator 5 "comparison_operator"
4992           [(match_operand:SI 3 "s_register_operand" "r,r")
4993            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
4994          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
4995          (not:SI
4996           (match_operand:SI 2 "s_register_operand" "r,r"))))
4997    (clobber (reg 24))]
4998   ""
4999   "#"
5000 [(set_attr "conds" "clob")
5001  (set_attr "length" "8,12")])
5003 (define_insn "*if_move_not"
5004   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5005         (if_then_else:SI
5006          (match_operator 4 "comparison_operator"
5007           [(match_operand 3 "cc_register" "") (const_int 0)])
5008          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5009          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5010   ""
5011   "@
5012    mvn%D4\\t%0, %2
5013    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
5014    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
5015 [(set_attr "conds" "use")
5016  (set_attr "length" "4,8,8")])
5018 (define_insn "*ifcompare_not_move"
5019   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5020         (if_then_else:SI 
5021          (match_operator 5 "comparison_operator"
5022           [(match_operand:SI 3 "s_register_operand" "r,r")
5023            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5024          (not:SI
5025           (match_operand:SI 2 "s_register_operand" "r,r"))
5026          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5027    (clobber (reg 24))]
5028   ""
5029   "#"
5030 [(set_attr "conds" "clob")
5031  (set_attr "length" "8,12")])
5033 (define_insn "*if_not_move"
5034   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5035         (if_then_else:SI
5036          (match_operator 4 "comparison_operator"
5037           [(match_operand 3 "cc_register" "") (const_int 0)])
5038          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5039          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5040   ""
5041   "@
5042    mvn%d4\\t%0, %2
5043    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
5044    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
5045 [(set_attr "conds" "use")
5046  (set_attr "length" "4,8,8")])
5048 (define_insn "*ifcompare_shift_move"
5049   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5050         (if_then_else:SI
5051          (match_operator 6 "comparison_operator"
5052           [(match_operand:SI 4 "s_register_operand" "r,r")
5053            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5054          (match_operator:SI 7 "shift_operator"
5055           [(match_operand:SI 2 "s_register_operand" "r,r")
5056            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
5057          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5058    (clobber (reg 24))]
5059   ""
5060   "#"
5061 [(set_attr "conds" "clob")
5062  (set_attr "length" "8,12")])
5064 (define_insn "*if_shift_move"
5065   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5066         (if_then_else:SI
5067          (match_operator 5 "comparison_operator"
5068           [(match_operand 6 "cc_register" "") (const_int 0)])
5069          (match_operator:SI 4 "shift_operator"
5070           [(match_operand:SI 2 "s_register_operand" "r,r,r")
5071            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
5072          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5073   ""
5074   "@
5075    mov%d5\\t%0, %2%S4
5076    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
5077    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
5078 [(set_attr "conds" "use")
5079  (set_attr "length" "4,8,8")])
5081 (define_insn "*ifcompare_move_shift"
5082   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5083         (if_then_else:SI
5084          (match_operator 6 "comparison_operator"
5085           [(match_operand:SI 4 "s_register_operand" "r,r")
5086            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5087          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5088          (match_operator:SI 7 "shift_operator"
5089           [(match_operand:SI 2 "s_register_operand" "r,r")
5090            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5091    (clobber (reg 24))]
5092   ""
5093   "#"
5094 [(set_attr "conds" "clob")
5095  (set_attr "length" "8,12")])
5097 (define_insn "*if_move_shift"
5098   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5099         (if_then_else:SI
5100          (match_operator 5 "comparison_operator"
5101           [(match_operand 6 "cc_register" "") (const_int 0)])
5102          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5103          (match_operator:SI 4 "shift_operator"
5104           [(match_operand:SI 2 "s_register_operand" "r,r,r")
5105            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5106   ""
5107   "@
5108    mov%D5\\t%0, %2%S4
5109    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5110    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5111 [(set_attr "conds" "use")
5112  (set_attr "length" "4,8,8")])
5114 (define_insn "*ifcompare_shift_shift"
5115   [(set (match_operand:SI 0 "s_register_operand" "=r")
5116         (if_then_else:SI
5117          (match_operator 7 "comparison_operator"
5118           [(match_operand:SI 5 "s_register_operand" "r")
5119            (match_operand:SI 6 "arm_add_operand" "rIL")])
5120          (match_operator:SI 8 "shift_operator"
5121           [(match_operand:SI 1 "s_register_operand" "r")
5122            (match_operand:SI 2 "arm_rhs_operand" "rM")])
5123          (match_operator:SI 9 "shift_operator"
5124           [(match_operand:SI 3 "s_register_operand" "r")
5125            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5126    (clobber (reg 24))]
5127   ""
5128   "#"
5129 [(set_attr "conds" "clob")
5130  (set_attr "length" "12")])
5132 (define_insn "*if_shift_shift"
5133   [(set (match_operand:SI 0 "s_register_operand" "=r")
5134         (if_then_else:SI
5135          (match_operator 5 "comparison_operator"
5136           [(match_operand 8 "cc_register" "") (const_int 0)])
5137          (match_operator:SI 6 "shift_operator"
5138           [(match_operand:SI 1 "s_register_operand" "r")
5139            (match_operand:SI 2 "arm_rhs_operand" "rM")])
5140          (match_operator:SI 7 "shift_operator"
5141           [(match_operand:SI 3 "s_register_operand" "r")
5142            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5143   ""
5144   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5145 [(set_attr "conds" "use")
5146  (set_attr "length" "8")])
5148 (define_insn "*ifcompare_not_arith"
5149   [(set (match_operand:SI 0 "s_register_operand" "=r")
5150         (if_then_else:SI
5151          (match_operator 6 "comparison_operator"
5152           [(match_operand:SI 4 "s_register_operand" "r")
5153            (match_operand:SI 5 "arm_add_operand" "rIL")])
5154          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5155          (match_operator:SI 7 "shiftable_operator"
5156           [(match_operand:SI 2 "s_register_operand" "r")
5157            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5158    (clobber (reg 24))]
5159   ""
5160   "#"
5161 [(set_attr "conds" "clob")
5162  (set_attr "length" "12")])
5164 (define_insn "*if_not_arith"
5165   [(set (match_operand:SI 0 "s_register_operand" "=r")
5166         (if_then_else:SI
5167          (match_operator 5 "comparison_operator"
5168           [(match_operand 4 "cc_register" "") (const_int 0)])
5169          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5170          (match_operator:SI 6 "shiftable_operator"
5171           [(match_operand:SI 2 "s_register_operand" "r")
5172            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5173   ""
5174   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5175 [(set_attr "conds" "use")
5176  (set_attr "length" "8")])
5178 (define_insn "*ifcompare_arith_not"
5179   [(set (match_operand:SI 0 "s_register_operand" "=r")
5180         (if_then_else:SI
5181          (match_operator 6 "comparison_operator"
5182           [(match_operand:SI 4 "s_register_operand" "r")
5183            (match_operand:SI 5 "arm_add_operand" "rIL")])
5184          (match_operator:SI 7 "shiftable_operator"
5185           [(match_operand:SI 2 "s_register_operand" "r")
5186            (match_operand:SI 3 "arm_rhs_operand" "rI")])
5187          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5188    (clobber (reg 24))]
5189   ""
5190   "#"
5191 [(set_attr "conds" "clob")
5192  (set_attr "length" "12")])
5194 (define_insn "*if_arith_not"
5195   [(set (match_operand:SI 0 "s_register_operand" "=r")
5196         (if_then_else:SI
5197          (match_operator 5 "comparison_operator"
5198           [(match_operand 4 "cc_register" "") (const_int 0)])
5199          (match_operator:SI 6 "shiftable_operator"
5200           [(match_operand:SI 2 "s_register_operand" "r")
5201            (match_operand:SI 3 "arm_rhs_operand" "rI")])
5202          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5203   ""
5204   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5205 [(set_attr "conds" "use")
5206  (set_attr "length" "8")])
5208 (define_insn "*ifcompare_neg_move"
5209   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5210         (if_then_else:SI
5211          (match_operator 5 "comparison_operator"
5212           [(match_operand:SI 3 "s_register_operand" "r,r")
5213            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5214          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5215          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5216    (clobber (reg:CC 24))]
5217   ""
5218   "#"
5219 [(set_attr "conds" "clob")
5220  (set_attr "length" "8,12")])
5222 (define_insn "*if_neg_move"
5223   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5224         (if_then_else:SI
5225          (match_operator 4 "comparison_operator"
5226           [(match_operand 3 "cc_register" "") (const_int 0)])
5227          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5228          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5229   ""
5230   "@
5231    rsb%d4\\t%0, %2, #0
5232    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5233    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5234 [(set_attr "conds" "use")
5235  (set_attr "length" "4,8,8")])
5237 (define_insn "*ifcompare_move_neg"
5238   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5239         (if_then_else:SI
5240          (match_operator 5 "comparison_operator"
5241           [(match_operand:SI 3 "s_register_operand" "r,r")
5242            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5243          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5244          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5245    (clobber (reg:CC 24))]
5246   ""
5247   "#"
5248 [(set_attr "conds" "clob")
5249  (set_attr "length" "8,12")])
5251 (define_insn "*if_move_neg"
5252   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5253         (if_then_else:SI
5254          (match_operator 4 "comparison_operator"
5255           [(match_operand 3 "cc_register" "") (const_int 0)])
5256          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5257          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5258   ""
5259   "@
5260    rsb%D4\\t%0, %2, #0
5261    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5262    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5263 [(set_attr "conds" "use")
5264  (set_attr "length" "4,8,8")])
5266 (define_insn "*arith_adjacentmem"
5267   [(set (match_operand:SI 0 "s_register_operand" "=r")
5268         (match_operator:SI 1 "shiftable_operator"
5269          [(match_operand:SI 2 "memory_operand" "m")
5270           (match_operand:SI 3 "memory_operand" "m")]))
5271    (clobber (match_scratch:SI 4 "=r"))]
5272   "adjacent_mem_locations (operands[2], operands[3])"
5273   "*
5275   rtx ldm[3];
5276   rtx arith[4];
5277   int val1 = 0, val2 = 0;
5279   if (REGNO (operands[0]) > REGNO (operands[4]))
5280     {
5281       ldm[1] = operands[4];
5282       ldm[2] = operands[0];
5283     }
5284   else
5285     {
5286       ldm[1] = operands[0];
5287       ldm[2] = operands[4];
5288     }
5289   if (GET_CODE (XEXP (operands[2], 0)) != REG)
5290     val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5291   if (GET_CODE (XEXP (operands[3], 0)) != REG)
5292     val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5293   arith[0] = operands[0];
5294   arith[3] = operands[1];
5295   if (val1 < val2)
5296     {
5297       arith[1] = ldm[1];
5298       arith[2] = ldm[2];
5299     }
5300   else
5301     {
5302       arith[1] = ldm[2];
5303       arith[2] = ldm[1];
5304     }
5305   if (val1 && val2)
5306     {
5307       rtx ops[3];
5308       ldm[0] = ops[0] = operands[4];
5309       ops[1] = XEXP (XEXP (operands[2], 0), 0);
5310       ops[2] = XEXP (XEXP (operands[2], 0), 1);
5311       output_add_immediate (ops);
5312       if (val1 < val2)
5313         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5314       else
5315         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5316     }
5317   else if (val1)
5318     {
5319       ldm[0] = XEXP (operands[3], 0);
5320       if (val1 < val2)
5321         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5322       else
5323         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5324     }
5325   else
5326     {
5327       ldm[0] = XEXP (operands[2], 0);
5328       if (val1 < val2)
5329         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5330       else
5331         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5332     }
5333   output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5334   return \"\";
5337 [(set_attr "length" "12")
5338  (set_attr "type" "load")])
5340 ;; the arm can support extended pre-inc instructions
5342 ;; In all these cases, we use operands 0 and 1 for the register being
5343 ;; incremented because those are the operands that local-alloc will
5344 ;; tie and these are the pair most likely to be tieable (and the ones
5345 ;; that will benefit the most).
5347 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5348 ;; elimination will cause too many headaches.
5350 (define_insn "*strqi_preinc"
5351   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5352                          (match_operand:SI 2 "index_operand" "rJ")))
5353         (match_operand:QI 3 "s_register_operand" "r"))
5354    (set (match_operand:SI 0 "s_register_operand" "=r")
5355         (plus:SI (match_dup 1) (match_dup 2)))]
5356   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5357    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5358    && (GET_CODE (operands[2]) != REG
5359        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5360   "str%?b\\t%3, [%0, %2]!"
5361 [(set_attr "type" "store1")])
5363 (define_insn "*strqi_predec"
5364   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5365                           (match_operand:SI 2 "s_register_operand" "r")))
5366         (match_operand:QI 3 "s_register_operand" "r"))
5367    (set (match_operand:SI 0 "s_register_operand" "=r")
5368         (minus:SI (match_dup 1) (match_dup 2)))]
5369   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5370    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5371    && (GET_CODE (operands[2]) != REG
5372        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5373   "str%?b\\t%3, [%0, -%2]!"
5374 [(set_attr "type" "store1")])
5376 (define_insn "*loadqi_preinc"
5377   [(set (match_operand:QI 3 "s_register_operand" "=r")
5378         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5379                          (match_operand:SI 2 "index_operand" "rJ"))))
5380    (set (match_operand:SI 0 "s_register_operand" "=r")
5381         (plus:SI (match_dup 1) (match_dup 2)))]
5382   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5383    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5384    && (GET_CODE (operands[2]) != REG
5385        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5386   "ldr%?b\\t%3, [%0, %2]!"
5387 [(set_attr "type" "load")])
5389 (define_insn "*loadqi_predec"
5390   [(set (match_operand:QI 3 "s_register_operand" "=r")
5391         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5392                           (match_operand:SI 2 "s_register_operand" "r"))))
5393    (set (match_operand:SI 0 "s_register_operand" "=r")
5394         (minus:SI (match_dup 1) (match_dup 2)))]
5395   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5396    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5397    && (GET_CODE (operands[2]) != REG
5398        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5399   "ldr%?b\\t%3, [%0, -%2]!"
5400 [(set_attr "type" "load")])
5402 (define_insn "*loadqisi_preinc"
5403   [(set (match_operand:SI 3 "s_register_operand" "=r")
5404         (zero_extend:SI
5405          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5406                           (match_operand:SI 2 "index_operand" "rJ")))))
5407    (set (match_operand:SI 0 "s_register_operand" "=r")
5408         (plus:SI (match_dup 1) (match_dup 2)))]
5409   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5410    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5411    && (GET_CODE (operands[2]) != REG
5412        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5413   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5414 [(set_attr "type" "load")])
5416 (define_insn "*loadqisi_predec"
5417   [(set (match_operand:SI 3 "s_register_operand" "=r")
5418         (zero_extend:SI
5419          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5420                            (match_operand:SI 2 "s_register_operand" "r")))))
5421    (set (match_operand:SI 0 "s_register_operand" "=r")
5422         (minus:SI (match_dup 1) (match_dup 2)))]
5423   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5424    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5425    && (GET_CODE (operands[2]) != REG
5426        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5427   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5428 [(set_attr "type" "load")])
5430 (define_insn "*strsi_preinc"
5431   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5432                          (match_operand:SI 2 "index_operand" "rJ")))
5433         (match_operand:SI 3 "s_register_operand" "r"))
5434    (set (match_operand:SI 0 "s_register_operand" "=r")
5435         (plus:SI (match_dup 1) (match_dup 2)))]
5436   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5437    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5438    && (GET_CODE (operands[2]) != REG
5439        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5440   "str%?\\t%3, [%0, %2]!"
5441 [(set_attr "type" "store1")])
5443 (define_insn "*strqi_predec"
5444   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5445                           (match_operand:SI 2 "s_register_operand" "r")))
5446         (match_operand:SI 3 "s_register_operand" "r"))
5447    (set (match_operand:SI 0 "s_register_operand" "=r")
5448         (minus:SI (match_dup 1) (match_dup 2)))]
5449   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5450    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5451    && (GET_CODE (operands[2]) != REG
5452        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5453   "str%?\\t%3, [%0, -%2]!"
5454 [(set_attr "type" "store1")])
5456 (define_insn "*loadsi_preinc"
5457   [(set (match_operand:SI 3 "s_register_operand" "=r")
5458         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5459                          (match_operand:SI 2 "index_operand" "rJ"))))
5460    (set (match_operand:SI 0 "s_register_operand" "=r")
5461         (plus:SI (match_dup 1) (match_dup 2)))]
5462   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5463    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5464    && (GET_CODE (operands[2]) != REG
5465        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5466   "ldr%?\\t%3, [%0, %2]!"
5467 [(set_attr "type" "load")])
5469 (define_insn "*loadsi_predec"
5470   [(set (match_operand:SI 3 "s_register_operand" "=r")
5471         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5472                           (match_operand:SI 2 "s_register_operand" "r"))))
5473    (set (match_operand:SI 0 "s_register_operand" "=r")
5474         (minus:SI (match_dup 1) (match_dup 2)))]
5475   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5476    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5477    && (GET_CODE (operands[2]) != REG
5478        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5479   "ldr%?\\t%3, [%0, -%2]!"
5480 [(set_attr "type" "load")])
5482 (define_insn "*loadhi_preinc"
5483   [(set (match_operand:HI 3 "s_register_operand" "=r")
5484         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5485                          (match_operand:SI 2 "index_operand" "rJ"))))
5486    (set (match_operand:SI 0 "s_register_operand" "=r")
5487         (plus:SI (match_dup 1) (match_dup 2)))]
5488   "(! BYTES_BIG_ENDIAN)
5489    && ! TARGET_SHORT_BY_BYTES
5490    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5491    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5492    && (GET_CODE (operands[2]) != REG
5493        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5494   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5495 [(set_attr "type" "load")])
5497 (define_insn "*loadhi_predec"
5498   [(set (match_operand:HI 3 "s_register_operand" "=r")
5499         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5500                           (match_operand:SI 2 "s_register_operand" "r"))))
5501    (set (match_operand:SI 0 "s_register_operand" "=r")
5502         (minus:SI (match_dup 1) (match_dup 2)))]
5503   "(!BYTES_BIG_ENDIAN)
5504    && ! TARGET_SHORT_BY_BYTES
5505    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5506    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5507    && (GET_CODE (operands[2]) != REG
5508        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5509   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5510 [(set_attr "type" "load")])
5512 (define_insn "*strqi_shiftpreinc"
5513   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5514                           [(match_operand:SI 3 "s_register_operand" "r")
5515                            (match_operand:SI 4 "const_shift_operand" "n")])
5516                          (match_operand:SI 1 "s_register_operand" "0")))
5517         (match_operand:QI 5 "s_register_operand" "r"))
5518    (set (match_operand:SI 0 "s_register_operand" "=r")
5519         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5520                  (match_dup 1)))]
5521   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5522    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5523    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5524   "str%?b\\t%5, [%0, %3%S2]!"
5525 [(set_attr "type" "store1")])
5527 (define_insn "*strqi_shiftpredec"
5528   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5529                           (match_operator:SI 2 "shift_operator"
5530                            [(match_operand:SI 3 "s_register_operand" "r")
5531                             (match_operand:SI 4 "const_shift_operand" "n")])))
5532         (match_operand:QI 5 "s_register_operand" "r"))
5533    (set (match_operand:SI 0 "s_register_operand" "=r")
5534         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5535                                                  (match_dup 4)])))]
5536   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5537    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5538    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5539   "str%?b\\t%5, [%0, -%3%S2]!"
5540 [(set_attr "type" "store1")])
5542 (define_insn "*loadqi_shiftpreinc"
5543   [(set (match_operand:QI 5 "s_register_operand" "=r")
5544         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5545                           [(match_operand:SI 3 "s_register_operand" "r")
5546                            (match_operand:SI 4 "const_shift_operand" "n")])
5547                          (match_operand:SI 1 "s_register_operand" "0"))))
5548    (set (match_operand:SI 0 "s_register_operand" "=r")
5549         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5550                  (match_dup 1)))]
5551   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5552    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5553    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5554   "ldr%?b\\t%5, [%0, %3%S2]!"
5555 [(set_attr "type" "load")])
5557 (define_insn "*loadqi_shiftpredec"
5558   [(set (match_operand:QI 5 "s_register_operand" "=r")
5559         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5560                           (match_operator:SI 2 "shift_operator"
5561                            [(match_operand:SI 3 "s_register_operand" "r")
5562                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5563    (set (match_operand:SI 0 "s_register_operand" "=r")
5564         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5565                                                  (match_dup 4)])))]
5566   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5567    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5568    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5569   "ldr%?b\\t%5, [%0, -%3%S2]!"
5570 [(set_attr "type" "load")])
5572 (define_insn "*strsi_shiftpreinc"
5573   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5574                           [(match_operand:SI 3 "s_register_operand" "r")
5575                            (match_operand:SI 4 "const_shift_operand" "n")])
5576                          (match_operand:SI 1 "s_register_operand" "0")))
5577         (match_operand:SI 5 "s_register_operand" "r"))
5578    (set (match_operand:SI 0 "s_register_operand" "=r")
5579         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5580                  (match_dup 1)))]
5581   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5582    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5583    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5584   "str%?\\t%5, [%0, %3%S2]!"
5585 [(set_attr "type" "store1")])
5587 (define_insn "*strsi_shiftpredec"
5588   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5589                           (match_operator:SI 2 "shift_operator"
5590                            [(match_operand:SI 3 "s_register_operand" "r")
5591                             (match_operand:SI 4 "const_shift_operand" "n")])))
5592         (match_operand:SI 5 "s_register_operand" "r"))
5593    (set (match_operand:SI 0 "s_register_operand" "=r")
5594         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5595                                                  (match_dup 4)])))]
5596   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5597    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5598    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5599   "str%?\\t%5, [%0, -%3%S2]!"
5600 [(set_attr "type" "store1")])
5602 (define_insn "*loadqi_shiftpreinc"
5603   [(set (match_operand:SI 5 "s_register_operand" "=r")
5604         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5605                           [(match_operand:SI 3 "s_register_operand" "r")
5606                            (match_operand:SI 4 "const_shift_operand" "n")])
5607                          (match_operand:SI 1 "s_register_operand" "0"))))
5608    (set (match_operand:SI 0 "s_register_operand" "=r")
5609         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5610                  (match_dup 1)))]
5611   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5612    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5613    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5614   "ldr%?\\t%5, [%0, %3%S2]!"
5615 [(set_attr "type" "load")])
5617 (define_insn "*loadqi_shiftpredec"
5618   [(set (match_operand:SI 5 "s_register_operand" "=r")
5619         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5620                           (match_operator:SI 2 "shift_operator"
5621                            [(match_operand:SI 3 "s_register_operand" "r")
5622                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5623    (set (match_operand:SI 0 "s_register_operand" "=r")
5624         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5625                                                  (match_dup 4)])))]
5626   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5627    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5628    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5629   "ldr%?\\t%5, [%0, -%3%S2]!"
5630 [(set_attr "type" "load")])
5632 (define_insn "*loadhi_shiftpreinc"
5633   [(set (match_operand:HI 5 "s_register_operand" "=r")
5634         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5635                           [(match_operand:SI 3 "s_register_operand" "r")
5636                            (match_operand:SI 4 "const_shift_operand" "n")])
5637                          (match_operand:SI 1 "s_register_operand" "0"))))
5638    (set (match_operand:SI 0 "s_register_operand" "=r")
5639         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5640                  (match_dup 1)))]
5641   "(! BYTES_BIG_ENDIAN)
5642    && ! TARGET_SHORT_BY_BYTES
5643    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5644    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5645    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5646   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5647 [(set_attr "type" "load")])
5649 (define_insn "*loadhi_shiftpredec"
5650   [(set (match_operand:HI 5 "s_register_operand" "=r")
5651         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5652                           (match_operator:SI 2 "shift_operator"
5653                            [(match_operand:SI 3 "s_register_operand" "r")
5654                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5655    (set (match_operand:SI 0 "s_register_operand" "=r")
5656         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5657                                                  (match_dup 4)])))]
5658   "(! BYTES_BIG_ENDIAN)
5659    && ! TARGET_SHORT_BY_BYTES
5660    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5661    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5662    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5663   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5664 [(set_attr "type" "load")])
5666 ; It can also support extended post-inc expressions, but combine doesn't
5667 ; try these....
5668 ; It doesn't seem worth adding peepholes for anything but the most common
5669 ; cases since, unlike combine, the increment must immediately follow the load
5670 ; for this pattern to match.
5671 ; When loading we must watch to see that the base register isn't trampled by
5672 ; the load.  In such cases this isn't a post-inc expression.
5674 (define_peephole
5675   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5676         (match_operand:QI 2 "s_register_operand" "r"))
5677    (set (match_dup 0)
5678         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5679   ""
5680   "str%?b\\t%2, [%0], %1")
5682 (define_peephole
5683   [(set (match_operand:QI 0 "s_register_operand" "=r")
5684         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5685    (set (match_dup 1)
5686         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5687   "REGNO(operands[0]) != REGNO(operands[1])
5688    && (GET_CODE (operands[2]) != REG
5689        || REGNO(operands[0]) != REGNO (operands[2]))"
5690   "ldr%?b\\t%0, [%1], %2")
5692 (define_peephole
5693   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5694         (match_operand:SI 2 "s_register_operand" "r"))
5695    (set (match_dup 0)
5696         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5697   ""
5698   "str%?\\t%2, [%0], %1")
5700 (define_peephole
5701   [(set (match_operand:HI 0 "s_register_operand" "=r")
5702         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5703    (set (match_dup 1)
5704         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5705   "(! BYTES_BIG_ENDIAN)
5706    && ! TARGET_SHORT_BY_BYTES
5707    && REGNO(operands[0]) != REGNO(operands[1])
5708    && (GET_CODE (operands[2]) != REG
5709        || REGNO(operands[0]) != REGNO (operands[2]))"
5710   "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5712 (define_peephole
5713   [(set (match_operand:SI 0 "s_register_operand" "=r")
5714         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5715    (set (match_dup 1)
5716         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5717   "REGNO(operands[0]) != REGNO(operands[1])
5718    && (GET_CODE (operands[2]) != REG
5719        || REGNO(operands[0]) != REGNO (operands[2]))"
5720   "ldr%?\\t%0, [%1], %2")
5722 (define_peephole
5723   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5724                          (match_operand:SI 1 "index_operand" "rJ")))
5725         (match_operand:QI 2 "s_register_operand" "r"))
5726    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5727   ""
5728   "str%?b\\t%2, [%0, %1]!")
5730 (define_peephole
5731   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5732                           [(match_operand:SI 0 "s_register_operand" "r")
5733                            (match_operand:SI 1 "const_int_operand" "n")])
5734                          (match_operand:SI 2 "s_register_operand" "+r")))
5735         (match_operand:QI 3 "s_register_operand" "r"))
5736    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5737                                (match_dup 2)))]
5738   ""
5739   "str%?b\\t%3, [%2, %0%S4]!")
5741 ; This pattern is never tried by combine, so do it as a peephole
5743 (define_peephole
5744   [(set (match_operand:SI 0 "s_register_operand" "=r")
5745         (match_operand:SI 1 "s_register_operand" "r"))
5746    (set (reg:CC 24)
5747         (compare:CC (match_dup 1) (const_int 0)))]
5748   ""
5749   "sub%?s\\t%0, %1, #0"
5750 [(set_attr "conds" "set")])
5752 ; Peepholes to spot possible load- and store-multiples.
5754 (define_peephole
5755   [(set (match_operand:SI 0 "s_register_operand" "=r")
5756         (match_operand:SI 4 "memory_operand" "m"))
5757    (set (match_operand:SI 1 "s_register_operand" "=r")
5758         (match_operand:SI 5 "memory_operand" "m"))
5759    (set (match_operand:SI 2 "s_register_operand" "=r")
5760         (match_operand:SI 6 "memory_operand" "m"))
5761    (set (match_operand:SI 3 "s_register_operand" "=r")
5762         (match_operand:SI 7 "memory_operand" "m"))]
5763   "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5764   "*
5765   return emit_ldm_seq (operands, 4);
5768 (define_peephole
5769   [(set (match_operand:SI 0 "s_register_operand" "=r")
5770         (match_operand:SI 3 "memory_operand" "m"))
5771    (set (match_operand:SI 1 "s_register_operand" "=r")
5772         (match_operand:SI 4 "memory_operand" "m"))
5773    (set (match_operand:SI 2 "s_register_operand" "=r")
5774         (match_operand:SI 5 "memory_operand" "m"))]
5775   "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5776   "*
5777   return emit_ldm_seq (operands, 3);
5780 (define_peephole
5781   [(set (match_operand:SI 0 "s_register_operand" "=r")
5782         (match_operand:SI 2 "memory_operand" "m"))
5783    (set (match_operand:SI 1 "s_register_operand" "=r")
5784         (match_operand:SI 3 "memory_operand" "m"))]
5785   "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5786   "*
5787   return emit_ldm_seq (operands, 2);
5790 (define_peephole
5791   [(set (match_operand:SI 4 "memory_operand" "=m")
5792         (match_operand:SI 0 "s_register_operand" "r"))
5793    (set (match_operand:SI 5 "memory_operand" "=m")
5794         (match_operand:SI 1 "s_register_operand" "r"))
5795    (set (match_operand:SI 6 "memory_operand" "=m")
5796         (match_operand:SI 2 "s_register_operand" "r"))
5797    (set (match_operand:SI 7 "memory_operand" "=m")
5798         (match_operand:SI 3 "s_register_operand" "r"))]
5799   "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5800   "*
5801   return emit_stm_seq (operands, 4);
5804 (define_peephole
5805   [(set (match_operand:SI 3 "memory_operand" "=m")
5806         (match_operand:SI 0 "s_register_operand" "r"))
5807    (set (match_operand:SI 4 "memory_operand" "=m")
5808         (match_operand:SI 1 "s_register_operand" "r"))
5809    (set (match_operand:SI 5 "memory_operand" "=m")
5810         (match_operand:SI 2 "s_register_operand" "r"))]
5811   "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5812   "*
5813   return emit_stm_seq (operands, 3);
5816 (define_peephole
5817   [(set (match_operand:SI 2 "memory_operand" "=m")
5818         (match_operand:SI 0 "s_register_operand" "r"))
5819    (set (match_operand:SI 3 "memory_operand" "=m")
5820         (match_operand:SI 1 "s_register_operand" "r"))]
5821   "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5822   "*
5823   return emit_stm_seq (operands, 2);
5826 ;; A call followed by return can be replaced by restoring the regs and
5827 ;; jumping to the subroutine, provided we aren't passing the address of
5828 ;; any of our local variables.  If we call alloca then this is unsafe
5829 ;; since restoring the frame frees the memory, which is not what we want.
5830 ;; Sometimes the return might have been targeted by the final prescan:
5831 ;; if so then emit a proper return insn as well.
5832 ;; Unfortunately, if the frame pointer is required, we don't know if the
5833 ;; current function has any implicit stack pointer adjustments that will 
5834 ;; be restored by the return: we can't therefore do a tail call.
5835 ;; Another unfortunate that we can't handle is if current_function_args_size
5836 ;; is non-zero: in this case elimination of the argument pointer assumed
5837 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5838 ;; calculations.
5840 (define_peephole
5841   [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5842                           (match_operand:SI 1 "general_operand" "g"))
5843                     (clobber (reg:SI 14))])
5844    (return)]
5845   "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN
5846     && !get_frame_size () && !current_function_calls_alloca
5847     && !frame_pointer_needed && !current_function_args_size)"
5848   "*
5850   extern rtx arm_target_insn;
5851   extern int arm_ccfsm_state;
5853   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5854   {
5855     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5856     output_return_instruction (NULL, TRUE, FALSE);
5857     arm_ccfsm_state = 0;
5858     arm_target_insn = NULL;
5859   }
5861   output_return_instruction (NULL, FALSE, FALSE);
5862   return \"b%?\\t%a0\";
5864 [(set_attr "type" "call")
5865  (set_attr "length" "8")])
5867 (define_peephole
5868   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5869                    (call (mem:SI (match_operand:SI 1 "" "X"))
5870                          (match_operand:SI 2 "general_operand" "g")))
5871               (clobber (reg:SI 14))])
5872    (return)]
5873   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5874     && !get_frame_size () && !current_function_calls_alloca
5875     && !frame_pointer_needed && !current_function_args_size)"
5876   "*
5878   extern rtx arm_target_insn;
5879   extern int arm_ccfsm_state;
5881   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5882   {
5883     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5884     output_return_instruction (NULL, TRUE, FALSE);
5885     arm_ccfsm_state = 0;
5886     arm_target_insn = NULL;
5887   }
5889   output_return_instruction (NULL, FALSE, FALSE);
5890   return \"b%?\\t%a1\";
5892 [(set_attr "type" "call")
5893  (set_attr "length" "8")])
5895 ;; As above but when this function is not void, we must be returning the
5896 ;; result of the called subroutine.
5898 (define_peephole
5899   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5900                    (call (mem:SI (match_operand:SI 1 "" "X"))
5901                          (match_operand:SI 2 "general_operand" "g")))
5902               (clobber (reg:SI 14))])
5903    (use (match_dup 0))
5904    (return)]
5905   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5906     && !get_frame_size () && !current_function_calls_alloca
5907     && !frame_pointer_needed && !current_function_args_size)"
5908   "*
5910   extern rtx arm_target_insn;
5911   extern int arm_ccfsm_state;
5913   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5914   {
5915     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5916     output_return_instruction (NULL, TRUE, FALSE);
5917     arm_ccfsm_state = 0;
5918     arm_target_insn = NULL;
5919   }
5921   output_return_instruction (NULL, FALSE, FALSE);
5922   return \"b%?\\t%a1\";
5924 [(set_attr "type" "call")
5925  (set_attr "length" "8")])
5927 (define_split
5928   [(set (match_operand:SI 0 "s_register_operand" "")
5929         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
5930                        (const_int 0))
5931                 (neg:SI (match_operator:SI 2 "comparison_operator"
5932                          [(match_operand:SI 3 "s_register_operand" "")
5933                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
5934    (clobber (match_operand:SI 5 "s_register_operand" ""))]
5935   ""
5936   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
5937    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5938                               (match_dup 5)))]
5939   "")
5941 ;; This split can be used because CC_Z mode implies that the following
5942 ;; branch will be an equality, or an unsigned inequality, so the sign
5943 ;; extension is not needed.
5945 (define_split
5946   [(set (reg:CC_Z 24)
5947         (compare:CC_Z
5948          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
5949                     (const_int 24))
5950          (match_operand 1 "const_int_operand" "")))
5951    (clobber (match_scratch:SI 2 ""))]
5952   "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
5953    == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
5954   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
5955    (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
5956   "
5957   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
5960 (define_expand "prologue"
5961   [(clobber (const_int 0))]
5962   ""
5963   "
5964   arm_expand_prologue ();
5965   DONE;
5968 ;; This split is only used during output to reduce the number of patterns
5969 ;; that need assembler instructions adding to them.  We allowed the setting
5970 ;; of the conditions to be implicit during rtl generation so that
5971 ;; the conditional compare patterns would work.  However this conflicts to
5972 ;; some extent with the conditional data operations, so we have to split them
5973 ;; up again here.
5975 (define_split
5976   [(set (match_operand:SI 0 "s_register_operand" "")
5977         (if_then_else:SI (match_operator 1 "comparison_operator"
5978                           [(match_operand 2 "" "") (match_operand 3 "" "")])
5979                          (match_operand 4 "" "")
5980                          (match_operand 5 "" "")))
5981    (clobber (reg 24))]
5982   "reload_completed"
5983   [(set (match_dup 6) (match_dup 7))
5984    (set (match_dup 0) 
5985         (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
5986                          (match_dup 4)
5987                          (match_dup 5)))]
5988   "
5990   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
5991                                            operands[3]);
5993   operands[6] = gen_rtx (REG, mode, 24);
5994   operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
5999 ;; The next two patterns occur when an AND operation is followed by a
6000 ;; scc insn sequence 
6002 (define_insn "*sign_extract_onebit"
6003   [(set (match_operand:SI 0 "s_register_operand" "=r")
6004         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6005                          (const_int 1)
6006                          (match_operand:SI 2 "const_int_operand" "n")))]
6007   ""
6008   "*
6009   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6010   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6011   return \"mvnne\\t%0, #0\";
6013 [(set_attr "conds" "clob")
6014  (set_attr "length" "8")])
6016 (define_insn "*not_signextract_onebit"
6017   [(set (match_operand:SI 0 "s_register_operand" "=r")
6018         (not:SI
6019          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6020                           (const_int 1)
6021                           (match_operand:SI 2 "const_int_operand" "n"))))]
6022   ""
6023   "*
6024   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6025   output_asm_insn (\"tst\\t%1, %2\", operands);
6026   output_asm_insn (\"mvneq\\t%0, #0\", operands);
6027   return \"movne\\t%0, #0\";
6029 [(set_attr "conds" "clob")
6030  (set_attr "length" "12")])
6032 ;; Push multiple registers to the stack.  The first register is in the
6033 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
6034 ;; expressions.
6035 (define_insn "*push_multi"
6036   [(match_parallel 2 "multi_register_push"
6037     [(set (match_operand:BLK 0 "memory_operand" "=m")
6038           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
6039   ""
6040   "*
6042   char pattern[100];
6043   int i;
6044   extern int lr_save_eliminated;
6046   if (lr_save_eliminated)
6047     {
6048       if (XVECLEN (operands[2], 0) > 1)
6049         abort ();
6050       return \"\";
6051     }
6052   strcpy (pattern, \"stmfd\\t%m0!, {%1\");
6053   for (i = 1; i < XVECLEN (operands[2], 0); i++)
6054     {
6055       strcat (pattern, \", %|\");
6056       strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
6057                                               0))]);
6058     }
6059   strcat (pattern, \"}\");
6060   output_asm_insn (pattern, operands);
6061   return \"\";
6063 [(set_attr "type" "store4")])
6065 ;; Similarly for the the floating point registers
6066 (define_insn "*push_fp_multi"
6067   [(match_parallel 2 "multi_register_push"
6068     [(set (match_operand:BLK 0 "memory_operand" "=m")
6069           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
6070   ""
6071   "*
6073   char pattern[100];
6074   int i;
6076   sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
6077   output_asm_insn (pattern, operands);
6078   return \"\";
6080 [(set_attr "type" "f_store")])
6082 ;; Special patterns for dealing with the constant pool
6084 (define_insn "consttable_4"
6085   [(unspec_volatile [(match_operand 0 "" "")] 2)]
6086   ""
6087   "*
6089   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6090     {
6091     case MODE_FLOAT:
6092     {
6093       union real_extract u;
6094       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6095       assemble_real (u.d, GET_MODE (operands[0]));
6096       break;
6097     }
6098     default:
6099       assemble_integer (operands[0], 4, 1);
6100       break;
6101     }
6102   return \"\";
6104 [(set_attr "length" "4")])
6106 (define_insn "consttable_8"
6107   [(unspec_volatile [(match_operand 0 "" "")] 3)]
6108   ""
6109   "*
6111   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6112     {
6113     case MODE_FLOAT:
6114     {
6115       union real_extract u;
6116       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6117       assemble_real (u.d, GET_MODE (operands[0]));
6118       break;
6119     }
6120     default:
6121       assemble_integer (operands[0], 8, 1);
6122       break;
6123     }
6124   return \"\";
6126 [(set_attr "length" "8")])
6128 (define_insn "consttable_end"
6129   [(unspec_volatile [(const_int 0)] 4)]
6130   ""
6131   "*
6132   /* Nothing to do (currently).  */
6133   return \"\";
6136 (define_insn "align_4"
6137   [(unspec_volatile [(const_int 0)] 5)]
6138   ""
6139   "*
6140   assemble_align (32);
6141   return \"\";