(attr cpu): Add new cpu types for arm8 and strongarm.
[official-gcc.git] / gcc / config / arm / arm.md
blobd28a3a0bf328aacc22d6226a1b5a3ca8f572e7ea
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 "mulsf3"
863   [(set (match_operand:SF 0 "s_register_operand" "=f")
864         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
865                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
866   "TARGET_HARD_FLOAT"
867   "fml%?s\\t%0, %1, %2"
868 [(set_attr "type" "ffmul")])
870 (define_insn "muldf3"
871   [(set (match_operand:DF 0 "s_register_operand" "=f")
872         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
873                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
874   "TARGET_HARD_FLOAT"
875   "muf%?d\\t%0, %1, %2"
876 [(set_attr "type" "fmul")])
878 (define_insn "*muldf_esfdf_df"
879   [(set (match_operand:DF 0 "s_register_operand" "=f")
880         (mult:DF (float_extend:DF
881                   (match_operand:SF 1 "s_register_operand" "f"))
882                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
883   "TARGET_HARD_FLOAT"
884   "muf%?d\\t%0, %1, %2"
885 [(set_attr "type" "fmul")])
887 (define_insn "*muldf_df_esfdf"
888   [(set (match_operand:DF 0 "s_register_operand" "=f")
889         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
890                  (float_extend:DF
891                   (match_operand:SF 2 "s_register_operand" "f"))))]
892   "TARGET_HARD_FLOAT"
893   "muf%?d\\t%0, %1, %2"
894 [(set_attr "type" "fmul")])
896 (define_insn "*muldf_esfdf_esfdf"
897   [(set (match_operand:DF 0 "s_register_operand" "=f")
898         (mult:DF (float_extend:DF
899                   (match_operand:SF 1 "s_register_operand" "f"))
900                  (float_extend:DF
901                   (match_operand:SF 2 "s_register_operand" "f"))))]
902   "TARGET_HARD_FLOAT"
903   "muf%?d\\t%0, %1, %2"
904 [(set_attr "type" "fmul")])
906 (define_insn "mulxf3"
907   [(set (match_operand:XF 0 "s_register_operand" "=f")
908         (mult:XF (match_operand:XF 1 "s_register_operand" "f")
909                  (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
910   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
911   "muf%?e\\t%0, %1, %2"
912 [(set_attr "type" "fmul")])
914 ;; Division insns
916 (define_insn "divsf3"
917   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
918         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
919                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
920   "TARGET_HARD_FLOAT"
921   "@
922    fdv%?s\\t%0, %1, %2
923    frd%?s\\t%0, %2, %1"
924 [(set_attr "type" "fdivs")])
926 (define_insn "divdf3"
927   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
928         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
929                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
930   "TARGET_HARD_FLOAT"
931   "@
932    dvf%?d\\t%0, %1, %2
933    rdf%?d\\t%0, %2, %1"
934 [(set_attr "type" "fdivd")])
936 (define_insn "*divdf_esfdf_df"
937   [(set (match_operand:DF 0 "s_register_operand" "=f")
938         (div:DF (float_extend:DF
939                  (match_operand:SF 1 "s_register_operand" "f"))
940                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
941   "TARGET_HARD_FLOAT"
942   "dvf%?d\\t%0, %1, %2"
943 [(set_attr "type" "fdivd")])
945 (define_insn "*divdf_df_esfdf"
946   [(set (match_operand:DF 0 "s_register_operand" "=f")
947         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
948                 (float_extend:DF
949                  (match_operand:SF 2 "s_register_operand" "f"))))]
950   "TARGET_HARD_FLOAT"
951   "rdf%?d\\t%0, %2, %1"
952 [(set_attr "type" "fdivd")])
954 (define_insn "*divdf_esfdf_esfdf"
955   [(set (match_operand:DF 0 "s_register_operand" "=f")
956         (div:DF (float_extend:DF
957                  (match_operand:SF 1 "s_register_operand" "f"))
958                 (float_extend:DF
959                  (match_operand:SF 2 "s_register_operand" "f"))))]
960   "TARGET_HARD_FLOAT"
961   "dvf%?d\\t%0, %1, %2"
962 [(set_attr "type" "fdivd")])
964 (define_insn "divxf3"
965   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
966         (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
967                 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
968   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
969   "@
970    dvf%?e\\t%0, %1, %2
971    rdf%?e\\t%0, %2, %1"
972 [(set_attr "type" "fdivx")])
974 ;; Modulo insns
976 (define_insn "modsf3"
977   [(set (match_operand:SF 0 "s_register_operand" "=f")
978         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
979                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
980   "TARGET_HARD_FLOAT"
981   "rmf%?s\\t%0, %1, %2"
982 [(set_attr "type" "fdivs")])
984 (define_insn "moddf3"
985   [(set (match_operand:DF 0 "s_register_operand" "=f")
986         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
987                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
988   "TARGET_HARD_FLOAT"
989   "rmf%?d\\t%0, %1, %2"
990 [(set_attr "type" "fdivd")])
992 (define_insn "*moddf_esfdf_df"
993   [(set (match_operand:DF 0 "s_register_operand" "=f")
994         (mod:DF (float_extend:DF
995                  (match_operand:SF 1 "s_register_operand" "f"))
996                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
997   "TARGET_HARD_FLOAT"
998   "rmf%?d\\t%0, %1, %2"
999 [(set_attr "type" "fdivd")])
1001 (define_insn "*moddf_df_esfdf"
1002   [(set (match_operand:DF 0 "s_register_operand" "=f")
1003         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1004                 (float_extend:DF
1005                  (match_operand:SF 2 "s_register_operand" "f"))))]
1006   "TARGET_HARD_FLOAT"
1007   "rmf%?d\\t%0, %1, %2"
1008 [(set_attr "type" "fdivd")])
1010 (define_insn "*moddf_esfdf_esfdf"
1011   [(set (match_operand:DF 0 "s_register_operand" "=f")
1012         (mod:DF (float_extend:DF
1013                  (match_operand:SF 1 "s_register_operand" "f"))
1014                 (float_extend:DF
1015                  (match_operand:SF 2 "s_register_operand" "f"))))]
1016   "TARGET_HARD_FLOAT"
1017   "rmf%?d\\t%0, %1, %2"
1018 [(set_attr "type" "fdivd")])
1020 (define_insn "modxf3"
1021   [(set (match_operand:XF 0 "s_register_operand" "=f")
1022         (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1023                 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1024   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1025   "rmf%?e\\t%0, %1, %2"
1026 [(set_attr "type" "fdivx")])
1028 ;; Boolean and,ior,xor insns
1030 (define_insn "anddi3"
1031   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1032         (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1033                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1034   ""
1035   "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2"
1036 [(set_attr "length" "8")])
1038 (define_insn "*anddi_zesidi_di"
1039   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1040         (and:DI (zero_extend:DI
1041                  (match_operand:SI 2 "s_register_operand" "r,r"))
1042                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1043   ""
1044   "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0"
1045 [(set_attr "length" "8")])
1047 (define_insn "*anddi_sesdi_di"
1048   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1049         (and:DI (sign_extend:DI
1050                  (match_operand:SI 2 "s_register_operand" "r,r"))
1051                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1052   ""
1053   "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31"
1054 [(set_attr "length" "8")])
1056 (define_expand "andsi3"
1057   [(set (match_operand:SI 0 "s_register_operand" "")
1058         (and:SI (match_operand:SI 1 "s_register_operand" "")
1059                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1060   ""
1061   "
1062   if (GET_CODE (operands[2]) == CONST_INT)
1063     {
1064       arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1065                           operands[1],
1066                           (reload_in_progress || reload_completed
1067                            ? 0 : preserve_subexpressions_p ()));
1068       DONE;
1069     }
1072 (define_insn "*andsi3_insn"
1073   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1074         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1075                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1076   ""
1077   "@
1078    and%?\\t%0, %1, %2
1079    bic%?\\t%0, %1, #%B2
1080    #"
1081 [(set_attr "length" "4,4,16")])
1083 (define_split
1084   [(set (match_operand:SI 0 "s_register_operand" "")
1085         (and:SI (match_operand:SI 1 "s_register_operand" "")
1086                 (match_operand:SI 2 "const_int_operand" "")))]
1087   "! (const_ok_for_arm (INTVAL (operands[2]))
1088       || const_ok_for_arm (~ INTVAL (operands[2])))"
1089   [(clobber (const_int 0))]
1090   "
1091   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1092                        operands[1], 0);
1093   DONE;
1096 (define_insn "*andsi3_compare0"
1097   [(set (reg:CC_NOOV 24)
1098         (compare:CC_NOOV
1099          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1100                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1101          (const_int 0)))
1102    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1103         (and:SI (match_dup 1) (match_dup 2)))]
1104   ""
1105   "@
1106    and%?s\\t%0, %1, %2
1107    bic%?s\\t%0, %1, #%B2"
1108 [(set_attr "conds" "set")])
1110 (define_insn "*andsi3_compare0_scratch"
1111   [(set (reg:CC_NOOV 24)
1112         (compare:CC_NOOV
1113          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1114                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1115          (const_int 0)))
1116    (clobber (match_scratch:SI 3 "=X,r"))]
1117   ""
1118   "@
1119    tst%?\\t%0, %1
1120    bic%?s\\t%3, %0, #%B1"
1121 [(set_attr "conds" "set")])
1123 (define_insn "*zeroextractsi_compare0_scratch"
1124   [(set (reg:CC_NOOV 24)
1125         (compare:CC_NOOV (zero_extract:SI
1126                           (match_operand:SI 0 "s_register_operand" "r")
1127                           (match_operand 1 "const_int_operand" "n")
1128                           (match_operand 2 "const_int_operand" "n"))
1129                          (const_int 0)))]
1130   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1131    && INTVAL (operands[1]) > 0 
1132    && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1133    && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1134   "*
1136   unsigned int mask = 0;
1137   int cnt = INTVAL (operands[1]);
1138   
1139   while (cnt--)
1140     mask = (mask << 1) | 1;
1141   operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1142   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1143   return \"\";
1146 [(set_attr "conds" "set")])
1148 (define_insn "*zeroextractqi_compare0_scratch"
1149   [(set (reg:CC_NOOV 24)
1150         (compare:CC_NOOV (zero_extract:SI
1151                           (match_operand:QI 0 "memory_operand" "m")
1152                           (match_operand 1 "const_int_operand" "n")
1153                           (match_operand 2 "const_int_operand" "n"))
1154                          (const_int 0)))
1155    (clobber (match_scratch:QI 3 "=r"))]
1156   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 8
1157    && INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8"
1158   "*
1160   unsigned int mask = 0;
1161   int cnt = INTVAL (operands[1]);
1162   
1163   while (cnt--)
1164     mask = (mask << 1) | 1;
1165   operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1166   output_asm_insn (\"ldr%?b\\t%3, %0\", operands);
1167   output_asm_insn (\"tst%?\\t%3, %1\", operands);
1168   return \"\";
1171 [(set_attr "conds" "set")
1172  (set_attr "length" "8")])
1174 (define_expand "insv"
1175   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1176                          (match_operand:SI 1 "general_operand" "")
1177                          (match_operand:SI 2 "general_operand" ""))
1178         (match_operand:SI 3 "nonmemory_operand" ""))]
1179   ""
1180   "
1182   HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << INTVAL (operands[1])) - 1;
1184   if (GET_CODE (operands[3]) == CONST_INT)
1185     {
1186       /* Since we are inserting a known constant, we may be able to
1187          reduce the number of bits that we have to clear so that
1188          the mask becomes simple.  */
1189       rtx op1 = gen_reg_rtx (SImode);
1190       HOST_WIDE_INT mask2 = ((mask & ~INTVAL (operands[3]))
1191                              << INTVAL (operands[2]));
1193       emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1194       emit_insn (gen_iorsi3 (operands[0], op1,
1195                              GEN_INT (INTVAL (operands[3])
1196                                       << INTVAL (operands[2]))));
1197     }
1198   else if (INTVAL (operands[2]) == 0
1199            && ! (const_ok_for_arm (mask)
1200                  || const_ok_for_arm (~mask)))
1201     {
1202       /* A Trick, since we are setting the bottom bits in the word,
1203          we can shift operand[3] up, operand[0] down, OR them together
1204          and rotate the result back again.  This takes 3 insns, and
1205          the third might be mergable into another op.  */
1207       rtx op0 = gen_reg_rtx (SImode);
1208       rtx op1 = gen_reg_rtx (SImode);
1210       emit_insn (gen_ashlsi3 (op0, operands[3],
1211                               GEN_INT (32 - INTVAL (operands[1]))));
1212       emit_insn (gen_iorsi3 (op1, gen_rtx (LSHIFTRT, SImode, operands[0],
1213                                            operands[1]),
1214                              op0));
1215       emit_insn (gen_rotlsi3 (operands[0], op1, operands[1]));
1216     }
1217   else if ((INTVAL (operands[1]) + INTVAL (operands[2]) == 32)
1218            && ! (const_ok_for_arm (mask)
1219                  || const_ok_for_arm (~mask)))
1220     {
1221       /* Similar trick, but slightly less efficient.  */
1223       rtx op0 = gen_reg_rtx (SImode);
1224       rtx op1 = gen_reg_rtx (SImode);
1226       emit_insn (gen_ashlsi3 (op0, operands[3],
1227                               GEN_INT (32 - INTVAL (operands[1]))));
1228       emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1229       emit_insn (gen_iorsi3 (operands[0], gen_rtx (LSHIFTRT, SImode, op1,
1230                                                    operands[1]), op0));
1231     }
1232   else
1233     {
1234       rtx op0 = GEN_INT (mask);
1235       rtx op1 = gen_reg_rtx (SImode);
1236       rtx op2 = gen_reg_rtx (SImode);
1238       if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1239         {
1240           rtx tmp = gen_reg_rtx (SImode);
1242           emit_insn (gen_movsi (tmp, op0));
1243           op0 = tmp;
1244         }
1246       emit_insn (gen_andsi3 (op1, operands[3], op0));
1248       if (GET_CODE (op0) == CONST_INT
1249           && (const_ok_for_arm (mask << INTVAL (operands[2]))
1250               || const_ok_for_arm (~ (mask << INTVAL (operands[2])))))
1251         {
1252           op0 = GEN_INT (~(mask << INTVAL (operands[2])));
1253           emit_insn (gen_andsi3 (op2, operands[0], op0));
1254         }
1255       else
1256         {
1257           if (GET_CODE (op0) == CONST_INT)
1258             {
1259               rtx tmp = gen_reg_rtx (SImode);
1261               emit_insn (gen_movsi (tmp, op0));
1262               op0 = tmp;
1263             }
1265           if (INTVAL (operands[2]) != 0)
1266             op0 = gen_rtx (ASHIFT, SImode, op0, operands[2]);
1267           emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1268         }
1270       if (INTVAL (operands[2]) != 0)
1271         op1 = gen_rtx (ASHIFT, SImode, op1, operands[2]);
1273       emit_insn (gen_iorsi3 (operands[0], op1, op2));
1274     }
1276   DONE;
1280 ;; constants for op 2 will never be given to these patterns.
1281 (define_insn "*anddi_notdi_di"
1282   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1283         (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1284                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1285   ""
1286   "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2"
1287 [(set_attr "length" "8")])
1288   
1289 (define_insn "*anddi_notzesidi_di"
1290   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1291         (and:DI (not:DI (zero_extend:DI
1292                          (match_operand:SI 2 "s_register_operand" "r,r")))
1293                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1294   ""
1295   "@
1296    bic%?\\t%Q0, %Q1, %2
1297    bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1298 [(set_attr "length" "4,8")])
1299   
1300 (define_insn "*anddi_notsesidi_di"
1301   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1302         (and:DI (not:DI (sign_extend:DI
1303                          (match_operand:SI 2 "s_register_operand" "r,r")))
1304                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1305   ""
1306   "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
1307 [(set_attr "length" "8")])
1308   
1309 (define_insn "andsi_notsi_si"
1310   [(set (match_operand:SI 0 "s_register_operand" "=r")
1311         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1312                 (match_operand:SI 1 "s_register_operand" "r")))]
1313   ""
1314   "bic%?\\t%0, %1, %2")
1316 (define_insn "andsi_not_shiftsi_si"
1317   [(set (match_operand:SI 0 "s_register_operand" "=r")
1318         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1319                          [(match_operand:SI 2 "s_register_operand" "r")
1320                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1321                 (match_operand:SI 1 "s_register_operand" "r")))]
1322   ""
1323   "bic%?\\t%0, %1, %2%S4")
1325 (define_insn "*andsi_notsi_si_compare0"
1326   [(set (reg:CC_NOOV 24)
1327         (compare:CC_NOOV
1328          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1329                  (match_operand:SI 1 "s_register_operand" "r"))
1330          (const_int 0)))
1331    (set (match_operand:SI 0 "s_register_operand" "=r")
1332         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1333   ""
1334   "bic%?s\\t%0, %1, %2"
1335 [(set_attr "conds" "set")])
1337 (define_insn "*andsi_notsi_si_compare0_scratch"
1338   [(set (reg:CC_NOOV 24)
1339         (compare:CC_NOOV
1340          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1341                  (match_operand:SI 1 "s_register_operand" "r"))
1342          (const_int 0)))
1343    (clobber (match_scratch:SI 0 "=r"))]
1344   ""
1345   "bic%?s\\t%0, %1, %2"
1346 [(set_attr "conds" "set")])
1348 (define_insn "iordi3"
1349   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1350         (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1351                 (match_operand:DI 2 "s_register_operand" "r")))]
1352   ""
1353   "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2"
1354 [(set_attr "length" "8")])
1356 (define_insn "*iordi_zesidi_di"
1357   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1358         (ior:DI (zero_extend:DI
1359                  (match_operand:SI 2 "s_register_operand" "r,r"))
1360                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1361   ""
1362   "@
1363    orr%?\\t%Q0, %Q1, %2
1364    orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1365 [(set_attr "length" "4,8")])
1367 (define_insn "*iordi_sesidi_di"
1368   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1369         (ior:DI (sign_extend:DI
1370                  (match_operand:SI 2 "s_register_operand" "r,r"))
1371                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1372   ""
1373   "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1374 [(set_attr "length" "8")])
1376 (define_expand "iorsi3"
1377   [(set (match_operand:SI 0 "s_register_operand" "")
1378         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1379                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1380   ""
1381   "
1382   if (GET_CODE (operands[2]) == CONST_INT)
1383     {
1384       arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1385                           operands[1],
1386                           (reload_in_progress || reload_completed
1387                            ? 0 : preserve_subexpressions_p ()));
1388       DONE;
1389     }
1392 (define_insn "*iorsi3_insn"
1393   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1394         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1395                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1396   ""
1397   "@
1398    orr%?\\t%0, %1, %2
1399    #"
1400 [(set_attr "length" "4,16")])
1402 (define_split
1403   [(set (match_operand:SI 0 "s_register_operand" "")
1404         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1405                 (match_operand:SI 2 "const_int_operand" "")))]
1406   "! const_ok_for_arm (INTVAL (operands[2]))"
1407   [(clobber (const_int 0))]
1408   "
1409   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1410                       operands[1], 0);
1411   DONE;
1413   
1414 (define_insn "*iorsi3_compare0"
1415   [(set (reg:CC_NOOV 24)
1416         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1417                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1418                          (const_int 0)))
1419    (set (match_operand:SI 0 "s_register_operand" "=r")
1420         (ior:SI (match_dup 1) (match_dup 2)))]
1421   ""
1422   "orr%?s\\t%0, %1, %2"
1423 [(set_attr "conds" "set")])
1425 (define_insn "*iorsi3_compare0_scratch"
1426   [(set (reg:CC_NOOV 24)
1427         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1428                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1429                          (const_int 0)))
1430    (clobber (match_scratch:SI 0 "=r"))]
1431   ""
1432   "orr%?s\\t%0, %1, %2"
1433 [(set_attr "conds" "set")])
1435 (define_insn "xordi3"
1436   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1437         (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1438                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1439   ""
1440   "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2"
1441 [(set_attr "length" "8")])
1443 (define_insn "*xordi_zesidi_di"
1444   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1445         (xor:DI (zero_extend:DI
1446                  (match_operand:SI 2 "s_register_operand" "r,r"))
1447                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1448   ""
1449   "@
1450    eor%?\\t%Q0, %Q1, %2
1451    eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1452 [(set_attr "length" "4,8")])
1454 (define_insn "*xordi_sesidi_di"
1455   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1456         (xor:DI (sign_extend:DI
1457                  (match_operand:SI 2 "s_register_operand" "r,r"))
1458                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1459   ""
1460   "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1461 [(set_attr "length" "8")])
1463 (define_insn "xorsi3"
1464   [(set (match_operand:SI 0 "s_register_operand" "=r")
1465         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1466                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1467   ""
1468   "eor%?\\t%0, %1, %2")
1470 (define_insn "*xorsi3_compare0"
1471   [(set (reg:CC_NOOV 24)
1472         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1473                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1474                          (const_int 0)))
1475    (set (match_operand:SI 0 "s_register_operand" "=r")
1476         (xor:SI (match_dup 1) (match_dup 2)))]
1477   ""
1478   "eor%?s\\t%0, %1, %2"
1479 [(set_attr "conds" "set")])
1481 (define_insn "*xorsi3_compare0_scratch"
1482   [(set (reg:CC_NOOV 24)
1483         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1484                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
1485                          (const_int 0)))]
1486   ""
1487   "teq%?\\t%0, %1"
1488 [(set_attr "conds" "set")])
1490 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
1491 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1492 ;; insns
1494 (define_split
1495   [(set (match_operand:SI 0 "s_register_operand" "=r")
1496         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1497                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1498                 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1499    (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1500   ""
1501   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1502                               (not:SI (match_dup 3))))
1503    (set (match_dup 0) (not:SI (match_dup 4)))]
1504   ""
1507 (define_insn "*andsi_iorsi3_notsi"
1508   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1509         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1510                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1511                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1512   ""
1513   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1514 [(set_attr "length" "8")])
1518 ;; Minimum and maximum insns
1520 (define_insn "smaxsi3"
1521   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1522         (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1523                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1524    (clobber (reg:CC 24))]
1525   ""
1526   "@
1527    cmp\\t%1, %2\;movlt\\t%0, %2
1528    cmp\\t%1, %2\;movge\\t%0, %1
1529    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1530 [(set_attr "conds" "clob")
1531  (set_attr "length" "8,8,12")])
1533 (define_insn "sminsi3"
1534   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1535         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1536                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1537    (clobber (reg:CC 24))]
1538   ""
1539   "@
1540    cmp\\t%1, %2\;movge\\t%0, %2
1541    cmp\\t%1, %2\;movlt\\t%0, %1
1542    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1543 [(set_attr "conds" "clob")
1544  (set_attr "length" "8,8,12")])
1546 (define_insn "umaxsi3"
1547   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1548         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1549                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1550    (clobber (reg:CC 24))]
1551   ""
1552   "@
1553    cmp\\t%1, %2\;movcc\\t%0, %2
1554    cmp\\t%1, %2\;movcs\\t%0, %1
1555    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1556 [(set_attr "conds" "clob")
1557  (set_attr "length" "8,8,12")])
1559 (define_insn "uminsi3"
1560   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1561         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1562                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1563    (clobber (reg:CC 24))]
1564   ""
1565   "@
1566    cmp\\t%1, %2\;movcs\\t%0, %2
1567    cmp\\t%1, %2\;movcc\\t%0, %1
1568    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1569 [(set_attr "conds" "clob")
1570  (set_attr "length" "8,8,12")])
1572 (define_insn "*store_minmaxsi"
1573   [(set (match_operand:SI 0 "memory_operand" "=m")
1574         (match_operator:SI 3 "minmax_operator"
1575          [(match_operand:SI 1 "s_register_operand" "r")
1576           (match_operand:SI 2 "s_register_operand" "r")]))
1577    (clobber (reg:CC 24))]
1578   ""
1579   "*
1580   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1581                          operands[2]);
1582   output_asm_insn (\"cmp\\t%1, %2\", operands);
1583   output_asm_insn (\"str%d3\\t%1, %0\", operands);
1584   output_asm_insn (\"str%D3\\t%2, %0\", operands);
1585   return \"\";
1587 [(set_attr "conds" "clob")
1588  (set_attr "length" "12")
1589  (set_attr "type" "store1")])
1591 ; Reject the frame pointer in operand[1], since reloading this after
1592 ; it has been eliminated can cause carnage.
1593 (define_insn "*minmax_arithsi"
1594   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1595         (match_operator:SI 4 "shiftable_operator"
1596          [(match_operator:SI 5 "minmax_operator"
1597            [(match_operand:SI 2 "s_register_operand" "r,r")
1598             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1599           (match_operand:SI 1 "s_register_operand" "0,?r")]))
1600    (clobber (reg:CC 24))]
1601   "GET_CODE (operands[1]) != REG
1602    || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
1603        && REGNO(operands[1]) != ARG_POINTER_REGNUM)"
1604   "*
1606   enum rtx_code code = GET_CODE (operands[4]);
1608   operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1609                          operands[3]);
1610   output_asm_insn (\"cmp\\t%2, %3\", operands);
1611   output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1612   if (which_alternative != 0 || operands[3] != const0_rtx
1613       || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1614     output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1615   return \"\";
1618 [(set_attr "conds" "clob")
1619  (set_attr "length" "12")])
1622 ;; Shift and rotation insns
1624 (define_expand "ashlsi3"
1625   [(set (match_operand:SI 0 "s_register_operand" "")
1626         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
1627                    (match_operand:SI 2 "arm_rhs_operand" "")))]
1628   ""
1629   "
1630   if (GET_CODE (operands[2]) == CONST_INT
1631       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1632     {
1633       emit_insn (gen_movsi (operands[0], const0_rtx));
1634       DONE;
1635     }
1638 (define_expand "ashrsi3"
1639   [(set (match_operand:SI 0 "s_register_operand" "")
1640         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1641                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1642   ""
1643   "
1644   if (GET_CODE (operands[2]) == CONST_INT
1645       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1646     operands[2] = GEN_INT (31);
1649 (define_expand "lshrsi3"
1650   [(set (match_operand:SI 0 "s_register_operand" "")
1651         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1652                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1653   ""
1654   "
1655   if (GET_CODE (operands[2]) == CONST_INT
1656       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1657     {
1658       emit_insn (gen_movsi (operands[0], const0_rtx));
1659       DONE;
1660     }
1663 (define_expand "rotlsi3"
1664   [(set (match_operand:SI 0 "s_register_operand" "")
1665         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1666                      (match_operand:SI 2 "reg_or_int_operand" "")))]
1667   ""
1668   "
1669   if (GET_CODE (operands[2]) == CONST_INT)
1670     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1671   else
1672     {
1673       rtx reg = gen_reg_rtx (SImode);
1674       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1675       operands[2] = reg;
1676     }
1679 (define_expand "rotrsi3"
1680   [(set (match_operand:SI 0 "s_register_operand" "")
1681         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1682                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1683   ""
1684   "
1685   if (GET_CODE (operands[2]) == CONST_INT
1686       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1687     operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1690 (define_insn "*shiftsi3"
1691   [(set (match_operand:SI 0 "s_register_operand" "=r")
1692         (match_operator:SI 3 "shift_operator"
1693          [(match_operand:SI 1 "s_register_operand" "r")
1694           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1695   ""
1696   "mov%?\\t%0, %1%S3")
1698 (define_insn "*shiftsi3_compare0"
1699   [(set (reg:CC_NOOV 24)
1700         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1701                           [(match_operand:SI 1 "s_register_operand" "r")
1702                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1703                          (const_int 0)))
1704    (set (match_operand:SI 0 "s_register_operand" "=r")
1705         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1706   ""
1707   "mov%?s\\t%0, %1%S3"
1708 [(set_attr "conds" "set")])
1710 (define_insn "*shiftsi3_compare0_scratch"
1711   [(set (reg:CC_NOOV 24)
1712         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1713                           [(match_operand:SI 1 "s_register_operand" "r")
1714                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1715                          (const_int 0)))
1716    (clobber (match_scratch:SI 0 "=r"))]
1717   ""
1718   "mov%?s\\t%0, %1%S3"
1719 [(set_attr "conds" "set")])
1721 (define_insn "*notsi_shiftsi"
1722   [(set (match_operand:SI 0 "s_register_operand" "=r")
1723         (not:SI (match_operator:SI 3 "shift_operator"
1724                  [(match_operand:SI 1 "s_register_operand" "r")
1725                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1726   ""
1727   "mvn%?\\t%0, %1%S3")
1729 (define_insn "*notsi_shiftsi_compare0"
1730   [(set (reg:CC_NOOV 24)
1731         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1732                           [(match_operand:SI 1 "s_register_operand" "r")
1733                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1734                          (const_int 0)))
1735    (set (match_operand:SI 0 "s_register_operand" "=r")
1736         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1737   ""
1738   "mvn%?s\\t%0, %1%S3"
1739 [(set_attr "conds" "set")])
1741 (define_insn "*not_shiftsi_compare0_scratch"
1742   [(set (reg:CC_NOOV 24)
1743         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1744                           [(match_operand:SI 1 "s_register_operand" "r")
1745                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1746                          (const_int 0)))
1747    (clobber (match_scratch:SI 0 "=r"))]
1748   ""
1749   "mvn%?s\\t%0, %1%S3"
1750 [(set_attr "conds" "set")])
1753 ;; Unary arithmetic insns
1755 (define_insn "negdi2"
1756   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1757         (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1758   ""
1759   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
1760 [(set_attr "conds" "clob")
1761  (set_attr "length" "8")])
1763 (define_insn "negsi2"
1764   [(set (match_operand:SI 0 "s_register_operand" "=r")
1765         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1766   ""
1767   "rsb%?\\t%0, %1, #0")
1769 (define_insn "negsf2"
1770   [(set (match_operand:SF 0 "s_register_operand" "=f")
1771         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1772   "TARGET_HARD_FLOAT"
1773   "mnf%?s\\t%0, %1"
1774 [(set_attr "type" "ffarith")])
1776 (define_insn "negdf2"
1777   [(set (match_operand:DF 0 "s_register_operand" "=f")
1778         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1779   "TARGET_HARD_FLOAT"
1780   "mnf%?d\\t%0, %1"
1781 [(set_attr "type" "ffarith")])
1783 (define_insn "*negdf_esfdf"
1784   [(set (match_operand:DF 0 "s_register_operand" "=f")
1785         (neg:DF (float_extend:DF
1786                  (match_operand:SF 1 "s_register_operand" "f"))))]
1787   "TARGET_HARD_FLOAT"
1788   "mnf%?d\\t%0, %1"
1789 [(set_attr "type" "ffarith")])
1791 (define_insn "negxf2"
1792   [(set (match_operand:XF 0 "s_register_operand" "=f")
1793         (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1794   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1795   "mnf%?e\\t%0, %1"
1796 [(set_attr "type" "ffarith")])
1798 ;; abssi2 doesn't really clobber the condition codes if a different register
1799 ;; is being set.  To keep things simple, assume during rtl manipulations that
1800 ;; it does, but tell the final scan operator the truth.  Similarly for
1801 ;; (neg (abs...))
1803 (define_insn "abssi2"
1804   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1805         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1806    (clobber (reg 24))]
1807   ""
1808   "@
1809    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1810    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1811 [(set_attr "conds" "clob,*")
1812  (set_attr "length" "8")])
1814 (define_insn "*neg_abssi2"
1815   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1816         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1817    (clobber (reg 24))]
1818   ""
1819   "@
1820    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1821    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1822 [(set_attr "conds" "clob,*")
1823  (set_attr "length" "8")])
1825 (define_insn "abssf2"
1826   [(set (match_operand:SF 0 "s_register_operand" "=f")
1827          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1828   "TARGET_HARD_FLOAT"
1829   "abs%?s\\t%0, %1"
1830 [(set_attr "type" "ffarith")])
1832 (define_insn "absdf2"
1833   [(set (match_operand:DF 0 "s_register_operand" "=f")
1834         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1835   "TARGET_HARD_FLOAT"
1836   "abs%?d\\t%0, %1"
1837 [(set_attr "type" "ffarith")])
1839 (define_insn "*absdf_esfdf"
1840   [(set (match_operand:DF 0 "s_register_operand" "=f")
1841         (abs:DF (float_extend:DF
1842                  (match_operand:SF 1 "s_register_operand" "f"))))]
1843   "TARGET_HARD_FLOAT"
1844   "abs%?d\\t%0, %1"
1845 [(set_attr "type" "ffarith")])
1847 (define_insn "absxf2"
1848   [(set (match_operand:XF 0 "s_register_operand" "=f")
1849         (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1850   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1851   "abs%?e\\t%0, %1"
1852 [(set_attr "type" "ffarith")])
1854 (define_insn "sqrtsf2"
1855   [(set (match_operand:SF 0 "s_register_operand" "=f")
1856         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1857   "TARGET_HARD_FLOAT"
1858   "sqt%?s\\t%0, %1"
1859 [(set_attr "type" "float_em")])
1861 (define_insn "sqrtdf2"
1862   [(set (match_operand:DF 0 "s_register_operand" "=f")
1863         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1864   "TARGET_HARD_FLOAT"
1865   "sqt%?d\\t%0, %1"
1866 [(set_attr "type" "float_em")])
1868 (define_insn "*sqrtdf_esfdf"
1869   [(set (match_operand:DF 0 "s_register_operand" "=f")
1870         (sqrt:DF (float_extend:DF
1871                   (match_operand:SF 1 "s_register_operand" "f"))))]
1872   "TARGET_HARD_FLOAT"
1873   "sqt%?d\\t%0, %1"
1874 [(set_attr "type" "float_em")])
1876 (define_insn "sqrtxf2"
1877   [(set (match_operand:XF 0 "s_register_operand" "=f")
1878         (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1879   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1880   "sqt%?e\\t%0, %1"
1881 [(set_attr "type" "float_em")])
1883 ;; SIN COS TAN and family are always emulated, so it's probably better
1884 ;; to always call a library function.
1885 ;(define_insn "sinsf2"
1886 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
1887 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1888 ;  "TARGET_HARD_FLOAT"
1889 ;  "sin%?s\\t%0, %1"
1890 ;[(set_attr "type" "float_em")])
1892 ;(define_insn "sindf2"
1893 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1894 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1895 ;  "TARGET_HARD_FLOAT"
1896 ;  "sin%?d\\t%0, %1"
1897 ;[(set_attr "type" "float_em")])
1899 ;(define_insn "*sindf_esfdf"
1900 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1901 ;       (unspec:DF [(float_extend:DF
1902 ;                    (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1903 ;  "TARGET_HARD_FLOAT"
1904 ;  "sin%?d\\t%0, %1"
1905 ;[(set_attr "type" "float_em")])
1907 ;(define_insn "sinxf2"
1908 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
1909 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1910 ;  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1911 ;  "sin%?e\\t%0, %1"
1912 ;[(set_attr "type" "float_em")])
1914 ;(define_insn "cossf2"
1915 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
1916 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
1917 ;  "TARGET_HARD_FLOAT"
1918 ;  "cos%?s\\t%0, %1"
1919 ;[(set_attr "type" "float_em")])
1921 ;(define_insn "cosdf2"
1922 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1923 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
1924 ;  "TARGET_HARD_FLOAT"
1925 ;  "cos%?d\\t%0, %1"
1926 ;[(set_attr "type" "float_em")])
1928 ;(define_insn "*cosdf_esfdf"
1929 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1930 ;       (unspec:DF [(float_extend:DF
1931 ;                    (match_operand:SF 1 "s_register_operand" "f"))] 1))]
1932 ;  "TARGET_HARD_FLOAT"
1933 ;  "cos%?d\\t%0, %1"
1934 ;[(set_attr "type" "float_em")])
1936 ;(define_insn "cosxf2"
1937 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
1938 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
1939 ;  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1940 ;  "cos%?e\\t%0, %1"
1941 ;[(set_attr "type" "float_em")])
1943 (define_insn "one_cmpldi2"
1944   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1945         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1946   ""
1947   "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1"
1948 [(set_attr "length" "8")])
1950 (define_insn "one_cmplsi2"
1951   [(set (match_operand:SI 0 "s_register_operand" "=r")
1952         (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
1953   ""
1954   "mvn%?\\t%0, %1")
1956 (define_insn "*notsi_compare0"
1957   [(set (reg:CC_NOOV 24)
1958         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1959                          (const_int 0)))
1960    (set (match_operand:SI 0 "s_register_operand" "=r")
1961         (not:SI (match_dup 1)))]
1962   ""
1963   "mvn%?s\\t%0, %1"
1964 [(set_attr "conds" "set")])
1966 (define_insn "*notsi_compare0_scratch"
1967   [(set (reg:CC_NOOV 24)
1968         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1969                          (const_int 0)))
1970    (clobber (match_scratch:SI 0 "=r"))]
1971   ""
1972   "mvn%?s\\t%0, %1"
1973 [(set_attr "conds" "set")])
1975 ;; Fixed <--> Floating conversion insns
1977 (define_insn "floatsisf2"
1978   [(set (match_operand:SF 0 "s_register_operand" "=f")
1979         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
1980   "TARGET_HARD_FLOAT"
1981   "flt%?s\\t%0, %1"
1982 [(set_attr "type" "r_2_f")])
1984 (define_insn "floatsidf2"
1985   [(set (match_operand:DF 0 "s_register_operand" "=f")
1986         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
1987   "TARGET_HARD_FLOAT"
1988   "flt%?d\\t%0, %1"
1989 [(set_attr "type" "r_2_f")])
1991 (define_insn "floatsixf2"
1992   [(set (match_operand:XF 0 "s_register_operand" "=f")
1993         (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
1994   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1995   "flt%?e\\t%0, %1"
1996 [(set_attr "type" "r_2_f")])
1998 (define_insn "fix_truncsfsi2"
1999   [(set (match_operand:SI 0 "s_register_operand" "=r")
2000         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2001   "TARGET_HARD_FLOAT"
2002   "fix%?z\\t%0, %1"
2003 [(set_attr "type" "f_2_r")])
2005 (define_insn "fix_truncdfsi2"
2006   [(set (match_operand:SI 0 "s_register_operand" "=r")
2007         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2008   "TARGET_HARD_FLOAT"
2009   "fix%?z\\t%0, %1"
2010 [(set_attr "type" "f_2_r")])
2012 (define_insn "fix_truncxfsi2"
2013   [(set (match_operand:SI 0 "s_register_operand" "=r")
2014         (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
2015   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2016   "fix%?z\\t%0, %1"
2017 [(set_attr "type" "f_2_r")])
2019 ;; Truncation insns
2021 (define_insn "truncdfsf2"
2022   [(set (match_operand:SF 0 "s_register_operand" "=f")
2023         (float_truncate:SF
2024          (match_operand:DF 1 "s_register_operand" "f")))]
2025   "TARGET_HARD_FLOAT"
2026   "mvf%?s\\t%0, %1"
2027 [(set_attr "type" "ffarith")])
2029 (define_insn "truncxfsf2"
2030   [(set (match_operand:SF 0 "s_register_operand" "=f")
2031         (float_truncate:SF
2032          (match_operand:XF 1 "s_register_operand" "f")))]
2033   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2034   "mvf%?s\\t%0, %1"
2035 [(set_attr "type" "ffarith")])
2037 (define_insn "truncxfdf2"
2038   [(set (match_operand:DF 0 "s_register_operand" "=f")
2039         (float_truncate:DF
2040          (match_operand:XF 1 "s_register_operand" "f")))]
2041   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2042   "mvf%?d\\t%0, %1"
2043 [(set_attr "type" "ffarith")])
2045 ;; Zero and sign extension instructions.
2047 (define_insn "zero_extendsidi2"
2048   [(set (match_operand:DI 0 "s_register_operand" "=r")
2049         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2050   ""
2051   "*
2052   if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2053     output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2054   return \"mov%?\\t%R0, #0\";
2056 [(set_attr "length" "8")])
2058 (define_insn "zero_extendqidi2"
2059   [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2060         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2061   ""
2062   "@
2063    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2064    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2065 [(set_attr "length" "8")
2066  (set_attr "type" "*,load")])
2068 (define_insn "extendsidi2"
2069   [(set (match_operand:DI 0 "s_register_operand" "=r")
2070         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2071   ""
2072   "*
2073   if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2074     output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2075   return \"mov%?\\t%R0, %Q0, asr #31\";
2077 [(set_attr "length" "8")])
2079 (define_expand "zero_extendhisi2"
2080   [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2081                                  (const_int 16)))
2082    (set (match_operand:SI 0 "s_register_operand" "")
2083         (lshiftrt:SI (match_dup 2) (const_int 16)))]
2084   ""
2085   "
2087   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2088     {
2089       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2090                           gen_rtx (ZERO_EXTEND, SImode, operands[1])));
2091       DONE;
2092     }
2093   if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2094     {
2095       emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2096       DONE;
2097     }
2098   if (! s_register_operand (operands[1], HImode))
2099     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2100   operands[1] = gen_lowpart (SImode, operands[1]);
2101   operands[2] = gen_reg_rtx (SImode); 
2104 (define_insn "*zero_extendhisi_insn"
2105   [(set (match_operand:SI 0 "s_register_operand" "=r")
2106         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2107   "arm_arch4"
2108   "ldr%?h\\t%0, %1"
2109 [(set_attr "type" "load")])
2111 (define_split
2112   [(set (match_operand:SI 0 "s_register_operand" "")
2113         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2114    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2115   "! arm_arch4"
2116   [(set (match_dup 2) (match_dup 1))
2117    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2118   "
2120   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2121     FAIL;
2124 (define_split
2125   [(set (match_operand:SI 0 "s_register_operand" "")
2126         (match_operator:SI 3 "shiftable_operator"
2127          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2128           (match_operand:SI 4 "s_register_operand" "")]))
2129    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2130   "! arm_arch4"
2131   [(set (match_dup 2) (match_dup 1))
2132    (set (match_dup 0)
2133         (match_op_dup 3
2134          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2135   "
2137   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2138     FAIL;
2141 (define_expand "zero_extendqisi2"
2142   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2143         (zero_extend:SI
2144          (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2145   ""
2146   "
2147   if (GET_CODE (operands[1]) != MEM)
2148     {
2149       emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
2150                              GEN_INT (255)));
2151       DONE;
2152     }
2155 (define_insn "*load_extendqisi"
2156   [(set (match_operand:SI 0 "s_register_operand" "=r")
2157         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2158   ""
2159   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
2160 [(set_attr "type" "load")])
2162 (define_split
2163   [(set (match_operand:SI 0 "s_register_operand" "")
2164         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
2165    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2166   "GET_CODE (operands[1]) != MEM"
2167   [(set (match_dup 2) (match_dup 1))
2168    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
2169   "")
2171 (define_insn "*compareqi_eq0"
2172   [(set (reg:CC_Z 24)
2173         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
2174                          (const_int 0)))]
2175   ""
2176   "tst\\t%0, #255"
2177 [(set_attr "conds" "set")])
2179 (define_expand "extendhisi2"
2180   [(set (match_dup 2)
2181         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2182                    (const_int 16)))
2183    (set (match_operand:SI 0 "s_register_operand" "")
2184         (ashiftrt:SI (match_dup 2)
2185                      (const_int 16)))]
2186   ""
2187   "
2189   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2190     {
2191       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2192                  gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2193       DONE;
2194     }
2196   if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2197     {
2198       emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
2199       DONE;
2200     }
2201   if (! s_register_operand (operands[1], HImode))
2202     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2203   operands[1] = gen_lowpart (SImode, operands[1]);
2204   operands[2] = gen_reg_rtx (SImode);
2207 (define_expand "extendhisi2_mem"
2208   [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" ""))))
2209    (set (match_dup 3)
2210         (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
2211    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
2212    (set (match_operand:SI 0 "" "")
2213         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
2214   ""
2215   "
2216   operands[0] = gen_lowpart (SImode, operands[0]);
2217   operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2218   operands[2] = gen_reg_rtx (SImode);
2219   operands[3] = gen_reg_rtx (SImode);
2220   operands[6] = gen_reg_rtx (SImode);
2222   if (BYTES_BIG_ENDIAN)
2223     {
2224       operands[4] = operands[2];
2225       operands[5] = operands[3];
2226     }
2227   else
2228     {
2229       operands[4] = operands[3];
2230       operands[5] = operands[2];
2231     }
2234 (define_insn "*extendhisi_insn"
2235   [(set (match_operand:SI 0 "s_register_operand" "=r")
2236         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2237   "arm_arch4"
2238   "ldr%?sh\\t%0, %1"
2239 [(set_attr "type" "load")])
2241 (define_split
2242   [(set (match_operand:SI 0 "s_register_operand" "")
2243         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2244    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2245   "! arm_arch4"
2246   [(set (match_dup 2) (match_dup 1))
2247    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2248   "
2250   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2251     FAIL;
2254 (define_split
2255   [(set (match_operand:SI 0 "s_register_operand" "")
2256         (match_operator:SI 3 "shiftable_operator"
2257          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2258           (match_operand:SI 4 "s_register_operand" "")]))
2259    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2260   "! arm_arch4"
2261   [(set (match_dup 2) (match_dup 1))
2262    (set (match_dup 0)
2263         (match_op_dup 3
2264          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2265   "
2267   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2268     FAIL;
2271 (define_expand "extendqihi2"
2272   [(set (match_dup 2)
2273         (ashift:SI (match_operand:QI 1 "general_operand" "")
2274                    (const_int 24)))
2275    (set (match_operand:HI 0 "s_register_operand" "")
2276         (ashiftrt:SI (match_dup 2)
2277                      (const_int 24)))]
2278   ""
2279   "
2281   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2282     {
2283       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2284                           gen_rtx (SIGN_EXTEND, HImode, operands[1])));
2285       DONE;
2286     }
2287   if (! s_register_operand (operands[1], QImode))
2288     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2289   operands[0] = gen_lowpart (SImode, operands[0]);
2290   operands[1] = gen_lowpart (SImode, operands[1]);
2291   operands[2] = gen_reg_rtx (SImode);
2294 (define_insn "*extendqihi_insn"
2295   [(set (match_operand:HI 0 "s_register_operand" "=r")
2296         (sign_extend:HI (match_operand:QI 1 "memory_operand" "o<>")))]
2297   "arm_arch4"
2298   "ldr%?sb\\t%0, %1"
2299 [(set_attr "type" "load")])
2301 (define_expand "extendqisi2"
2302   [(set (match_dup 2)
2303         (ashift:SI (match_operand:QI 1 "s_register_operand" "")
2304                    (const_int 24)))
2305    (set (match_operand:SI 0 "s_register_operand" "")
2306         (ashiftrt:SI (match_dup 2)
2307                      (const_int 24)))]
2308   ""
2309   "
2311   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2312     {
2313       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2314                           gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2315       DONE;
2316     }
2317   if (! s_register_operand (operands[1], QImode))
2318     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2319   operands[1] = gen_lowpart (SImode, operands[1]);
2320   operands[2] = gen_reg_rtx (SImode);
2323 (define_insn "*extendqisi_insn"
2324   [(set (match_operand:SI 0 "s_register_operand" "=r")
2325         (sign_extend:SI (match_operand:QI 1 "memory_operand" "o<>")))]
2326   "arm_arch4"
2327   "ldr%?sb\\t%0, %1"
2328 [(set_attr "type" "load")])
2330 (define_insn "extendsfdf2"
2331   [(set (match_operand:DF 0 "s_register_operand" "=f")
2332         (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2333   "TARGET_HARD_FLOAT"
2334   "mvf%?d\\t%0, %1"
2335 [(set_attr "type" "ffarith")])
2337 (define_insn "extendsfxf2"
2338   [(set (match_operand:XF 0 "s_register_operand" "=f")
2339         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2340   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2341   "mvf%?e\\t%0, %1"
2342 [(set_attr "type" "ffarith")])
2344 (define_insn "extenddfxf2"
2345   [(set (match_operand:XF 0 "s_register_operand" "=f")
2346         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2347   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2348   "mvf%?e\\t%0, %1"
2349 [(set_attr "type" "ffarith")])
2352 ;; Move insns (including loads and stores)
2354 ;; XXX Just some ideas about movti.
2355 ;; I don't think these are a good idea on the arm, there just aren't enough
2356 ;; registers
2357 ;;(define_expand "loadti"
2358 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
2359 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
2360 ;;  "" "")
2362 ;;(define_expand "storeti"
2363 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2364 ;;      (match_operand:TI 1 "s_register_operand" ""))]
2365 ;;  "" "")
2367 ;;(define_expand "movti"
2368 ;;  [(set (match_operand:TI 0 "general_operand" "")
2369 ;;      (match_operand:TI 1 "general_operand" ""))]
2370 ;;  ""
2371 ;;  "
2373 ;;  rtx insn;
2375 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2376 ;;    operands[1] = copy_to_reg (operands[1]);
2377 ;;  if (GET_CODE (operands[0]) == MEM)
2378 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2379 ;;  else if (GET_CODE (operands[1]) == MEM)
2380 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2381 ;;  else
2382 ;;    FAIL;
2384 ;;  emit_insn (insn);
2385 ;;  DONE;
2386 ;;}")
2388 ;; Recognise garbage generated above.
2390 ;;(define_insn ""
2391 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2392 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2393 ;;  ""
2394 ;;  "*
2395 ;;  {
2396 ;;    register mem = (which_alternative < 3);
2397 ;;    register char *template;
2399 ;;    operands[mem] = XEXP (operands[mem], 0);
2400 ;;    switch (which_alternative)
2401 ;;      {
2402 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2403 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
2404 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
2405 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
2406 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
2407 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
2408 ;;      }
2409 ;;    output_asm_insn (template, operands);
2410 ;;    return \"\";
2411 ;;  }")
2414 (define_insn "movdi"
2415   [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2416         (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2417   ""
2418   "*
2419   return (output_move_double (operands));
2421 [(set_attr "length" "8,8,8")
2422  (set_attr "type" "*,load,store2")])
2424 (define_expand "movsi"
2425   [(set (match_operand:SI 0 "general_operand" "")
2426         (match_operand:SI 1 "general_operand" ""))]
2427   ""
2428   "
2429   /* Everything except mem = const or mem = mem can be done easily */
2430   if (GET_CODE (operands[0]) == MEM)
2431     operands[1] = force_reg (SImode, operands[1]);
2432   if (GET_CODE (operands[1]) == CONST_INT
2433       && !(const_ok_for_arm (INTVAL (operands[1]))
2434            || const_ok_for_arm (~INTVAL (operands[1]))))
2435     {
2436       arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2437                           NULL_RTX,
2438                           (reload_in_progress || reload_completed ? 0
2439                            : preserve_subexpressions_p ()));
2440       DONE;
2441     }
2442   if (CONSTANT_P (operands[1]) && flag_pic)
2443     operands[1] = legitimize_pic_address (operands[1], SImode,
2444                                           ((reload_in_progress
2445                                             || reload_completed)
2446                                            ? operands[0] : 0));
2449 (define_insn "*movsi_insn"
2450   [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2451         (match_operand:SI 1 "general_operand"  "rI,K,mi,r"))]
2452   "register_operand (operands[0], SImode)
2453    || register_operand (operands[1], SImode)"
2454   "@
2455    mov%?\\t%0, %1
2456    mvn%?\\t%0, #%B1
2457    ldr%?\\t%0, %1
2458    str%?\\t%1, %0"
2459 [(set_attr "type" "*,*,load,store1")])
2461 (define_split
2462   [(set (match_operand:SI 0 "s_register_operand" "")
2463         (match_operand:SI 1 "const_int_operand" ""))]
2464   "! (const_ok_for_arm (INTVAL (operands[1]))
2465       || const_ok_for_arm (~INTVAL (operands[1])))"
2466   [(clobber (const_int 0))]
2467   "
2468   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2469                       NULL_RTX, 0);
2470   DONE;
2473 (define_expand "movaddr"
2474   [(set (match_operand:SI 0 "s_register_operand" "")
2475         (match_operand:DI 1 "address_operand" ""))]
2476   ""
2477   "")
2479 (define_insn "*movaddr_insn"
2480   [(set (match_operand:SI 0 "s_register_operand" "=r")
2481         (match_operand:DI 1 "address_operand" "p"))]
2482   "reload_completed
2483    && (GET_CODE (operands[1]) == LABEL_REF
2484        || (GET_CODE (operands[1]) == CONST
2485            && GET_CODE (XEXP (operands[1], 0)) == PLUS
2486            && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2487            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2488   "adr%?\\t%0, %a1")
2490 /* When generating pic, we need to load the symbol offset into a register.
2491    So that the optimizer does not confuse this with a normal symbol load
2492    we use an unspec.  The offset will be loaded from a constant pool entry,
2493    since that is the only type of relocation we can use.  */
2495 (define_insn "pic_load_addr"
2496   [(set (match_operand:SI 0 "s_register_operand" "=r")
2497         (unspec:SI [(match_operand 1 "" "")] 3))]
2498   "flag_pic"
2499   "ldr%?\\t%0, %a1"
2500  [(set_attr "type" "load")])
2502 ;; This variant is used for AOF assembly, since it needs to mention the
2503 ;; pic register in the rtl.
2504 (define_expand "pic_load_addr_based"
2505   [(set (match_operand:SI 0 "s_register_operand" "=r")
2506         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
2507   "flag_pic"
2508   "operands[2] = pic_offset_table_rtx;")
2510 (define_insn "*pic_load_addr_based_insn"
2511   [(set (match_operand:SI 0 "s_register_operand" "=r")
2512         (unspec:SI [(match_operand 1 "" "")
2513                     (match_operand 2 "s_register_operand" "r")] 3))]
2514   "flag_pic && operands[2] == pic_offset_table_rtx"
2515   "*
2516 #ifdef AOF_ASSEMBLER
2517   operands[1] = aof_pic_entry (operands[1]);
2518 #endif
2519   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
2520   return \"\";
2521 " [(set_attr "type" "load")])
2523 (define_insn "pic_add_dot_plus_eight"
2524   [(set (pc) (label_ref (match_operand 0 "" "")))
2525    (set (match_operand 1 "register_operand" "+r")
2526         (plus:SI (match_dup 1) (const (plus:SI (pc) (const_int 8)))))]
2527   "flag_pic"
2528   "add%?\\t%1, %|pc, %1")
2530 ;; If copying one reg to another we can set the condition codes according to
2531 ;; its value.  Such a move is common after a return from subroutine and the
2532 ;; result is being tested against zero.
2534 (define_insn "*movsi_compare0"
2535   [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
2536                                 (const_int 0)))
2537    (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2538   ""
2539   "@
2540    cmp%?\\t%0, #0
2541    sub%?s\\t%0, %1, #0"
2542 [(set_attr "conds" "set")])
2544 ;; Subroutine to store a half word from a register into memory.
2545 ;; Operand 0 is the source register (HImode)
2546 ;; Operand 1 is the destination address in a register (SImode)
2548 ;; In both this routine and the next, we must be careful not to spill
2549 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2550 ;; can generate unrecognizable rtl.
2552 (define_expand "storehi"
2553   [;; store the low byte
2554    (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3))
2555    ;; extract the high byte
2556    (set (match_dup 2)
2557         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2558    ;; store the high byte
2559    (set (mem:QI (match_dup 4))
2560         (subreg:QI (match_dup 2) 0))]   ;explicit subreg safe
2561   ""
2562   "
2564   enum rtx_code code = GET_CODE (operands[1]);
2566   if ((code == PLUS || code == MINUS)
2567       && (GET_CODE (XEXP (operands[1], 1)) == REG
2568           || GET_CODE (XEXP (operands[1], 0)) != REG))
2569     operands[1] = force_reg (SImode, operands[1]);
2570   operands[4] = plus_constant (operands[1], 1);
2571   operands[3] = gen_lowpart (QImode, operands[0]);
2572   operands[0] = gen_lowpart (SImode, operands[0]);
2573   operands[2] = gen_reg_rtx (SImode); 
2577 (define_expand "storehi_bigend"
2578   [(set (mem:QI (match_dup 4)) (match_dup 3))
2579    (set (match_dup 2)
2580         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2581    (set (mem:QI (match_operand 1 "" ""))
2582         (subreg:QI (match_dup 2) 0))]
2583   ""
2584   "
2586   enum rtx_code code = GET_CODE (operands[1]);
2587   if ((code == PLUS || code == MINUS)
2588       && (GET_CODE (XEXP (operands[1], 1)) == REG
2589           || GET_CODE (XEXP (operands[1], 0)) != REG))
2590     operands[1] = force_reg (SImode, operands[1]);
2592   operands[4] = plus_constant (operands[1], 1);
2593   operands[3] = gen_lowpart (QImode, operands[0]);
2594   operands[0] = gen_lowpart (SImode, operands[0]);
2595   operands[2] = gen_reg_rtx (SImode);
2599 ;; Subroutine to store a half word integer constant into memory.
2600 (define_expand "storeinthi"
2601   [(set (mem:QI (match_operand:SI 0 "" ""))
2602         (subreg:QI (match_operand 1 "" "") 0))
2603    (set (mem:QI (match_dup 3)) (subreg:QI (match_dup 2) 0))]
2604   ""
2605   "
2607   HOST_WIDE_INT value = INTVAL (operands[1]);
2608   enum rtx_code code = GET_CODE (operands[0]);
2610   if ((code == PLUS || code == MINUS)
2611       && (GET_CODE (XEXP (operands[0], 1)) == REG
2612           || GET_CODE (XEXP (operands[0], 0)) != REG))
2613   operands[0] = force_reg (SImode, operands[0]);
2615   operands[1] = gen_reg_rtx (SImode);
2616   if (BYTES_BIG_ENDIAN)
2617     {
2618       emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2619       if ((value & 255) == ((value >> 8) & 255))
2620         operands[2] = operands[1];
2621       else
2622         {
2623           operands[2] = gen_reg_rtx (SImode);
2624           emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2625         }
2626     }
2627   else
2628     {
2629       emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2630       if ((value & 255) == ((value >> 8) & 255))
2631         operands[2] = operands[1];
2632       else
2633         {
2634           operands[2] = gen_reg_rtx (SImode);
2635           emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2636         }
2637     }
2639   operands[3] = plus_constant (operands[0], 1);
2643 (define_expand "storehi_single_op"
2644   [(set (match_operand:HI 0 "memory_operand" "")
2645         (match_operand:HI 1 "general_operand" ""))]
2646   "arm_arch4"
2647   "
2648   if (! s_register_operand (operands[1], HImode))
2649     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2652 (define_expand "movhi"
2653   [(set (match_operand:HI 0 "general_operand" "")
2654         (match_operand:HI 1 "general_operand" ""))]
2655   ""
2656   "
2658   rtx insn;
2660   if (! (reload_in_progress || reload_completed))
2661     {
2662       if (GET_CODE (operands[0]) == MEM)
2663         {
2664           if (arm_arch4)
2665             {
2666               emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2667               DONE;
2668             }
2669           if (GET_CODE (operands[1]) == CONST_INT)
2670             emit_insn (gen_storeinthi (XEXP (operands[0], 0), operands[1]));
2671           else
2672             {
2673               if (GET_CODE (operands[1]) == MEM)
2674                 operands[1] = force_reg (HImode, operands[1]);
2675               if (BYTES_BIG_ENDIAN)
2676                 emit_insn (gen_storehi_bigend (operands[1],
2677                                                XEXP (operands[0], 0)));
2678               else
2679                 emit_insn (gen_storehi (operands[1], XEXP (operands[0], 0)));
2680             }
2681           DONE;
2682         }
2683       /* Sign extend a constant, and keep it in an SImode reg.  */
2684       else if (GET_CODE (operands[1]) == CONST_INT)
2685         {
2686           rtx reg = gen_reg_rtx (SImode);
2687           HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2689           /* If the constant is already valid, leave it alone.  */
2690           if (! const_ok_for_arm (val))
2691             {
2692               /* If setting all the top bits will make the constant 
2693                  loadable in a single instruction, then set them.  
2694                  Otherwise, sign extend the number.  */
2696               if (const_ok_for_arm (~ (val | ~0xffff)))
2697                 val |= ~0xffff;
2698               else if (val & 0x8000)
2699                 val |= ~0xffff;
2700             }
2702           emit_insn (gen_movsi (reg, GEN_INT (val)));
2703           operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
2704         }
2705       else if (! arm_arch4)
2706         {
2707           if (GET_CODE (operands[1]) == MEM)
2708             {
2709               if (TARGET_SHORT_BY_BYTES)
2710                 {
2711                   rtx base;
2712                   rtx offset = const0_rtx;
2713                   rtx reg = gen_reg_rtx (SImode);
2715                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2716                        || (GET_CODE (base) == PLUS
2717                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2718                            && GET_CODE (base = XEXP (base, 0)) == REG))
2719                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2720                     {
2721                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~2;
2723                       emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode,
2724                                            plus_constant (base, new_offset))));
2725                       if (((INTVAL (offset) & 2) != 0)
2726                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
2727                         {
2728                           rtx reg2 = gen_reg_rtx (SImode);
2730                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
2731                           reg = reg2;
2732                         }
2733                     }
2734                   else
2735                     emit_insn (gen_movhi_bytes (reg, operands[1]));
2737                   operands[1] = gen_lowpart (HImode, reg);
2738                 }
2739               else if (BYTES_BIG_ENDIAN)
2740                 {
2741                   rtx base;
2742                   rtx offset = const0_rtx;
2744                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2745                        || (GET_CODE (base) == PLUS
2746                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2747                            && GET_CODE (base = XEXP (base, 0)) == REG))
2748                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2749                     {
2750                       rtx reg = gen_reg_rtx (SImode);
2751                       rtx new_mem;
2753                       if ((INTVAL (offset) & 2) == 2)
2754                         {
2755                           HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
2756                           new_mem = gen_rtx (MEM, SImode,
2757                                              plus_constant (base, new_offset));
2759                           emit_insn (gen_movsi (reg, new_mem));
2760                         }
2761                       else
2762                         {
2763                           new_mem = gen_rtx (MEM, SImode,
2764                                              XEXP (operands[1], 0));
2765                           emit_insn (gen_rotated_loadsi (reg, new_mem));
2766                         }
2768                       operands[1] = gen_lowpart (HImode, reg);
2769                     }
2770                   else
2771                     {
2772                       emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2773                       DONE;
2774                     }
2775                 }
2776             }
2777         }
2778     }
2779   /* Handle loading a large integer during reload */
2780   else if (GET_CODE (operands[1]) == CONST_INT
2781            && ! const_ok_for_arm (INTVAL (operands[1]))
2782            && ! const_ok_for_arm (~INTVAL (operands[1])))
2783     {
2784       /* Writing a constant to memory needs a scratch, which should
2785          be handled with SECONDARY_RELOADs.  */
2786       if (GET_CODE (operands[0]) != REG)
2787         abort ();
2789       operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
2790       emit_insn (gen_movsi (operands[0], operands[1]));
2791       DONE;
2792     }
2796 (define_insn "rotated_loadsi"
2797   [(set (match_operand:SI 0 "s_register_operand" "=r")
2798         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
2799                    (const_int 16)))]
2800   "! TARGET_SHORT_BY_BYTES"
2801   "*
2803   rtx ops[2];
2805   ops[0] = operands[0];
2806   ops[1] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 2));
2807   output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
2808   return \"\";
2810 [(set_attr "type" "load")])
2812 (define_expand "movhi_bytes"
2813   [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" ""))))
2814    (set (match_dup 3)
2815         (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
2816    (set (match_operand:SI 0 "" "")
2817          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
2818   ""
2819   "
2820   operands[0] = gen_lowpart (SImode, operands[0]);
2821   operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2822   operands[2] = gen_reg_rtx (SImode);
2823   operands[3] = gen_reg_rtx (SImode);
2825   if (BYTES_BIG_ENDIAN)
2826     {
2827       operands[4] = operands[2];
2828       operands[5] = operands[3];
2829     }
2830   else
2831     {
2832       operands[4] = operands[3];
2833       operands[5] = operands[2];
2834     }
2837 (define_expand "movhi_bigend"
2838   [(set (match_dup 2)
2839         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
2840                    (const_int 16)))
2841    (set (match_dup 3)
2842         (ashiftrt:SI (match_dup 2) (const_int 16)))
2843    (set (match_operand:HI 0 "s_register_operand" "")
2844         (subreg:HI (match_dup 3) 0))]
2845   ""
2846   "
2847   operands[2] = gen_reg_rtx (SImode);
2848   operands[3] = gen_reg_rtx (SImode);
2851 ;; Pattern to recognise insn generated default case above
2853 (define_insn "*movhi_insn_arch4"
2854   [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
2855         (match_operand:HI 1 "general_operand"  "rI,K,m,r"))]
2856   "arm_arch4
2857    && (GET_CODE (operands[1]) != CONST_INT
2858        || const_ok_for_arm (INTVAL (operands[1]))
2859        || const_ok_for_arm (~INTVAL (operands[1])))"
2860   "@
2861    mov%?\\t%0, %1\\t%@ movhi
2862    mvn%?\\t%0, #%B1\\t%@ movhi
2863    ldr%?h\\t%0, %1\\t%@ movhi
2864    str%?h\\t%1, %0\\t%@ movhi"
2865 [(set_attr "type" "*,*,load,store1")])
2867 (define_insn "*movhi_insn_littleend"
2868   [(set (match_operand:HI 0 "general_operand" "=r,r,r")
2869         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2870   "! arm_arch4
2871    && ! BYTES_BIG_ENDIAN
2872    && ! TARGET_SHORT_BY_BYTES
2873    && (GET_CODE (operands[1]) != CONST_INT
2874        || const_ok_for_arm (INTVAL (operands[1]))
2875        || const_ok_for_arm (~INTVAL (operands[1])))"
2876   "@
2877    mov%?\\t%0, %1\\t%@ movhi
2878    mvn%?\\t%0, #%B1\\t%@ movhi
2879    ldr%?\\t%0, %1\\t%@ movhi"
2880 [(set_attr "type" "*,*,load")])
2882 (define_insn "*movhi_insn_bigend"
2883   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
2884         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2885   "! arm_arch4
2886    && BYTES_BIG_ENDIAN
2887    && ! TARGET_SHORT_BY_BYTES
2888    && (GET_CODE (operands[1]) != CONST_INT
2889        || const_ok_for_arm (INTVAL (operands[1]))
2890        || const_ok_for_arm (~INTVAL (operands[1])))"
2891   "@
2892    mov%?\\t%0, %1\\t%@ movhi
2893    mvn%?\\t%0, #%B1\\t%@ movhi
2894    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
2895 [(set_attr "type" "*,*,load")
2896  (set_attr "length" "4,4,8")])
2898 (define_insn "*loadhi_si_bigend"
2899   [(set (match_operand:SI 0 "s_register_operand" "=r")
2900         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
2901                    (const_int 16)))]
2902   "BYTES_BIG_ENDIAN
2903    && ! TARGET_SHORT_BY_BYTES"
2904   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
2905 [(set_attr "type" "load")])
2907 (define_insn "*movhi_bytes"
2908   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
2909         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
2910   "TARGET_SHORT_BY_BYTES"
2911   "@
2912    mov%?\\t%0, %1\\t%@ movhi
2913    mvn%?\\t%0, #%B1\\t%@ movhi")
2916 (define_expand "reload_outhi"
2917   [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
2918               (match_operand:HI 1 "s_register_operand" "r")
2919               (match_operand:SI 2 "s_register_operand" "=&r")])]
2920   ""
2921   "
2922   arm_reload_out_hi (operands);
2923   DONE;
2926 (define_expand "reload_inhi"
2927   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
2928               (match_operand:HI 1 "reload_memory_operand" "o")
2929               (match_operand:SI 2 "s_register_operand" "=&r")])]
2930   "TARGET_SHORT_BY_BYTES"
2931   "
2932   arm_reload_in_hi (operands);
2933   DONE;
2936 (define_expand "movqi"
2937   [(set (match_operand:QI 0 "general_operand" "")
2938         (match_operand:QI 1 "general_operand" ""))]
2939   ""
2940   "
2941   /* Everything except mem = const or mem = mem can be done easily */
2943   if (!(reload_in_progress || reload_completed))
2944     {
2945       if (GET_CODE (operands[1]) == CONST_INT)
2946         {
2947           rtx reg = gen_reg_rtx (SImode);
2949           emit_insn (gen_movsi (reg, operands[1]));
2950           operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
2951         }
2952       if (GET_CODE (operands[0]) == MEM)
2953         operands[1] = force_reg (QImode, operands[1]);
2954     }
2958 (define_insn "*movqi_insn"
2959   [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
2960         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
2961   "register_operand (operands[0], QImode)
2962    || register_operand (operands[1], QImode)"
2963   "@
2964    mov%?\\t%0, %1
2965    mvn%?\\t%0, #%B1
2966    ldr%?b\\t%0, %1
2967    str%?b\\t%1, %0"
2968 [(set_attr "type" "*,*,load,store1")])
2970 (define_expand "movsf"
2971   [(set (match_operand:SF 0 "general_operand" "")
2972         (match_operand:SF 1 "general_operand" ""))]
2973   ""
2974   "
2975   if (GET_CODE (operands[0]) == MEM)
2976     operands[1] = force_reg (SFmode, operands[1]);
2979 (define_insn "*movsf_hard_insn"
2980   [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
2981         (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
2982   "TARGET_HARD_FLOAT
2983    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
2984   "@
2985    mvf%?s\\t%0, %1
2986    mnf%?s\\t%0, #%N1
2987    ldf%?s\\t%0, %1
2988    stf%?s\\t%1, %0
2989    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
2990    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
2991    mov%?\\t%0, %1
2992    ldr%?\\t%0, %1\\t%@ float
2993    str%?\\t%1, %0\\t%@ float"
2994 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
2995  (set_attr "type"
2996          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
2998 ;; Exactly the same as above, except that all `f' cases are deleted.
2999 ;; This is necessary to prevent reload from ever trying to use a `f' reg
3000 ;; when -msoft-float.
3002 (define_insn "*movsf_soft_insn"
3003   [(set (match_operand:SF 0 "general_operand" "=r,r,m")
3004         (match_operand:SF 1 "general_operand" "r,mE,r"))]
3005   "TARGET_SOFT_FLOAT
3006    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3007   "@
3008    mov%?\\t%0, %1
3009    ldr%?\\t%0, %1\\t%@ float
3010    str%?\\t%1, %0\\t%@ float"
3011 [(set_attr "length" "4,4,4")
3012  (set_attr "type" "*,load,store1")])
3014 (define_expand "movdf"
3015   [(set (match_operand:DF 0 "general_operand" "")
3016         (match_operand:DF 1 "general_operand" ""))]
3017   ""
3018   "
3019   if (GET_CODE (operands[0]) == MEM)
3020     operands[1] = force_reg (DFmode, operands[1]);
3023 ;; Reloading a df mode value stored in integer regs to memory can require a
3024 ;; scratch reg.
3025 (define_expand "reload_outdf"
3026   [(match_operand:DF 0 "reload_memory_operand" "=o")
3027    (match_operand:DF 1 "s_register_operand" "r")
3028    (match_operand:SI 2 "s_register_operand" "=&r")]
3029   ""
3030   "
3032   enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
3034   if (code == REG)
3035     operands[2] = XEXP (operands[0], 0);
3036   else if (code == POST_INC || code == PRE_DEC)
3037     {
3038       operands[0] = gen_rtx (SUBREG, DImode, operands[0], 0);
3039       operands[1] = gen_rtx (SUBREG, DImode, operands[1], 0);
3040       emit_insn (gen_movdi (operands[0], operands[1]));
3041       DONE;
3042     }
3043   else if (code == PRE_INC)
3044     {
3045       rtx reg = XEXP (XEXP (operands[0], 0), 0);
3046       emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
3047       operands[2] = reg;
3048     }
3049   else if (code == POST_DEC)
3050     operands[2] = XEXP (XEXP (operands[0], 0), 0);
3051   else
3052     emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
3053                            XEXP (XEXP (operands[0], 0), 1)));
3055   emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DFmode, operands[2]),
3056                       operands[1]));
3058   if (code == POST_DEC)
3059     emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
3061   DONE;
3065 (define_insn "*movdf_hard_insn"
3066   [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
3067         (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
3068   "TARGET_HARD_FLOAT
3069    && (GET_CODE (operands[0]) != MEM
3070        || register_operand (operands[1], DFmode))"
3071   "*
3073   rtx ops[3];
3075   switch (which_alternative)
3076     {
3077     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3078     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3079     case 2: case 3: case 4: return output_move_double (operands);
3080     case 5: return \"mvf%?d\\t%0, %1\";
3081     case 6: return \"mnf%?d\\t%0, #%N1\";
3082     case 7: return \"ldf%?d\\t%0, %1\";
3083     case 8: return \"stf%?d\\t%1, %0\";
3084     case 9: return output_mov_double_fpu_from_arm (operands);
3085     case 10: return output_mov_double_arm_from_fpu (operands);
3086     }
3089 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3090  (set_attr "type"
3091 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
3093 ;; Software floating point version.  This is essentially the same as movdi.
3094 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
3095 ;; an `f' reg.
3097 (define_insn "*movdf_soft_insn"
3098   [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3099         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3100   "TARGET_SOFT_FLOAT"
3101   "* return output_move_double (operands);"
3102 [(set_attr "length" "8,8,8")
3103  (set_attr "type" "*,load,store2")])
3105 (define_expand "movxf"
3106   [(set (match_operand:XF 0 "general_operand" "")
3107         (match_operand:XF 1 "general_operand" ""))]
3108   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3109   "")
3111 ;; Even when the XFmode patterns aren't enabled, we enable this after
3112 ;; reloading so that we can push floating point registers in the prologue.
3114 (define_insn "*movxf_hard_insn"
3115   [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3116         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3117   "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3118   "*
3119   switch (which_alternative)
3120     {
3121     case 0: return \"mvf%?e\\t%0, %1\";
3122     case 1: return \"mnf%?e\\t%0, #%N1\";
3123     case 2: return \"ldf%?e\\t%0, %1\";
3124     case 3: return \"stf%?e\\t%1, %0\";
3125     case 4: return output_mov_long_double_fpu_from_arm (operands);
3126     case 5: return output_mov_long_double_arm_from_fpu (operands);
3127     case 6: return output_mov_long_double_arm_from_arm (operands);
3128     }
3130 [(set_attr "length" "4,4,4,4,8,8,12")
3131  (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
3134 ;; load- and store-multiple insns
3135 ;; The arm can load/store any set of registers, provided that they are in
3136 ;; ascending order; but that is beyond GCC so stick with what it knows.
3138 (define_expand "load_multiple"
3139   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3140                           (match_operand:SI 1 "" ""))
3141                      (use (match_operand:SI 2 "" ""))])]
3142   ""
3143   "
3144   /* Support only fixed point registers */
3145   if (GET_CODE (operands[2]) != CONST_INT
3146       || INTVAL (operands[2]) > 14
3147       || INTVAL (operands[2]) < 2
3148       || GET_CODE (operands[1]) != MEM
3149       || GET_CODE (operands[0]) != REG
3150       || REGNO (operands[0]) > 14
3151       || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
3152     FAIL;
3154   operands[3]
3155             = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
3156                                      force_reg (SImode, XEXP (operands[1], 0)),
3157                                      TRUE, FALSE);
3160 ;; Load multiple with write-back
3162 (define_insn "*ldmsi_postinc"
3163   [(match_parallel 0 "load_multiple_operation"
3164     [(set (match_operand:SI 1 "s_register_operand" "+r")
3165           (plus:SI (match_dup 1)
3166                    (match_operand:SI 2 "const_int_operand" "n")))
3167      (set (match_operand:SI 3 "s_register_operand" "=r")
3168           (mem:SI (match_dup 1)))])]
3169   "(INTVAL (operands[2])  == 4 * (XVECLEN (operands[0], 0) - 2))"
3170   "*
3172   rtx ops[3];
3173   int count = XVECLEN (operands[0], 0);
3175   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3176   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
3177   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
3179   output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
3180   return \"\";
3183 [(set_attr "type" "load")])
3185 ;; Ordinary load multiple
3187 (define_insn "*ldmsi"
3188   [(match_parallel 0 "load_multiple_operation"
3189     [(set (match_operand:SI 1 "s_register_operand" "=r")
3190           (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3191   ""
3192   "*
3194   rtx ops[3];
3195   int count = XVECLEN (operands[0], 0);
3197   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3198   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3199   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3201   output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3202   return \"\";
3205 [(set_attr "type" "load")])
3207 (define_expand "store_multiple"
3208   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3209                           (match_operand:SI 1 "" ""))
3210                      (use (match_operand:SI 2 "" ""))])]
3211   ""
3212   "
3213   /* Support only fixed point registers */
3214   if (GET_CODE (operands[2]) != CONST_INT
3215       || INTVAL (operands[2]) > 14
3216       || INTVAL (operands[2]) < 2
3217       || GET_CODE (operands[1]) != REG
3218       || GET_CODE (operands[0]) != MEM
3219       || REGNO (operands[1]) > 14
3220       || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3221     FAIL;
3223   operands[3]
3224            = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3225                                      force_reg (SImode, XEXP (operands[0], 0)),
3226                                      TRUE, FALSE);
3229 ;; Store multiple with write-back
3231 (define_insn "*stmsi_postinc"
3232   [(match_parallel 0 "store_multiple_operation"
3233     [(set (match_operand:SI 1 "s_register_operand" "+r")
3234           (plus:SI (match_dup 1)
3235                    (match_operand:SI 2 "const_int_operand" "n")))
3236      (set (mem:SI (match_dup 1))
3237           (match_operand:SI 3 "s_register_operand" "r"))])]
3238   "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3239   "*
3241   rtx ops[3];
3242   int count = XVECLEN (operands[0], 0);
3244   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3245   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3246   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3248   output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3249   return \"\";
3252 [(set (attr "type")
3253       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3254                 (const_string "store2")
3255              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3256                 (const_string "store3")]
3257           (const_string "store4")))])
3259 ;; Ordinary store multiple
3261 (define_insn "*stmsi"
3262   [(match_parallel 0 "store_multiple_operation"
3263     [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3264           (match_operand:SI 1 "s_register_operand" "r"))])]
3265   ""
3266   "*
3268   rtx ops[3];
3269   int count = XVECLEN (operands[0], 0);
3271   ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3272   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3273   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3275   output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3276   return \"\";
3279 [(set (attr "type")
3280       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3281                 (const_string "store2")
3282              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3283                 (const_string "store3")]
3284           (const_string "store4")))])
3286 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
3287 ;; We could let this apply for blocks of less than this, but it clobbers so
3288 ;; many registers that there is then probably a better way.
3290 (define_expand "movstrqi"
3291   [(match_operand:BLK 0 "general_operand" "")
3292    (match_operand:BLK 1 "general_operand" "")
3293    (match_operand:SI 2 "const_int_operand" "")
3294    (match_operand:SI 3 "const_int_operand" "")]
3295   ""
3296   "
3297   if (arm_gen_movstrqi (operands))
3298     DONE;
3299   FAIL;
3303 ;; Comparison and test insns
3305 (define_expand "cmpsi"
3306   [(match_operand:SI 0 "s_register_operand" "")
3307    (match_operand:SI 1 "arm_add_operand" "")]
3308   ""
3309   "
3311   arm_compare_op0 = operands[0];
3312   arm_compare_op1 = operands[1];
3313   arm_compare_fp = 0;
3314   DONE;
3318 (define_expand "cmpsf"
3319   [(match_operand:SF 0 "s_register_operand" "")
3320    (match_operand:SF 1 "fpu_rhs_operand" "")]
3321   "TARGET_HARD_FLOAT"
3322   "
3324   arm_compare_op0 = operands[0];
3325   arm_compare_op1 = operands[1];
3326   arm_compare_fp = 1;
3327   DONE;
3331 (define_expand "cmpdf"
3332   [(match_operand:DF 0 "s_register_operand" "")
3333    (match_operand:DF 1 "fpu_rhs_operand" "")]
3334   "TARGET_HARD_FLOAT"
3335   "
3337   arm_compare_op0 = operands[0];
3338   arm_compare_op1 = operands[1];
3339   arm_compare_fp = 1;
3340   DONE;
3344 (define_expand "cmpxf"
3345   [(match_operand:XF 0 "s_register_operand" "")
3346    (match_operand:XF 1 "fpu_rhs_operand" "")]
3347   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3348   "
3350   arm_compare_op0 = operands[0];
3351   arm_compare_op1 = operands[1];
3352   arm_compare_fp = 1;
3353   DONE;
3357 (define_insn "*cmpsi_insn"
3358   [(set (reg:CC 24)
3359         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3360                     (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3361   ""
3362   "@
3363    cmp%?\\t%0, %1
3364    cmn%?\\t%0, #%n1"
3365 [(set_attr "conds" "set")])
3367 (define_insn "*cmpsi_shiftsi"
3368   [(set (reg:CC 24)
3369         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3370                     (match_operator:SI 3 "shift_operator"
3371                      [(match_operand:SI 1 "s_register_operand" "r")
3372                       (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3373   ""
3374   "cmp%?\\t%0, %1%S3"
3375 [(set_attr "conds" "set")])
3377 (define_insn "*cmpsi_shiftsi_swp"
3378   [(set (reg:CC_SWP 24)
3379         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3380                          [(match_operand:SI 1 "s_register_operand" "r")
3381                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
3382                         (match_operand:SI 0 "s_register_operand" "r")))]
3383   ""
3384   "cmp%?\\t%0, %1%S3"
3385 [(set_attr "conds" "set")])
3387 (define_insn "*cmpsi_neg_shiftsi"
3388   [(set (reg:CC 24)
3389         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3390                     (neg:SI (match_operator:SI 3 "shift_operator"
3391                              [(match_operand:SI 1 "s_register_operand" "r")
3392                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3393   ""
3394   "cmn%?\\t%0, %1%S3"
3395 [(set_attr "conds" "set")])
3397 (define_insn "*cmpsf_insn"
3398   [(set (reg:CCFP 24)
3399         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3400                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3401   "TARGET_HARD_FLOAT"
3402   "@
3403    cmf%?\\t%0, %1
3404    cnf%?\\t%0, #%N1"
3405 [(set_attr "conds" "set")
3406  (set_attr "type" "f_2_r")])
3408 (define_insn "*cmpdf_insn"
3409   [(set (reg:CCFP 24)
3410         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3411                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3412   "TARGET_HARD_FLOAT"
3413   "@
3414    cmf%?\\t%0, %1
3415    cnf%?\\t%0, #%N1"
3416 [(set_attr "conds" "set")
3417  (set_attr "type" "f_2_r")])
3419 (define_insn "*cmpesfdf_df"
3420   [(set (reg:CCFP 24)
3421         (compare:CCFP (float_extend:DF
3422                        (match_operand:SF 0 "s_register_operand" "f,f"))
3423                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3424   "TARGET_HARD_FLOAT"
3425   "@
3426    cmf%?\\t%0, %1
3427    cnf%?\\t%0, #%N1"
3428 [(set_attr "conds" "set")
3429  (set_attr "type" "f_2_r")])
3431 (define_insn "*cmpdf_esfdf"
3432   [(set (reg:CCFP 24)
3433         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3434                       (float_extend:DF
3435                        (match_operand:SF 1 "s_register_operand" "f"))))]
3436   "TARGET_HARD_FLOAT"
3437   "cmf%?\\t%0, %1"
3438 [(set_attr "conds" "set")
3439  (set_attr "type" "f_2_r")])
3441 (define_insn "*cmpxf_insn"
3442   [(set (reg:CCFP 24)
3443         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3444                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3445   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3446   "@
3447    cmf%?\\t%0, %1
3448    cnf%?\\t%0, #%N1"
3449 [(set_attr "conds" "set")
3450  (set_attr "type" "f_2_r")])
3452 (define_insn "*cmpsf_trap"
3453   [(set (reg:CCFPE 24)
3454         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3455                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3456   "TARGET_HARD_FLOAT"
3457   "@
3458    cmf%?e\\t%0, %1
3459    cnf%?e\\t%0, #%N1"
3460 [(set_attr "conds" "set")
3461  (set_attr "type" "f_2_r")])
3463 (define_insn "*cmpdf_trap"
3464   [(set (reg:CCFPE 24)
3465         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3466                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3467   "TARGET_HARD_FLOAT"
3468   "@
3469    cmf%?e\\t%0, %1
3470    cnf%?e\\t%0, #%N1"
3471 [(set_attr "conds" "set")
3472  (set_attr "type" "f_2_r")])
3474 (define_insn "*cmp_esfdf_df_trap"
3475   [(set (reg:CCFPE 24)
3476         (compare:CCFPE (float_extend:DF
3477                         (match_operand:SF 0 "s_register_operand" "f,f"))
3478                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3479   "TARGET_HARD_FLOAT"
3480   "@
3481    cmf%?e\\t%0, %1
3482    cnf%?e\\t%0, #%N1"
3483 [(set_attr "conds" "set")
3484  (set_attr "type" "f_2_r")])
3486 (define_insn "*cmp_df_esfdf_trap"
3487   [(set (reg:CCFPE 24)
3488         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3489                        (float_extend:DF
3490                         (match_operand:SF 1 "s_register_operand" "f"))))]
3491   "TARGET_HARD_FLOAT"
3492   "cmf%?e\\t%0, %1"
3493 [(set_attr "conds" "set")
3494  (set_attr "type" "f_2_r")])
3496 (define_insn "*cmpxf_trap"
3497   [(set (reg:CCFPE 24)
3498         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3499                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3500   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3501   "@
3502    cmf%?e\\t%0, %1
3503    cnf%?e\\t%0, #%N1"
3504 [(set_attr "conds" "set")
3505  (set_attr "type" "f_2_r")])
3507 ; This insn allows redundant compares to be removed by cse, nothing should
3508 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3509 ; is deleted later on. The match_dup will match the mode here, so that
3510 ; mode changes of the condition codes aren't lost by this even though we don't
3511 ; specify what they are.
3513 (define_insn "*deleted_compare"
3514   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3515   ""
3516   "\\t%@ deleted compare"
3517 [(set_attr "conds" "set")
3518  (set_attr "length" "0")])
3521 ;; Conditional branch insns
3523 (define_expand "beq"
3524   [(set (pc)
3525         (if_then_else (eq (match_dup 1) (const_int 0))
3526                       (label_ref (match_operand 0 "" ""))
3527                       (pc)))]
3528   ""
3529   "
3531   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3532                                  arm_compare_fp);
3536 (define_expand "bne"
3537   [(set (pc)
3538         (if_then_else (ne (match_dup 1) (const_int 0))
3539                       (label_ref (match_operand 0 "" ""))
3540                       (pc)))]
3541   ""
3542   "
3544   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3545                                  arm_compare_fp);
3549 (define_expand "bgt"
3550   [(set (pc)
3551         (if_then_else (gt (match_dup 1) (const_int 0))
3552                       (label_ref (match_operand 0 "" ""))
3553                       (pc)))]
3554   ""
3555   "
3557   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3558                                  arm_compare_fp);
3562 (define_expand "ble"
3563   [(set (pc)
3564         (if_then_else (le (match_dup 1) (const_int 0))
3565                       (label_ref (match_operand 0 "" ""))
3566                       (pc)))]
3567   ""
3568   "
3570   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3571                                  arm_compare_fp);
3575 (define_expand "bge"
3576   [(set (pc)
3577         (if_then_else (ge (match_dup 1) (const_int 0))
3578                       (label_ref (match_operand 0 "" ""))
3579                       (pc)))]
3580   ""
3581   "
3583   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3584                                  arm_compare_fp);
3588 (define_expand "blt"
3589   [(set (pc)
3590         (if_then_else (lt (match_dup 1) (const_int 0))
3591                       (label_ref (match_operand 0 "" ""))
3592                       (pc)))]
3593   ""
3594   "
3596   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3597                                  arm_compare_fp);
3601 (define_expand "bgtu"
3602   [(set (pc)
3603         (if_then_else (gtu (match_dup 1) (const_int 0))
3604                       (label_ref (match_operand 0 "" ""))
3605                       (pc)))]
3606   ""
3607   "
3609   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3610                                  arm_compare_fp);
3614 (define_expand "bleu"
3615   [(set (pc)
3616         (if_then_else (leu (match_dup 1) (const_int 0))
3617                       (label_ref (match_operand 0 "" ""))
3618                       (pc)))]
3619   ""
3620   "
3622   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3623                                  arm_compare_fp);
3627 (define_expand "bgeu"
3628   [(set (pc)
3629         (if_then_else (geu (match_dup 1) (const_int 0))
3630                       (label_ref (match_operand 0 "" ""))
3631                       (pc)))]
3632   ""
3633   "
3635   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3636                                  arm_compare_fp);
3640 (define_expand "bltu"
3641   [(set (pc)
3642         (if_then_else (ltu (match_dup 1) (const_int 0))
3643                       (label_ref (match_operand 0 "" ""))
3644                       (pc)))]
3645   ""
3646   "
3648   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3649                                  arm_compare_fp);
3653 ;; patterns to match conditional branch insns
3655 (define_insn "*condbranch"
3656   [(set (pc)
3657         (if_then_else (match_operator 1 "comparison_operator"
3658                        [(match_operand 2 "cc_register" "") (const_int 0)])
3659                       (label_ref (match_operand 0 "" ""))
3660                       (pc)))]
3661   ""
3662   "*
3664   extern int arm_ccfsm_state;
3666   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3667   {
3668     arm_ccfsm_state += 2;
3669     return \"\";
3670   }
3671   return \"b%d1\\t%l0\";
3673 [(set_attr "conds" "use")])
3675 (define_insn "*condbranch_reversed"
3676   [(set (pc)
3677         (if_then_else (match_operator 1 "comparison_operator"
3678                        [(match_operand 2 "cc_register" "") (const_int 0)])
3679                       (pc)
3680                       (label_ref (match_operand 0 "" ""))))]
3681   ""
3682   "*
3684   extern int arm_ccfsm_state;
3686   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3687   {
3688     arm_ccfsm_state += 2;
3689     return \"\";
3690   }
3691   return \"b%D1\\t%l0\";
3693 [(set_attr "conds" "use")])
3696 ; scc insns
3698 (define_expand "seq"
3699   [(set (match_operand:SI 0 "s_register_operand" "=r")
3700         (eq:SI (match_dup 1) (const_int 0)))]
3701   ""
3702   "
3704   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3705                                  arm_compare_fp);
3709 (define_expand "sne"
3710   [(set (match_operand:SI 0 "s_register_operand" "=r")
3711         (ne:SI (match_dup 1) (const_int 0)))]
3712   ""
3713   "
3715   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3716                                  arm_compare_fp);
3720 (define_expand "sgt"
3721   [(set (match_operand:SI 0 "s_register_operand" "=r")
3722         (gt:SI (match_dup 1) (const_int 0)))]
3723   ""
3724   "
3726   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3727                                  arm_compare_fp);
3731 (define_expand "sle"
3732   [(set (match_operand:SI 0 "s_register_operand" "=r")
3733         (le:SI (match_dup 1) (const_int 0)))]
3734   ""
3735   "
3737   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3738                                  arm_compare_fp);
3742 (define_expand "sge"
3743   [(set (match_operand:SI 0 "s_register_operand" "=r")
3744         (ge:SI (match_dup 1) (const_int 0)))]
3745   ""
3746   "
3748   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3749                                  arm_compare_fp);
3753 (define_expand "slt"
3754   [(set (match_operand:SI 0 "s_register_operand" "=r")
3755         (lt:SI (match_dup 1) (const_int 0)))]
3756   ""
3757   "
3759   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3760                                  arm_compare_fp);
3764 (define_expand "sgtu"
3765   [(set (match_operand:SI 0 "s_register_operand" "=r")
3766         (gtu:SI (match_dup 1) (const_int 0)))]
3767   ""
3768   "
3770   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3771                                  arm_compare_fp);
3775 (define_expand "sleu"
3776   [(set (match_operand:SI 0 "s_register_operand" "=r")
3777         (leu:SI (match_dup 1) (const_int 0)))]
3778   ""
3779   "
3781   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3782                                  arm_compare_fp);
3786 (define_expand "sgeu"
3787   [(set (match_operand:SI 0 "s_register_operand" "=r")
3788         (geu:SI (match_dup 1) (const_int 0)))]
3789   ""
3790   "
3792   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3793                                  arm_compare_fp);
3797 (define_expand "sltu"
3798   [(set (match_operand:SI 0 "s_register_operand" "=r")
3799         (ltu:SI (match_dup 1) (const_int 0)))]
3800   ""
3801   "
3803   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3804                                  arm_compare_fp);
3808 (define_insn "*mov_scc"
3809   [(set (match_operand:SI 0 "s_register_operand" "=r")
3810         (match_operator:SI 1 "comparison_operator"
3811          [(match_operand 2 "cc_register" "") (const_int 0)]))]
3812   ""
3813   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
3814 [(set_attr "conds" "use")
3815  (set_attr "length" "8")])
3817 (define_insn "*mov_negscc"
3818   [(set (match_operand:SI 0 "s_register_operand" "=r")
3819         (neg:SI (match_operator:SI 1 "comparison_operator"
3820                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
3821   ""
3822   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
3823 [(set_attr "conds" "use")
3824  (set_attr "length" "8")])
3826 (define_insn "*mov_notscc"
3827   [(set (match_operand:SI 0 "s_register_operand" "=r")
3828         (not:SI (match_operator:SI 1 "comparison_operator"
3829                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
3830   ""
3831   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
3832 [(set_attr "conds" "use")
3833  (set_attr "length" "8")])
3836 ;; Conditional move insns
3838 (define_expand "movsicc"
3839   [(set (match_operand:SI 0 "s_register_operand" "")
3840         (if_then_else:SI (match_operand 1 "comparison_operator" "")
3841                          (match_operand:SI 2 "arm_not_operand" "")
3842                          (match_operand:SI 3 "arm_not_operand" "")))]
3843   ""
3844   "
3846   enum rtx_code code = GET_CODE (operands[1]);
3847   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3848                                arm_compare_fp);
3850   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3853 (define_expand "movsfcc"
3854   [(set (match_operand:SF 0 "s_register_operand" "")
3855         (if_then_else:SF (match_operand 1 "comparison_operator" "")
3856                          (match_operand:SF 2 "s_register_operand" "")
3857                          (match_operand:SF 3 "nonmemory_operand" "")))]
3858   ""
3859   "
3861   enum rtx_code code = GET_CODE (operands[1]);
3862   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3863                                arm_compare_fp);
3865   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3868 (define_expand "movdfcc"
3869   [(set (match_operand:DF 0 "s_register_operand" "")
3870         (if_then_else:DF (match_operand 1 "comparison_operator" "")
3871                          (match_operand:DF 2 "s_register_operand" "")
3872                          (match_operand:DF 3 "nonmemory_operand" "")))]
3873   "TARGET_HARD_FLOAT"
3874   "
3876   enum rtx_code code = GET_CODE (operands[1]);
3877   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3878                                arm_compare_fp);
3880   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3883 (define_insn "*movsicc_insn"
3884   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r")
3885         (if_then_else:SI
3886          (match_operator 3 "comparison_operator"
3887           [(match_operand 4 "cc_register" "") (const_int 0)])
3888          (match_operand:SI 1 "arm_not_operand" "0,0,?rI,?rI,K,K")
3889          (match_operand:SI 2 "arm_not_operand" "rI,K,rI,K,rI,K")))]
3890   ""
3891   "@
3892    mov%D3\\t%0, %2
3893    mvn%D3\\t%0, #%B2
3894    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
3895    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
3896    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
3897    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
3898   [(set_attr "length" "4,4,8,8,8,8")
3899    (set_attr "conds" "use")])
3901 (define_insn "*movsfcc_hard_insn"
3902   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
3903         (if_then_else:SF (match_operator 3 "comparison_operator" 
3904                           [(match_operand 4 "cc_register" "") (const_int 0)])
3905                          (match_operand:SF 1 "s_register_operand" "0,0")
3906                          (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
3907   "TARGET_HARD_FLOAT"
3908   "@
3909    mvf%D3s\\t%0, %2
3910    mnf%D3s\\t%0, #%N2"
3911   [(set_attr "type" "ffarith")
3912    (set_attr "conds" "use")])
3914 (define_insn "*movsfcc_soft_insn"
3915   [(set (match_operand:SF 0 "s_register_operand" "=r")
3916         (if_then_else:SF (match_operator 3 "comparison_operator"
3917                           [(match_operand 4 "cc_register" "") (const_int 0)])
3918                          (match_operand:SF 1 "s_register_operand" "0")
3919                          (match_operand:SF 2 "s_register_operand" "r")))]
3920   "TARGET_SOFT_FLOAT"
3921   "mov%D3\\t%0, %2"
3922   [(set_attr "conds" "use")])
3924 (define_insn "*movdfcc_insn"
3925   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
3926         (if_then_else:DF (match_operator 3 "comparison_operator"
3927                           [(match_operand 4 "cc_register" "") (const_int 0)])
3928                          (match_operand:DF 1 "s_register_operand" "0,0")
3929                          (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
3930   "TARGET_HARD_FLOAT"
3931   "@
3932    mvf%D3d\\t%0, %2
3933    mnf%D3d\\t%0, #%N2"
3934   [(set_attr "type" "ffarith")
3935    (set_attr "conds" "use")])
3937 ;; Jump and linkage insns
3939 (define_insn "jump"
3940   [(set (pc)
3941         (label_ref (match_operand 0 "" "")))]
3942   ""
3943   "*
3945   extern int arm_ccfsm_state;
3947   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3948   {
3949     arm_ccfsm_state += 2;
3950     return \"\";
3951   }
3952   return \"b%?\\t%l0\";
3955 (define_expand "call"
3956   [(parallel [(call (match_operand 0 "memory_operand" "")
3957                     (match_operand 1 "general_operand" ""))
3958               (clobber (reg:SI 14))])]
3959   ""
3960   "")
3962 (define_insn "*call_reg"
3963   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
3964          (match_operand 1 "" "g"))
3965    (clobber (reg:SI 14))]
3966   ""
3967   "*
3968   return output_call (operands);
3970 ;; length is worst case, normally it is only two
3971 [(set_attr "length" "12")
3972  (set_attr "type" "call")])
3974 (define_insn "*call_mem"
3975   [(call (mem:SI (match_operand 0 "memory_operand" "m"))
3976          (match_operand 1 "general_operand" "g"))
3977    (clobber (reg:SI 14))]
3978   ""
3979   "*
3980   return output_call_mem (operands);
3982 [(set_attr "length" "12")
3983  (set_attr "type" "call")])
3985 (define_expand "call_value"
3986   [(parallel [(set (match_operand 0 "" "=rf")
3987                    (call (match_operand 1 "memory_operand" "m")
3988                          (match_operand 2 "general_operand" "g")))
3989               (clobber (reg:SI 14))])]
3990   ""
3991   "")
3993 (define_insn "*call_value_reg"
3994   [(set (match_operand 0 "" "=rf")
3995         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
3996               (match_operand 2 "general_operand" "g")))
3997    (clobber (reg:SI 14))]
3998   ""
3999   "*
4000   return output_call (&operands[1]);
4002 [(set_attr "length" "12")
4003  (set_attr "type" "call")])
4005 (define_insn "*call_value_mem"
4006   [(set (match_operand 0 "" "=rf")
4007         (call (mem:SI (match_operand 1 "memory_operand" "m"))
4008         (match_operand 2 "general_operand" "g")))
4009    (clobber (reg:SI 14))]
4010   "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4011   "*
4012   return output_call_mem (&operands[1]);
4014 [(set_attr "length" "12")
4015  (set_attr "type" "call")])
4017 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4018 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4020 (define_insn "*call_symbol"
4021   [(call (mem:SI (match_operand:SI 0 "" "X"))
4022          (match_operand:SI 1 "general_operand" "g"))
4023    (clobber (reg:SI 14))]
4024   "GET_CODE (operands[0]) == SYMBOL_REF"
4025   "bl%?\\t%a0"
4026 [(set_attr "type" "call")])
4028 (define_insn "*call_value_symbol"
4029   [(set (match_operand 0 "s_register_operand" "=rf")
4030         (call (mem:SI (match_operand:SI 1 "" "X"))
4031         (match_operand:SI 2 "general_operand" "g")))
4032    (clobber (reg:SI 14))]
4033   "GET_CODE(operands[1]) == SYMBOL_REF"
4034   "bl%?\\t%a1"
4035 [(set_attr "type" "call")])
4037 ;; Often the return insn will be the same as loading from memory, so set attr
4038 (define_insn "return"
4039   [(return)]
4040   "USE_RETURN_INSN"
4041   "*
4043   extern int arm_ccfsm_state;
4045   if (arm_ccfsm_state == 2)
4046   {
4047     arm_ccfsm_state += 2;
4048     return \"\";
4049   }
4050   return output_return_instruction (NULL, TRUE, FALSE);
4052 [(set_attr "type" "load")])
4054 (define_insn "*cond_return"
4055   [(set (pc)
4056         (if_then_else (match_operator 0 "comparison_operator"
4057                        [(match_operand 1 "cc_register" "") (const_int 0)])
4058                       (return)
4059                       (pc)))]
4060   "USE_RETURN_INSN"
4061   "*
4063   extern int arm_ccfsm_state;
4065   if (arm_ccfsm_state == 2)
4066   {
4067     arm_ccfsm_state += 2;
4068     return \"\";
4069   }
4070   return output_return_instruction (operands[0], TRUE, FALSE);
4072 [(set_attr "conds" "use")
4073  (set_attr "type" "load")])
4075 (define_insn "*cond_return_inverted"
4076   [(set (pc)
4077         (if_then_else (match_operator 0 "comparison_operator"
4078                        [(match_operand 1 "cc_register" "") (const_int 0)])
4079                       (pc)
4080                       (return)))]
4081   "USE_RETURN_INSN"
4082   "*
4084   extern int arm_ccfsm_state;
4086   if (arm_ccfsm_state == 2)
4087   {
4088     arm_ccfsm_state += 2;
4089     return \"\";
4090   }
4091   return output_return_instruction (operands[0], TRUE, TRUE);
4093 [(set_attr "conds" "use")
4094  (set_attr "type" "load")])
4096 ;; Call subroutine returning any type.
4098 (define_expand "untyped_call"
4099   [(parallel [(call (match_operand 0 "" "")
4100                     (const_int 0))
4101               (match_operand 1 "" "")
4102               (match_operand 2 "" "")])]
4103   ""
4104   "
4106   int i;
4108   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4110   for (i = 0; i < XVECLEN (operands[2], 0); i++)
4111     {
4112       rtx set = XVECEXP (operands[2], 0, i);
4113       emit_move_insn (SET_DEST (set), SET_SRC (set));
4114     }
4116   /* The optimizer does not know that the call sets the function value
4117      registers we stored in the result block.  We avoid problems by
4118      claiming that all hard registers are used and clobbered at this
4119      point.  */
4120   emit_insn (gen_blockage ());
4122   DONE;
4125 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4126 ;; all of memory.  This blocks insns from being moved across this point.
4128 (define_insn "blockage"
4129   [(unspec_volatile [(const_int 0)] 0)]
4130   ""
4131   ""
4132 [(set_attr "length" "0")
4133  (set_attr "type" "block")])
4135 (define_expand "casesi"
4136   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
4137    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
4138    (match_operand:SI 2 "const_int_operand" "")  ; total range
4139    (match_operand:SI 3 "" "")                   ; table label
4140    (match_operand:SI 4 "" "")]                  ; Out of range label
4141   ""
4142   "
4144   rtx reg;
4145   if (operands[1] != const0_rtx)
4146     {
4147       reg = gen_reg_rtx (SImode);
4148       emit_insn (gen_addsi3 (reg, operands[0],
4149                              GEN_INT (-INTVAL (operands[1]))));
4150       operands[0] = reg;
4151     }
4153   if (! const_ok_for_arm (INTVAL (operands[2])))
4154     operands[2] = force_reg (SImode, operands[2]);
4156   emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4157                                        operands[4]));
4158   DONE;
4161 (define_insn "casesi_internal"
4162   [(set (pc)
4163         (if_then_else
4164          (leu (match_operand:SI 0 "s_register_operand" "r")
4165               (match_operand:SI 1 "arm_rhs_operand" "rI"))
4166          (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4167                           (label_ref (match_operand 2 "" ""))))
4168          (label_ref (match_operand 3 "" ""))))]
4169   ""
4170   "*
4171   if (flag_pic)
4172     return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4173   return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4175 [(set_attr "conds" "clob")
4176  (set_attr "length" "12")])
4178 (define_insn "indirect_jump"
4179   [(set (pc)
4180         (match_operand:SI 0 "s_register_operand" "r"))]
4181   ""
4182   "mov%?\\t%|pc, %0\\t%@ indirect jump")
4184 (define_insn "*load_indirect_jump"
4185   [(set (pc)
4186         (match_operand:SI 0 "memory_operand" "m"))]
4187   ""
4188   "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4189 [(set_attr "type" "load")])
4191 ;; Misc insns
4193 (define_insn "nop"
4194   [(const_int 0)]
4195   ""
4196   "mov%?\\tr0, r0\\t%@ nop")
4198 ;; Patterns to allow combination of arithmetic, cond code and shifts
4200 (define_insn "*arith_shiftsi"
4201   [(set (match_operand:SI 0 "s_register_operand" "=r")
4202         (match_operator:SI 1 "shiftable_operator"
4203           [(match_operator:SI 3 "shift_operator"
4204              [(match_operand:SI 4 "s_register_operand" "r")
4205               (match_operand:SI 5 "reg_or_int_operand" "rI")])
4206            (match_operand:SI 2 "s_register_operand" "r")]))]
4207   ""
4208   "%i1%?\\t%0, %2, %4%S3")
4210 (define_insn "*arith_shiftsi_compare0"
4211   [(set (reg:CC_NOOV 24)
4212         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4213                           [(match_operator:SI 3 "shift_operator"
4214                             [(match_operand:SI 4 "s_register_operand" "r")
4215                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4216                            (match_operand:SI 2 "s_register_operand" "r")])
4217                          (const_int 0)))
4218    (set (match_operand:SI 0 "s_register_operand" "=r")
4219         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4220                          (match_dup 2)]))]
4221   ""
4222   "%i1%?s\\t%0, %2, %4%S3"
4223 [(set_attr "conds" "set")])
4225 (define_insn "*arith_shiftsi_compare0_scratch"
4226   [(set (reg:CC_NOOV 24)
4227         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4228                           [(match_operator:SI 3 "shift_operator"
4229                             [(match_operand:SI 4 "s_register_operand" "r")
4230                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4231                            (match_operand:SI 2 "s_register_operand" "r")])
4232                          (const_int 0)))
4233    (clobber (match_scratch:SI 0 "=r"))]
4234   ""
4235   "%i1%?s\\t%0, %2, %4%S3"
4236 [(set_attr "conds" "set")])
4238 (define_insn "*sub_shiftsi"
4239   [(set (match_operand:SI 0 "s_register_operand" "=r")
4240         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4241                   (match_operator:SI 2 "shift_operator"
4242                    [(match_operand:SI 3 "s_register_operand" "r")
4243                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4244   ""
4245   "sub%?\\t%0, %1, %3%S2")
4247 (define_insn "*sub_shiftsi_compare0"
4248   [(set (reg:CC_NOOV 24)
4249         (compare:CC_NOOV
4250          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4251                    (match_operator:SI 2 "shift_operator"
4252                     [(match_operand:SI 3 "s_register_operand" "r")
4253                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4254          (const_int 0)))
4255    (set (match_operand:SI 0 "s_register_operand" "=r")
4256         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4257                                                  (match_dup 4)])))]
4258   ""
4259   "sub%?s\\t%0, %1, %3%S2"
4260 [(set_attr "conds" "set")])
4262 (define_insn "*sub_shiftsi_compare0_scratch"
4263   [(set (reg:CC_NOOV 24)
4264         (compare:CC_NOOV
4265          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4266                    (match_operator:SI 2 "shift_operator"
4267                     [(match_operand:SI 3 "s_register_operand" "r")
4268                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4269          (const_int 0)))
4270    (clobber (match_scratch:SI 0 "=r"))]
4271   ""
4272   "sub%?s\\t%0, %1, %3%S2"
4273 [(set_attr "conds" "set")])
4275 ;; These variants of the above insns can occur if the first operand is the
4276 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
4277 ;; seem to be a way around it.  Most of the predicates have to be null
4278 ;; because the format can be generated part way through reload, so
4279 ;; if we don't match it as soon as it becomes available, reload doesn't know
4280 ;; how to reload pseudos that haven't got hard registers; the constraints will
4281 ;; sort everything out.
4283 (define_insn "*reload_mulsi3"
4284   [(set (match_operand:SI 0 "" "=&r")
4285         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4286                            [(match_operand:SI 3 "" "r")
4287                             (match_operand:SI 4 "" "rM")])
4288                           (match_operand:SI 2 "" "r"))
4289                  (match_operand:SI 1 "const_int_operand" "n")))]
4290   "reload_in_progress"
4291   "*
4292   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4293   operands[2] = operands[1];
4294   operands[1] = operands[0];
4295   return output_add_immediate (operands);
4297 ; we have no idea how long the add_immediate is, it could be up to 4.
4298 [(set_attr "length" "20")])
4300 (define_insn "*reload_mulsi_compare0"
4301   [(set (reg:CC_NOOV 24)
4302         (compare:CC_NOOV (plus:SI
4303                           (plus:SI 
4304                            (match_operator:SI 5 "shift_operator"
4305                             [(match_operand:SI 3 "" "r")
4306                              (match_operand:SI 4 "" "rM")])
4307                            (match_operand:SI 1 "" "r"))
4308                           (match_operand:SI 2 "const_int_operand" "n"))
4309                          (const_int 0)))
4310    (set (match_operand:SI 0 "" "=&r")
4311         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4312                           (match_dup 1))
4313                  (match_dup 2)))]
4314   "reload_in_progress"
4315   "*
4316   output_add_immediate (operands);
4317   return \"add%?s\\t%0, %0, %3%S5\";
4319 [(set_attr "conds" "set")
4320  (set_attr "length" "20")])
4322 (define_insn "*reload_mulsi_compare0_scratch"
4323   [(set (reg:CC_NOOV 24)
4324         (compare:CC_NOOV (plus:SI
4325                           (plus:SI 
4326                            (match_operator:SI 5 "shift_operator"
4327                             [(match_operand:SI 3 "" "r")
4328                              (match_operand:SI 4 "" "rM")])
4329                            (match_operand:SI 1 "" "r"))
4330                           (match_operand:SI 2 "const_int_operand" "n"))
4331                          (const_int 0)))
4332    (clobber (match_scratch:SI 0 "=&r"))]
4333   "reload_in_progress"
4334   "*
4335   output_add_immediate (operands);
4336   return \"add%?s\\t%0, %0, %3%S5\";
4338 [(set_attr "conds" "set")
4339  (set_attr "length" "20")])
4341 ;; These are similar, but are needed when the mla pattern contains the
4342 ;; eliminated register as operand 3.
4344 (define_insn "*reload_muladdsi"
4345   [(set (match_operand:SI 0 "" "=&r,&r")
4346         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4347                                    (match_operand:SI 2 "" "r,r"))
4348                           (match_operand:SI 3 "" "r,r"))
4349                  (match_operand:SI 4 "const_int_operand" "n,n")))]
4350   "reload_in_progress"
4351   "*
4352   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4353   operands[2] = operands[4];
4354   operands[1] = operands[0];
4355   return output_add_immediate (operands);
4357 [(set_attr "length" "20")
4358  (set_attr "type" "mult")])
4360 (define_insn "*reload_muladdsi_compare0"
4361   [(set (reg:CC_NOOV 24)
4362         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4363                                             (match_operand:SI 3 "" "r")
4364                                             (match_operand:SI 4 "" "r"))
4365                                            (match_operand:SI 1 "" "r"))
4366                                   (match_operand:SI 2 "const_int_operand" "n"))
4367                          (const_int 0)))
4368    (set (match_operand:SI 0 "" "=&r")
4369         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4370                  (match_dup 2)))]
4371   "reload_in_progress"
4372   "*
4373   output_add_immediate (operands);
4374   output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4375   return \"\";
4377 [(set_attr "length" "20")
4378  (set_attr "conds" "set")
4379  (set_attr "type" "mult")])
4381 (define_insn "*reload_muladdsi_compare0_scratch"
4382   [(set (reg:CC_NOOV 24)
4383         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4384                                             (match_operand:SI 3 "" "r")
4385                                             (match_operand:SI 4 "" "r"))
4386                                            (match_operand:SI 1 "" "r"))
4387                                   (match_operand:SI 2 "const_int_operand" "n"))
4388                          (const_int 0)))
4389    (clobber (match_scratch:SI 0 "=&r"))]
4390   "reload_in_progress"
4391   "*
4392   output_add_immediate (operands);
4393   return \"mla%?s\\t%0, %3, %4, %0\";
4395 [(set_attr "length" "20")
4396  (set_attr "conds" "set")
4397  (set_attr "type" "mult")])
4401 (define_insn "*and_scc"
4402   [(set (match_operand:SI 0 "s_register_operand" "=r")
4403         (and:SI (match_operator 1 "comparison_operator"
4404                  [(match_operand 3 "cc_register" "") (const_int 0)])
4405                 (match_operand:SI 2 "s_register_operand" "r")))]
4406   ""
4407   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
4408 [(set_attr "conds" "use")
4409  (set_attr "length" "8")])
4411 (define_insn "*ior_scc"
4412   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4413         (ior:SI (match_operator 2 "comparison_operator"
4414                  [(match_operand 3 "cc_register" "") (const_int 0)])
4415                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
4416   ""
4417   "@
4418    orr%d2\\t%0, %1, #1
4419    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
4420 [(set_attr "conds" "use")
4421  (set_attr "length" "4,8")])
4423 (define_insn "*compare_scc"
4424   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4425         (match_operator 1 "comparison_operator"
4426          [(match_operand:SI 2 "s_register_operand" "r,r")
4427           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4428    (clobber (reg 24))]
4429   ""
4430   "*
4431   if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4432     return \"mov\\t%0, %2, lsr #31\";
4434   if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4435     return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4437   if (GET_CODE (operands[1]) == NE)
4438     {
4439       if (which_alternative == 1)
4440         return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4441       return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4442     }
4443   if (which_alternative == 1)
4444     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4445   else
4446     output_asm_insn (\"cmp\\t%2, %3\", operands);
4447   return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4449 [(set_attr "conds" "clob")
4450  (set_attr "length" "12")])
4452 (define_insn "*cond_move"
4453   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4454         (if_then_else:SI (match_operator 3 "equality_operator"
4455                           [(match_operator 4 "comparison_operator"
4456                             [(match_operand 5 "cc_register" "") (const_int 0)])
4457                            (const_int 0)])
4458                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4459                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4460   ""
4461   "*
4462   if (GET_CODE (operands[3]) == NE)
4463     {
4464       if (which_alternative != 1)
4465         output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4466       if (which_alternative != 0)
4467         output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4468       return \"\";
4469     }
4470   if (which_alternative != 0)
4471     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4472   if (which_alternative != 1)
4473     output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4474   return \"\";
4476 [(set_attr "conds" "use")
4477  (set_attr "length" "4,4,8")])
4479 (define_insn "*cond_arith"
4480   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4481         (match_operator:SI 5 "shiftable_operator" 
4482          [(match_operator:SI 4 "comparison_operator"
4483            [(match_operand:SI 2 "s_register_operand" "r,r")
4484             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4485           (match_operand:SI 1 "s_register_operand" "0,?r")]))
4486    (clobber (reg 24))]
4487   ""
4488   "*
4489   if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4490     return \"%i5\\t%0, %1, %2, lsr #31\";
4492   output_asm_insn (\"cmp\\t%2, %3\", operands);
4493   if (GET_CODE (operands[5]) == AND)
4494     output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4495   else if (GET_CODE (operands[5]) == MINUS)
4496     output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4497   else if (which_alternative != 0)
4498     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4499   return \"%i5%d4\\t%0, %1, #1\";
4501 [(set_attr "conds" "clob")
4502  (set_attr "length" "12")])
4504 (define_insn "*cond_sub"
4505   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4506         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4507                   (match_operator:SI 4 "comparison_operator"
4508                    [(match_operand:SI 2 "s_register_operand" "r,r")
4509                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4510    (clobber (reg 24))]
4511   ""
4512   "*
4513   output_asm_insn (\"cmp\\t%2, %3\", operands);
4514   if (which_alternative != 0)
4515     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4516   return \"sub%d4\\t%0, %1, #1\";
4518 [(set_attr "conds" "clob")
4519  (set_attr "length" "8,12")])
4521 (define_insn "*cmp_ite0"
4522   [(set (match_operand 6 "dominant_cc_register" "")
4523         (compare
4524          (if_then_else:SI
4525           (match_operator 4 "comparison_operator"
4526            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4527             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4528           (match_operator:SI 5 "comparison_operator"
4529            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4530             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4531           (const_int 0))
4532          (const_int 0)))]
4533   ""
4534   "*
4536   char* opcodes[4][2] =
4537   {
4538     {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
4539     {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
4540     {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
4541     {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
4542      \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
4543   };
4544   int swap =
4545     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
4547   return opcodes[which_alternative][swap];
4550 [(set_attr "conds" "set")
4551  (set_attr "length" "8")])
4553 (define_insn "*cmp_ite1"
4554   [(set (match_operand 6 "dominant_cc_register" "")
4555         (compare
4556          (if_then_else:SI
4557           (match_operator 4 "comparison_operator"
4558            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4559             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4560           (match_operator:SI 5 "comparison_operator"
4561            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4562             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4563           (const_int 1))
4564          (const_int 0)))]
4565   ""
4566   "*
4568   char* opcodes[4][2] =
4569   {
4570     {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
4571     {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
4572     {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
4573     {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
4574      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
4575   };
4576   int swap =
4577     comparison_dominates_p (GET_CODE (operands[5]),
4578                             reverse_condition (GET_CODE (operands[4])));
4580   return opcodes[which_alternative][swap];
4583 [(set_attr "conds" "set")
4584  (set_attr "length" "8")])
4586 (define_insn "*negscc"
4587   [(set (match_operand:SI 0 "s_register_operand" "=r")
4588         (neg:SI (match_operator 3 "comparison_operator"
4589                  [(match_operand:SI 1 "s_register_operand" "r")
4590                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4591    (clobber (reg 24))]
4592   ""
4593   "*
4594   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4595     return \"mov\\t%0, %1, asr #31\";
4597   if (GET_CODE (operands[3]) == NE)
4598     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4600   if (GET_CODE (operands[3]) == GT)
4601     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4603   output_asm_insn (\"cmp\\t%1, %2\", operands);
4604   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4605   return \"mvn%d3\\t%0, #0\";
4607 [(set_attr "conds" "clob")
4608  (set_attr "length" "12")])
4610 (define_insn "movcond"
4611   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4612         (if_then_else:SI
4613          (match_operator 5 "comparison_operator"
4614           [(match_operand:SI 3 "s_register_operand" "r,r,r")
4615            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4616          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4617          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4618    (clobber (reg 24))]
4619   ""
4620   "*
4621   if (GET_CODE (operands[5]) == LT
4622       && (operands[4] == const0_rtx))
4623     {
4624       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4625         {
4626           if (operands[2] == const0_rtx)
4627             return \"and\\t%0, %1, %3, asr #31\";
4628           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4629         }
4630       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4631         {
4632           if (operands[1] == const0_rtx)
4633             return \"bic\\t%0, %2, %3, asr #31\";
4634           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4635         }
4636       /* The only case that falls through to here is when both ops 1 & 2
4637          are constants */
4638     }
4640   if (GET_CODE (operands[5]) == GE
4641       && (operands[4] == const0_rtx))
4642     {
4643       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4644         {
4645           if (operands[2] == const0_rtx)
4646             return \"bic\\t%0, %1, %3, asr #31\";
4647           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4648         }
4649       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4650         {
4651           if (operands[1] == const0_rtx)
4652             return \"and\\t%0, %2, %3, asr #31\";
4653           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4654         }
4655       /* The only case that falls through to here is when both ops 1 & 2
4656          are constants */
4657     }
4658   if (GET_CODE (operands[4]) == CONST_INT
4659       && !const_ok_for_arm (INTVAL (operands[4])))
4660     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4661   else
4662     output_asm_insn (\"cmp\\t%3, %4\", operands);
4663   if (which_alternative != 0)
4664     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4665   if (which_alternative != 1)
4666     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4667   return \"\";
4669 [(set_attr "conds" "clob")
4670  (set_attr "length" "8,8,12")])
4672 (define_insn "*ifcompare_plus_move"
4673   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4674         (if_then_else:SI (match_operator 6 "comparison_operator"
4675                           [(match_operand:SI 4 "s_register_operand" "r,r")
4676                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4677                          (plus:SI
4678                           (match_operand:SI 2 "s_register_operand" "r,r")
4679                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
4680                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4681    (clobber (reg 24))]
4682   ""
4683   "#"
4684 [(set_attr "conds" "clob")
4685  (set_attr "length" "8,12")])
4687 (define_insn "*if_plus_move"
4688   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r")
4689         (if_then_else:SI
4690          (match_operator 4 "comparison_operator"
4691           [(match_operand 5 "cc_register" "") (const_int 0)])
4692          (plus:SI
4693           (match_operand:SI 2 "s_register_operand" "r,r,r,r,r,r")
4694           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L,rI,L"))
4695          (match_operand:SI 1 "arm_rhsm_operand" "0,0,?rI,?rI,m,m")))]
4696   ""
4697   "@
4698    add%d4\\t%0, %2, %3
4699    sub%d4\\t%0, %2, #%n3
4700    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4701    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1
4702    add%d4\\t%0, %2, %3\;ldr%D4\\t%0, %1
4703    sub%d4\\t%0, %2, #%n3\;ldr%D4\\t%0, %1"
4704 [(set_attr "conds" "use")
4705  (set_attr "length" "4,4,8,8,8,8")
4706  (set_attr "type" "*,*,*,*,load,load")])
4708 (define_insn "*ifcompare_move_plus"
4709   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4710         (if_then_else:SI (match_operator 6 "comparison_operator"
4711                           [(match_operand:SI 4 "s_register_operand" "r,r")
4712                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4713                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4714                          (plus:SI
4715                           (match_operand:SI 2 "s_register_operand" "r,r")
4716                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4717    (clobber (reg 24))]
4718   ""
4719   "#"
4720 [(set_attr "conds" "clob")
4721  (set_attr "length" "8,12")])
4723 (define_insn "*if_move_plus"
4724   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r")
4725         (if_then_else:SI
4726          (match_operator 4 "comparison_operator"
4727           [(match_operand 5 "cc_register" "") (const_int 0)])
4728          (match_operand:SI 1 "arm_rhsm_operand" "0,0,?rI,?rI,m,m")
4729          (plus:SI
4730           (match_operand:SI 2 "s_register_operand" "r,r,r,r,r,r")
4731           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L,rI,L"))))]
4732   ""
4733   "@
4734    add%D4\\t%0, %2, %3
4735    sub%D4\\t%0, %2, #%n3
4736    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4737    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1
4738    add%D4\\t%0, %2, %3\;ldr%d4\\t%0, %1
4739    sub%D4\\t%0, %2, #%n3\;ldr%d4\\t%0, %1"
4740 [(set_attr "conds" "use")
4741  (set_attr "length" "4,4,8,8,8,8")
4742  (set_attr "type" "*,*,*,*,load,load")])
4744 (define_insn "*ifcompare_arith_arith"
4745   [(set (match_operand:SI 0 "s_register_operand" "=r")
4746         (if_then_else:SI (match_operator 9 "comparison_operator"
4747                           [(match_operand:SI 5 "s_register_operand" "r")
4748                            (match_operand:SI 6 "arm_add_operand" "rIL")])
4749                          (match_operator:SI 8 "shiftable_operator"
4750                           [(match_operand:SI 1 "s_register_operand" "r")
4751                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
4752                          (match_operator:SI 7 "shiftable_operator"
4753                           [(match_operand:SI 3 "s_register_operand" "r")
4754                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
4755    (clobber (reg 24))]
4756   ""
4757   "#"
4758 [(set_attr "conds" "clob")
4759  (set_attr "length" "12")])
4761 (define_insn "*if_arith_arith"
4762   [(set (match_operand:SI 0 "s_register_operand" "=r")
4763         (if_then_else:SI (match_operator 5 "comparison_operator"
4764                           [(match_operand 8 "cc_register" "") (const_int 0)])
4765                          (match_operator:SI 6 "shiftable_operator"
4766                           [(match_operand:SI 1 "s_register_operand" "r")
4767                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
4768                          (match_operator:SI 7 "shiftable_operator"
4769                           [(match_operand:SI 3 "s_register_operand" "r")
4770                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
4771   ""
4772   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
4773 [(set_attr "conds" "use")
4774  (set_attr "length" "8")])
4776 (define_insn "*ifcompare_arith_move"
4777   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4778         (if_then_else:SI (match_operator 6 "comparison_operator"
4779                           [(match_operand:SI 2 "s_register_operand" "r,r")
4780                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
4781                          (match_operator:SI 7 "shiftable_operator"
4782                           [(match_operand:SI 4 "s_register_operand" "r,r")
4783                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
4784                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4785    (clobber (reg 24))]
4786   ""
4787   "*
4788   /* If we have an operation where (op x 0) is the identity operation and
4789      the conditional operator is LT or GE and we are comparing against zero and
4790      everything is in registers then we can do this in two instructions */
4791   if (operands[3] == const0_rtx
4792       && GET_CODE (operands[7]) != AND
4793       && GET_CODE (operands[5]) == REG
4794       && GET_CODE (operands[1]) == REG 
4795       && REGNO (operands[1]) == REGNO (operands[4])
4796       && REGNO (operands[4]) != REGNO (operands[0]))
4797     {
4798       if (GET_CODE (operands[6]) == LT)
4799         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4800       else if (GET_CODE (operands[6]) == GE)
4801         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4802     }
4803   if (GET_CODE (operands[3]) == CONST_INT
4804       && !const_ok_for_arm (INTVAL (operands[3])))
4805     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4806   else
4807     output_asm_insn (\"cmp\\t%2, %3\", operands);
4808   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
4809   if (which_alternative != 0)
4810     {
4811       if (GET_CODE (operands[1]) == MEM)
4812         return \"ldr%D6\\t%0, %1\";
4813       else
4814         return \"mov%D6\\t%0, %1\";
4815     }
4816   return \"\";
4818 [(set_attr "conds" "clob")
4819  (set_attr "length" "8,12")])
4821 (define_insn "*if_arith_move"
4822   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4823         (if_then_else:SI (match_operator 4 "comparison_operator"
4824                           [(match_operand 6 "cc_register" "") (const_int 0)])
4825                          (match_operator:SI 5 "shiftable_operator"
4826                           [(match_operand:SI 2 "s_register_operand" "r,r,r")
4827                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI")])
4828                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rI,m")))]
4829   ""
4830   "@
4831    %I5%d4\\t%0, %2, %3
4832    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4833    %I5%d4\\t%0, %2, %3\;ldr%D4\\t%0, %1"
4834 [(set_attr "conds" "use")
4835  (set_attr "length" "4,8,8")
4836  (set_attr "type" "*,*,load")])
4838 (define_insn "*ifcompare_move_arith"
4839   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4840         (if_then_else:SI (match_operator 6 "comparison_operator"
4841                           [(match_operand:SI 4 "s_register_operand" "r,r")
4842                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4843                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4844                          (match_operator:SI 7 "shiftable_operator"
4845                           [(match_operand:SI 2 "s_register_operand" "r,r")
4846                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4847    (clobber (reg 24))]
4848   ""
4849   "*
4850   /* If we have an operation where (op x 0) is the identity operation and
4851      the conditional operator is LT or GE and we are comparing against zero and
4852      everything is in registers then we can do this in two instructions */
4853   if (operands[5] == const0_rtx
4854       && GET_CODE (operands[7]) != AND
4855       && GET_CODE (operands[3]) == REG
4856       && GET_CODE (operands[1]) == REG 
4857       && REGNO (operands[1]) == REGNO (operands[2])
4858       && REGNO (operands[2]) != REGNO (operands[0]))
4859     {
4860       if (GET_CODE (operands[6]) == GE)
4861         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4862       else if (GET_CODE (operands[6]) == LT)
4863         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4864     }
4866   if (GET_CODE (operands[5]) == CONST_INT
4867       && !const_ok_for_arm (INTVAL (operands[5])))
4868     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4869   else
4870     output_asm_insn (\"cmp\\t%4, %5\", operands);
4872   if (which_alternative != 0)
4873     {
4874       if (GET_CODE (operands[1]) == MEM)
4875         output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4876       else
4877         output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4878     }
4879   return \"%I7%D6\\t%0, %2, %3\";
4881 [(set_attr "conds" "clob")
4882  (set_attr "length" "8,12")])
4884 (define_insn "*if_move_arith"
4885   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4886         (if_then_else:SI
4887          (match_operator 4 "comparison_operator"
4888           [(match_operand 6 "cc_register" "") (const_int 0)])
4889          (match_operand:SI 1 "arm_rhsm_operand" "0,?rI,m")
4890          (match_operator:SI 5 "shiftable_operator"
4891           [(match_operand:SI 2 "s_register_operand" "r,r,r")
4892            (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI")])))]
4893   ""
4894   "@
4895    %I5%D4\\t%0, %2, %3
4896    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4897    %I5%D4\\t%0, %2, %3\;ldr%d4\\t%0, %1"
4898 [(set_attr "conds" "use")
4899  (set_attr "length" "4,8,8")
4900  (set_attr "type" "*,*,load")])
4902 (define_insn "*ifcompare_move_not"
4903   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4904         (if_then_else:SI
4905          (match_operator 5 "comparison_operator"
4906           [(match_operand:SI 3 "s_register_operand" "r,r")
4907            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
4908          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
4909          (not:SI
4910           (match_operand:SI 2 "s_register_operand" "r,r"))))
4911    (clobber (reg 24))]
4912   ""
4913   "#"
4914 [(set_attr "conds" "clob")
4915  (set_attr "length" "8,12")])
4917 (define_insn "*if_move_not"
4918   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4919         (if_then_else:SI
4920          (match_operator 4 "comparison_operator"
4921           [(match_operand 3 "cc_register" "") (const_int 0)])
4922          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
4923          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
4924   ""
4925   "@
4926    mvn%D4\\t%0, %2
4927    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
4928    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
4929 [(set_attr "conds" "use")
4930  (set_attr "length" "4,8,8")])
4932 (define_insn "*ifcompare_not_move"
4933   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4934         (if_then_else:SI 
4935          (match_operator 5 "comparison_operator"
4936           [(match_operand:SI 3 "s_register_operand" "r,r")
4937            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
4938          (not:SI
4939           (match_operand:SI 2 "s_register_operand" "r,r"))
4940          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
4941    (clobber (reg 24))]
4942   ""
4943   "#"
4944 [(set_attr "conds" "clob")
4945  (set_attr "length" "8,12")])
4947 (define_insn "*if_not_move"
4948   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4949         (if_then_else:SI
4950          (match_operator 4 "comparison_operator"
4951           [(match_operand 3 "cc_register" "") (const_int 0)])
4952          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
4953          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
4954   ""
4955   "@
4956    mvn%d4\\t%0, %2
4957    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
4958    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
4959 [(set_attr "conds" "use")
4960  (set_attr "length" "4,8,8")])
4962 (define_insn "*ifcompare_shift_move"
4963   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4964         (if_then_else:SI
4965          (match_operator 6 "comparison_operator"
4966           [(match_operand:SI 4 "s_register_operand" "r,r")
4967            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4968          (match_operator:SI 7 "shift_operator"
4969           [(match_operand:SI 2 "s_register_operand" "r,r")
4970            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
4971          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
4972    (clobber (reg 24))]
4973   ""
4974   "#"
4975 [(set_attr "conds" "clob")
4976  (set_attr "length" "8,12")])
4978 (define_insn "*if_shift_move"
4979   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4980         (if_then_else:SI
4981          (match_operator 5 "comparison_operator"
4982           [(match_operand 6 "cc_register" "") (const_int 0)])
4983          (match_operator:SI 4 "shift_operator"
4984           [(match_operand:SI 2 "s_register_operand" "r,r,r")
4985            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
4986          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
4987   ""
4988   "@
4989    mov%d5\\t%0, %2%S4
4990    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
4991    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
4992 [(set_attr "conds" "use")
4993  (set_attr "length" "4,8,8")])
4995 (define_insn "*ifcompare_move_shift"
4996   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4997         (if_then_else:SI
4998          (match_operator 6 "comparison_operator"
4999           [(match_operand:SI 4 "s_register_operand" "r,r")
5000            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5001          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5002          (match_operator:SI 7 "shift_operator"
5003           [(match_operand:SI 2 "s_register_operand" "r,r")
5004            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5005    (clobber (reg 24))]
5006   ""
5007   "#"
5008 [(set_attr "conds" "clob")
5009  (set_attr "length" "8,12")])
5011 (define_insn "*if_move_shift"
5012   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5013         (if_then_else:SI
5014          (match_operator 5 "comparison_operator"
5015           [(match_operand 6 "cc_register" "") (const_int 0)])
5016          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5017          (match_operator:SI 4 "shift_operator"
5018           [(match_operand:SI 2 "s_register_operand" "r,r,r")
5019            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5020   ""
5021   "@
5022    mov%D5\\t%0, %2%S4
5023    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5024    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5025 [(set_attr "conds" "use")
5026  (set_attr "length" "4,8,8")])
5028 (define_insn "*ifcompare_shift_shift"
5029   [(set (match_operand:SI 0 "s_register_operand" "=r")
5030         (if_then_else:SI
5031          (match_operator 7 "comparison_operator"
5032           [(match_operand:SI 5 "s_register_operand" "r")
5033            (match_operand:SI 6 "arm_add_operand" "rIL")])
5034          (match_operator:SI 8 "shift_operator"
5035           [(match_operand:SI 1 "s_register_operand" "r")
5036            (match_operand:SI 2 "arm_rhs_operand" "rM")])
5037          (match_operator:SI 9 "shift_operator"
5038           [(match_operand:SI 3 "s_register_operand" "r")
5039            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5040    (clobber (reg 24))]
5041   ""
5042   "#"
5043 [(set_attr "conds" "clob")
5044  (set_attr "length" "12")])
5046 (define_insn "*if_shift_shift"
5047   [(set (match_operand:SI 0 "s_register_operand" "=r")
5048         (if_then_else:SI
5049          (match_operator 5 "comparison_operator"
5050           [(match_operand 8 "cc_register" "") (const_int 0)])
5051          (match_operator:SI 6 "shift_operator"
5052           [(match_operand:SI 1 "s_register_operand" "r")
5053            (match_operand:SI 2 "arm_rhs_operand" "rM")])
5054          (match_operator:SI 7 "shift_operator"
5055           [(match_operand:SI 3 "s_register_operand" "r")
5056            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5057   ""
5058   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5059 [(set_attr "conds" "use")
5060  (set_attr "length" "8")])
5062 (define_insn "*ifcompare_not_arith"
5063   [(set (match_operand:SI 0 "s_register_operand" "=r")
5064         (if_then_else:SI
5065          (match_operator 6 "comparison_operator"
5066           [(match_operand:SI 4 "s_register_operand" "r")
5067            (match_operand:SI 5 "arm_add_operand" "rIL")])
5068          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5069          (match_operator:SI 7 "shiftable_operator"
5070           [(match_operand:SI 2 "s_register_operand" "r")
5071            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5072    (clobber (reg 24))]
5073   ""
5074   "#"
5075 [(set_attr "conds" "clob")
5076  (set_attr "length" "12")])
5078 (define_insn "*if_not_arith"
5079   [(set (match_operand:SI 0 "s_register_operand" "=r")
5080         (if_then_else:SI
5081          (match_operator 5 "comparison_operator"
5082           [(match_operand 4 "cc_register" "") (const_int 0)])
5083          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5084          (match_operator:SI 6 "shiftable_operator"
5085           [(match_operand:SI 2 "s_register_operand" "r")
5086            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5087   ""
5088   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5089 [(set_attr "conds" "use")
5090  (set_attr "length" "8")])
5092 (define_insn "*ifcompare_arith_not"
5093   [(set (match_operand:SI 0 "s_register_operand" "=r")
5094         (if_then_else:SI
5095          (match_operator 6 "comparison_operator"
5096           [(match_operand:SI 4 "s_register_operand" "r")
5097            (match_operand:SI 5 "arm_add_operand" "rIL")])
5098          (match_operator:SI 7 "shiftable_operator"
5099           [(match_operand:SI 2 "s_register_operand" "r")
5100            (match_operand:SI 3 "arm_rhs_operand" "rI")])
5101          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5102    (clobber (reg 24))]
5103   ""
5104   "#"
5105 [(set_attr "conds" "clob")
5106  (set_attr "length" "12")])
5108 (define_insn "*if_arith_not"
5109   [(set (match_operand:SI 0 "s_register_operand" "=r")
5110         (if_then_else:SI
5111          (match_operator 5 "comparison_operator"
5112           [(match_operand 4 "cc_register" "") (const_int 0)])
5113          (match_operator:SI 6 "shiftable_operator"
5114           [(match_operand:SI 2 "s_register_operand" "r")
5115            (match_operand:SI 3 "arm_rhs_operand" "rI")])
5116          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5117   ""
5118   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5119 [(set_attr "conds" "use")
5120  (set_attr "length" "8")])
5122 (define_insn "*ifcompare_neg_move"
5123   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5124         (if_then_else:SI
5125          (match_operator 5 "comparison_operator"
5126           [(match_operand:SI 3 "s_register_operand" "r,r")
5127            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5128          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5129          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5130    (clobber (reg:CC 24))]
5131   ""
5132   "#"
5133 [(set_attr "conds" "clob")
5134  (set_attr "length" "8,12")])
5136 (define_insn "*if_neg_move"
5137   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5138         (if_then_else:SI
5139          (match_operator 4 "comparison_operator"
5140           [(match_operand 3 "cc_register" "") (const_int 0)])
5141          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5142          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5143   ""
5144   "@
5145    rsb%d4\\t%0, %2, #0
5146    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5147    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5148 [(set_attr "conds" "use")
5149  (set_attr "length" "4,8,8")])
5151 (define_insn "*ifcompare_move_neg"
5152   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5153         (if_then_else:SI
5154          (match_operator 5 "comparison_operator"
5155           [(match_operand:SI 3 "s_register_operand" "r,r")
5156            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5157          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5158          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5159    (clobber (reg:CC 24))]
5160   ""
5161   "#"
5162 [(set_attr "conds" "clob")
5163  (set_attr "length" "8,12")])
5165 (define_insn "*if_move_neg"
5166   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5167         (if_then_else:SI
5168          (match_operator 4 "comparison_operator"
5169           [(match_operand 3 "cc_register" "") (const_int 0)])
5170          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5171          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5172   ""
5173   "@
5174    rsb%D4\\t%0, %2, #0
5175    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5176    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5177 [(set_attr "conds" "use")
5178  (set_attr "length" "4,8,8")])
5180 (define_insn "*arith_adjacentmem"
5181   [(set (match_operand:SI 0 "s_register_operand" "=r")
5182         (match_operator:SI 1 "shiftable_operator"
5183          [(match_operand:SI 2 "memory_operand" "m")
5184           (match_operand:SI 3 "memory_operand" "m")]))
5185    (clobber (match_scratch:SI 4 "=r"))]
5186   "adjacent_mem_locations (operands[2], operands[3])"
5187   "*
5189   rtx ldm[3];
5190   rtx arith[4];
5191   int val1 = 0, val2 = 0;
5193   if (REGNO (operands[0]) > REGNO (operands[4]))
5194     {
5195       ldm[1] = operands[4];
5196       ldm[2] = operands[0];
5197     }
5198   else
5199     {
5200       ldm[1] = operands[0];
5201       ldm[2] = operands[4];
5202     }
5203   if (GET_CODE (XEXP (operands[2], 0)) != REG)
5204     val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5205   if (GET_CODE (XEXP (operands[3], 0)) != REG)
5206     val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5207   arith[0] = operands[0];
5208   arith[3] = operands[1];
5209   if (val1 < val2)
5210     {
5211       arith[1] = ldm[1];
5212       arith[2] = ldm[2];
5213     }
5214   else
5215     {
5216       arith[1] = ldm[2];
5217       arith[2] = ldm[1];
5218     }
5219   if (val1 && val2)
5220     {
5221       rtx ops[3];
5222       ldm[0] = ops[0] = operands[4];
5223       ops[1] = XEXP (XEXP (operands[2], 0), 0);
5224       ops[2] = XEXP (XEXP (operands[2], 0), 1);
5225       output_add_immediate (ops);
5226       if (val1 < val2)
5227         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5228       else
5229         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5230     }
5231   else if (val1)
5232     {
5233       ldm[0] = XEXP (operands[3], 0);
5234       if (val1 < val2)
5235         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5236       else
5237         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5238     }
5239   else
5240     {
5241       ldm[0] = XEXP (operands[2], 0);
5242       if (val1 < val2)
5243         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5244       else
5245         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5246     }
5247   output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5248   return \"\";
5251 [(set_attr "length" "12")
5252  (set_attr "type" "load")])
5254 ;; the arm can support extended pre-inc instructions
5256 ;; In all these cases, we use operands 0 and 1 for the register being
5257 ;; incremented because those are the operands that local-alloc will
5258 ;; tie and these are the pair most likely to be tieable (and the ones
5259 ;; that will benefit the most).
5261 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5262 ;; elimination will cause too many headaches.
5264 (define_insn "*strqi_preinc"
5265   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5266                          (match_operand:SI 2 "index_operand" "rJ")))
5267         (match_operand:QI 3 "s_register_operand" "r"))
5268    (set (match_operand:SI 0 "s_register_operand" "=r")
5269         (plus:SI (match_dup 1) (match_dup 2)))]
5270   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5271    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5272    && (GET_CODE (operands[2]) != REG
5273        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5274   "str%?b\\t%3, [%0, %2]!"
5275 [(set_attr "type" "store1")])
5277 (define_insn "*strqi_predec"
5278   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5279                           (match_operand:SI 2 "s_register_operand" "r")))
5280         (match_operand:QI 3 "s_register_operand" "r"))
5281    (set (match_operand:SI 0 "s_register_operand" "=r")
5282         (minus:SI (match_dup 1) (match_dup 2)))]
5283   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5284    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5285    && (GET_CODE (operands[2]) != REG
5286        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5287   "str%?b\\t%3, [%0, -%2]!"
5288 [(set_attr "type" "store1")])
5290 (define_insn "*loadqi_preinc"
5291   [(set (match_operand:QI 3 "s_register_operand" "=r")
5292         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5293                          (match_operand:SI 2 "index_operand" "rJ"))))
5294    (set (match_operand:SI 0 "s_register_operand" "=r")
5295         (plus:SI (match_dup 1) (match_dup 2)))]
5296   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5297    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5298    && (GET_CODE (operands[2]) != REG
5299        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5300   "ldr%?b\\t%3, [%0, %2]!"
5301 [(set_attr "type" "load")])
5303 (define_insn "*loadqi_predec"
5304   [(set (match_operand:QI 3 "s_register_operand" "=r")
5305         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5306                           (match_operand:SI 2 "s_register_operand" "r"))))
5307    (set (match_operand:SI 0 "s_register_operand" "=r")
5308         (minus:SI (match_dup 1) (match_dup 2)))]
5309   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5310    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5311    && (GET_CODE (operands[2]) != REG
5312        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5313   "ldr%?b\\t%3, [%0, -%2]!"
5314 [(set_attr "type" "load")])
5316 (define_insn "*loadqisi_preinc"
5317   [(set (match_operand:SI 3 "s_register_operand" "=r")
5318         (zero_extend:SI
5319          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5320                           (match_operand:SI 2 "index_operand" "rJ")))))
5321    (set (match_operand:SI 0 "s_register_operand" "=r")
5322         (plus:SI (match_dup 1) (match_dup 2)))]
5323   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5324    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5325    && (GET_CODE (operands[2]) != REG
5326        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5327   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5328 [(set_attr "type" "load")])
5330 (define_insn "*loadqisi_predec"
5331   [(set (match_operand:SI 3 "s_register_operand" "=r")
5332         (zero_extend:SI
5333          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5334                            (match_operand:SI 2 "s_register_operand" "r")))))
5335    (set (match_operand:SI 0 "s_register_operand" "=r")
5336         (minus:SI (match_dup 1) (match_dup 2)))]
5337   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5338    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5339    && (GET_CODE (operands[2]) != REG
5340        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5341   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5342 [(set_attr "type" "load")])
5344 (define_insn "*strsi_preinc"
5345   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5346                          (match_operand:SI 2 "index_operand" "rJ")))
5347         (match_operand:SI 3 "s_register_operand" "r"))
5348    (set (match_operand:SI 0 "s_register_operand" "=r")
5349         (plus:SI (match_dup 1) (match_dup 2)))]
5350   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5351    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5352    && (GET_CODE (operands[2]) != REG
5353        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5354   "str%?\\t%3, [%0, %2]!"
5355 [(set_attr "type" "store1")])
5357 (define_insn "*strqi_predec"
5358   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5359                           (match_operand:SI 2 "s_register_operand" "r")))
5360         (match_operand:SI 3 "s_register_operand" "r"))
5361    (set (match_operand:SI 0 "s_register_operand" "=r")
5362         (minus:SI (match_dup 1) (match_dup 2)))]
5363   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5364    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5365    && (GET_CODE (operands[2]) != REG
5366        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5367   "str%?\\t%3, [%0, -%2]!"
5368 [(set_attr "type" "store1")])
5370 (define_insn "*loadsi_preinc"
5371   [(set (match_operand:SI 3 "s_register_operand" "=r")
5372         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5373                          (match_operand:SI 2 "index_operand" "rJ"))))
5374    (set (match_operand:SI 0 "s_register_operand" "=r")
5375         (plus:SI (match_dup 1) (match_dup 2)))]
5376   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5377    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5378    && (GET_CODE (operands[2]) != REG
5379        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5380   "ldr%?\\t%3, [%0, %2]!"
5381 [(set_attr "type" "load")])
5383 (define_insn "*loadsi_predec"
5384   [(set (match_operand:SI 3 "s_register_operand" "=r")
5385         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5386                           (match_operand:SI 2 "s_register_operand" "r"))))
5387    (set (match_operand:SI 0 "s_register_operand" "=r")
5388         (minus:SI (match_dup 1) (match_dup 2)))]
5389   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5390    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5391    && (GET_CODE (operands[2]) != REG
5392        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5393   "ldr%?\\t%3, [%0, -%2]!"
5394 [(set_attr "type" "load")])
5396 (define_insn "*loadhi_preinc"
5397   [(set (match_operand:HI 3 "s_register_operand" "=r")
5398         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5399                          (match_operand:SI 2 "index_operand" "rJ"))))
5400    (set (match_operand:SI 0 "s_register_operand" "=r")
5401         (plus:SI (match_dup 1) (match_dup 2)))]
5402   "(! BYTES_BIG_ENDIAN)
5403    && ! TARGET_SHORT_BY_BYTES
5404    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5405    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5406    && (GET_CODE (operands[2]) != REG
5407        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5408   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5409 [(set_attr "type" "load")])
5411 (define_insn "*loadhi_predec"
5412   [(set (match_operand:HI 3 "s_register_operand" "=r")
5413         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5414                           (match_operand:SI 2 "s_register_operand" "r"))))
5415    (set (match_operand:SI 0 "s_register_operand" "=r")
5416         (minus:SI (match_dup 1) (match_dup 2)))]
5417   "(!BYTES_BIG_ENDIAN)
5418    && ! TARGET_SHORT_BY_BYTES
5419    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5420    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5421    && (GET_CODE (operands[2]) != REG
5422        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5423   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5424 [(set_attr "type" "load")])
5426 (define_insn "*strqi_shiftpreinc"
5427   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5428                           [(match_operand:SI 3 "s_register_operand" "r")
5429                            (match_operand:SI 4 "const_shift_operand" "n")])
5430                          (match_operand:SI 1 "s_register_operand" "0")))
5431         (match_operand:QI 5 "s_register_operand" "r"))
5432    (set (match_operand:SI 0 "s_register_operand" "=r")
5433         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5434                  (match_dup 1)))]
5435   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5436    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5437    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5438   "str%?b\\t%5, [%0, %3%S2]!"
5439 [(set_attr "type" "store1")])
5441 (define_insn "*strqi_shiftpredec"
5442   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5443                           (match_operator:SI 2 "shift_operator"
5444                            [(match_operand:SI 3 "s_register_operand" "r")
5445                             (match_operand:SI 4 "const_shift_operand" "n")])))
5446         (match_operand:QI 5 "s_register_operand" "r"))
5447    (set (match_operand:SI 0 "s_register_operand" "=r")
5448         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5449                                                  (match_dup 4)])))]
5450   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5451    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5452    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5453   "str%?b\\t%5, [%0, -%3%S2]!"
5454 [(set_attr "type" "store1")])
5456 (define_insn "*loadqi_shiftpreinc"
5457   [(set (match_operand:QI 5 "s_register_operand" "=r")
5458         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5459                           [(match_operand:SI 3 "s_register_operand" "r")
5460                            (match_operand:SI 4 "const_shift_operand" "n")])
5461                          (match_operand:SI 1 "s_register_operand" "0"))))
5462    (set (match_operand:SI 0 "s_register_operand" "=r")
5463         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5464                  (match_dup 1)))]
5465   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5466    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5467    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5468   "ldr%?b\\t%5, [%0, %3%S2]!"
5469 [(set_attr "type" "load")])
5471 (define_insn "*loadqi_shiftpredec"
5472   [(set (match_operand:QI 5 "s_register_operand" "=r")
5473         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5474                           (match_operator:SI 2 "shift_operator"
5475                            [(match_operand:SI 3 "s_register_operand" "r")
5476                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5477    (set (match_operand:SI 0 "s_register_operand" "=r")
5478         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5479                                                  (match_dup 4)])))]
5480   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5481    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5482    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5483   "ldr%?b\\t%5, [%0, -%3%S2]!"
5484 [(set_attr "type" "load")])
5486 (define_insn "*strsi_shiftpreinc"
5487   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5488                           [(match_operand:SI 3 "s_register_operand" "r")
5489                            (match_operand:SI 4 "const_shift_operand" "n")])
5490                          (match_operand:SI 1 "s_register_operand" "0")))
5491         (match_operand:SI 5 "s_register_operand" "r"))
5492    (set (match_operand:SI 0 "s_register_operand" "=r")
5493         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5494                  (match_dup 1)))]
5495   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5496    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5497    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5498   "str%?\\t%5, [%0, %3%S2]!"
5499 [(set_attr "type" "store1")])
5501 (define_insn "*strsi_shiftpredec"
5502   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5503                           (match_operator:SI 2 "shift_operator"
5504                            [(match_operand:SI 3 "s_register_operand" "r")
5505                             (match_operand:SI 4 "const_shift_operand" "n")])))
5506         (match_operand:SI 5 "s_register_operand" "r"))
5507    (set (match_operand:SI 0 "s_register_operand" "=r")
5508         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5509                                                  (match_dup 4)])))]
5510   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5511    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5512    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5513   "str%?\\t%5, [%0, -%3%S2]!"
5514 [(set_attr "type" "store1")])
5516 (define_insn "*loadqi_shiftpreinc"
5517   [(set (match_operand:SI 5 "s_register_operand" "=r")
5518         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5519                           [(match_operand:SI 3 "s_register_operand" "r")
5520                            (match_operand:SI 4 "const_shift_operand" "n")])
5521                          (match_operand:SI 1 "s_register_operand" "0"))))
5522    (set (match_operand:SI 0 "s_register_operand" "=r")
5523         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5524                  (match_dup 1)))]
5525   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5526    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5527    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5528   "ldr%?\\t%5, [%0, %3%S2]!"
5529 [(set_attr "type" "load")])
5531 (define_insn "*loadqi_shiftpredec"
5532   [(set (match_operand:SI 5 "s_register_operand" "=r")
5533         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5534                           (match_operator:SI 2 "shift_operator"
5535                            [(match_operand:SI 3 "s_register_operand" "r")
5536                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5537    (set (match_operand:SI 0 "s_register_operand" "=r")
5538         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5539                                                  (match_dup 4)])))]
5540   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5541    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5542    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5543   "ldr%?\\t%5, [%0, -%3%S2]!"
5544 [(set_attr "type" "load")])
5546 (define_insn "*loadhi_shiftpreinc"
5547   [(set (match_operand:HI 5 "s_register_operand" "=r")
5548         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5549                           [(match_operand:SI 3 "s_register_operand" "r")
5550                            (match_operand:SI 4 "const_shift_operand" "n")])
5551                          (match_operand:SI 1 "s_register_operand" "0"))))
5552    (set (match_operand:SI 0 "s_register_operand" "=r")
5553         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5554                  (match_dup 1)))]
5555   "(! BYTES_BIG_ENDIAN)
5556    && ! TARGET_SHORT_BY_BYTES
5557    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5558    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5559    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5560   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5561 [(set_attr "type" "load")])
5563 (define_insn "*loadhi_shiftpredec"
5564   [(set (match_operand:HI 5 "s_register_operand" "=r")
5565         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5566                           (match_operator:SI 2 "shift_operator"
5567                            [(match_operand:SI 3 "s_register_operand" "r")
5568                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5569    (set (match_operand:SI 0 "s_register_operand" "=r")
5570         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5571                                                  (match_dup 4)])))]
5572   "(! BYTES_BIG_ENDIAN)
5573    && ! TARGET_SHORT_BY_BYTES
5574    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5575    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5576    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5577   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5578 [(set_attr "type" "load")])
5580 ; It can also support extended post-inc expressions, but combine doesn't
5581 ; try these....
5582 ; It doesn't seem worth adding peepholes for anything but the most common
5583 ; cases since, unlike combine, the increment must immediately follow the load
5584 ; for this pattern to match.
5585 ; When loading we must watch to see that the base register isn't trampled by
5586 ; the load.  In such cases this isn't a post-inc expression.
5588 (define_peephole
5589   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5590         (match_operand:QI 2 "s_register_operand" "r"))
5591    (set (match_dup 0)
5592         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5593   ""
5594   "str%?b\\t%2, [%0], %1")
5596 (define_peephole
5597   [(set (match_operand:QI 0 "s_register_operand" "=r")
5598         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5599    (set (match_dup 1)
5600         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5601   "REGNO(operands[0]) != REGNO(operands[1])
5602    && (GET_CODE (operands[2]) != REG
5603        || REGNO(operands[0]) != REGNO (operands[2]))"
5604   "ldr%?b\\t%0, [%1], %2")
5606 (define_peephole
5607   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5608         (match_operand:SI 2 "s_register_operand" "r"))
5609    (set (match_dup 0)
5610         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5611   ""
5612   "str%?\\t%2, [%0], %1")
5614 (define_peephole
5615   [(set (match_operand:HI 0 "s_register_operand" "=r")
5616         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5617    (set (match_dup 1)
5618         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5619   "(! BYTES_BIG_ENDIAN)
5620    && ! TARGET_SHORT_BY_BYTES
5621    && REGNO(operands[0]) != REGNO(operands[1])
5622    && (GET_CODE (operands[2]) != REG
5623        || REGNO(operands[0]) != REGNO (operands[2]))"
5624   "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5626 (define_peephole
5627   [(set (match_operand:SI 0 "s_register_operand" "=r")
5628         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5629    (set (match_dup 1)
5630         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5631   "REGNO(operands[0]) != REGNO(operands[1])
5632    && (GET_CODE (operands[2]) != REG
5633        || REGNO(operands[0]) != REGNO (operands[2]))"
5634   "ldr%?\\t%0, [%1], %2")
5636 (define_peephole
5637   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5638                          (match_operand:SI 1 "index_operand" "rJ")))
5639         (match_operand:QI 2 "s_register_operand" "r"))
5640    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5641   ""
5642   "str%?b\\t%2, [%0, %1]!")
5644 (define_peephole
5645   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5646                           [(match_operand:SI 0 "s_register_operand" "r")
5647                            (match_operand:SI 1 "const_int_operand" "n")])
5648                          (match_operand:SI 2 "s_register_operand" "+r")))
5649         (match_operand:QI 3 "s_register_operand" "r"))
5650    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5651                                (match_dup 2)))]
5652   ""
5653   "str%?b\\t%3, [%2, %0%S4]!")
5655 ; This pattern is never tried by combine, so do it as a peephole
5657 (define_peephole
5658   [(set (match_operand:SI 0 "s_register_operand" "=r")
5659         (match_operand:SI 1 "s_register_operand" "r"))
5660    (set (reg:CC 24)
5661         (compare:CC (match_dup 1) (const_int 0)))]
5662   ""
5663   "sub%?s\\t%0, %1, #0"
5664 [(set_attr "conds" "set")])
5666 ; Peepholes to spot possible load- and store-multiples, if the ordering is
5667 ; reversed, check that the memory references aren't volatile.
5669 (define_peephole
5670   [(set (match_operand:SI 0 "s_register_operand" "=r")
5671         (match_operand:SI 4 "memory_operand" "m"))
5672    (set (match_operand:SI 1 "s_register_operand" "=r")
5673         (match_operand:SI 5 "memory_operand" "m"))
5674    (set (match_operand:SI 2 "s_register_operand" "=r")
5675         (match_operand:SI 6 "memory_operand" "m"))
5676    (set (match_operand:SI 3 "s_register_operand" "=r")
5677         (match_operand:SI 7 "memory_operand" "m"))]
5678   "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5679   "*
5680   return emit_ldm_seq (operands, 4);
5683 (define_peephole
5684   [(set (match_operand:SI 0 "s_register_operand" "=r")
5685         (match_operand:SI 3 "memory_operand" "m"))
5686    (set (match_operand:SI 1 "s_register_operand" "=r")
5687         (match_operand:SI 4 "memory_operand" "m"))
5688    (set (match_operand:SI 2 "s_register_operand" "=r")
5689         (match_operand:SI 5 "memory_operand" "m"))]
5690   "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5691   "*
5692   return emit_ldm_seq (operands, 3);
5695 (define_peephole
5696   [(set (match_operand:SI 0 "s_register_operand" "=r")
5697         (match_operand:SI 2 "memory_operand" "m"))
5698    (set (match_operand:SI 1 "s_register_operand" "=r")
5699         (match_operand:SI 3 "memory_operand" "m"))]
5700   "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5701   "*
5702   return emit_ldm_seq (operands, 2);
5705 (define_peephole
5706   [(set (match_operand:SI 4 "memory_operand" "=m")
5707         (match_operand:SI 0 "s_register_operand" "r"))
5708    (set (match_operand:SI 5 "memory_operand" "=m")
5709         (match_operand:SI 1 "s_register_operand" "r"))
5710    (set (match_operand:SI 6 "memory_operand" "=m")
5711         (match_operand:SI 2 "s_register_operand" "r"))
5712    (set (match_operand:SI 7 "memory_operand" "=m")
5713         (match_operand:SI 3 "s_register_operand" "r"))]
5714   "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5715   "*
5716   return emit_stm_seq (operands, 4);
5719 (define_peephole
5720   [(set (match_operand:SI 3 "memory_operand" "=m")
5721         (match_operand:SI 0 "s_register_operand" "r"))
5722    (set (match_operand:SI 4 "memory_operand" "=m")
5723         (match_operand:SI 1 "s_register_operand" "r"))
5724    (set (match_operand:SI 5 "memory_operand" "=m")
5725         (match_operand:SI 2 "s_register_operand" "r"))]
5726   "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5727   "*
5728   return emit_stm_seq (operands, 3);
5731 (define_peephole
5732   [(set (match_operand:SI 2 "memory_operand" "=m")
5733         (match_operand:SI 0 "s_register_operand" "r"))
5734    (set (match_operand:SI 3 "memory_operand" "=m")
5735         (match_operand:SI 1 "s_register_operand" "r"))]
5736   "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5737   "*
5738   return emit_stm_seq (operands, 2);
5741 ;; A call followed by return can be replaced by restoring the regs and
5742 ;; jumping to the subroutine, provided we aren't passing the address of
5743 ;; any of our local variables.  If we call alloca then this is unsafe
5744 ;; since restoring the frame frees the memory, which is not what we want.
5745 ;; Sometimes the return might have been targeted by the final prescan:
5746 ;; if so then emit a proper return insn as well.
5747 ;; Unfortunately, if the frame pointer is required, we don't know if the
5748 ;; current function has any implicit stack pointer adjustments that will 
5749 ;; be restored by the return: we can't therefore do a tail call.
5750 ;; Another unfortunate that we can't handle is if current_function_args_size
5751 ;; is non-zero: in this case elimination of the argument pointer assumed
5752 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5753 ;; calculations.
5755 (define_peephole
5756   [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5757                           (match_operand:SI 1 "general_operand" "g"))
5758                     (clobber (reg:SI 14))])
5759    (return)]
5760   "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN
5761     && !get_frame_size () && !current_function_calls_alloca
5762     && !frame_pointer_needed && !current_function_args_size)"
5763   "*
5765   extern rtx arm_target_insn;
5766   extern int arm_ccfsm_state;
5768   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5769   {
5770     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5771     output_return_instruction (NULL, TRUE, FALSE);
5772     arm_ccfsm_state = 0;
5773     arm_target_insn = NULL;
5774   }
5776   output_return_instruction (NULL, FALSE, FALSE);
5777   return \"b%?\\t%a0\";
5779 [(set_attr "type" "call")
5780  (set_attr "length" "8")])
5782 (define_peephole
5783   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5784                    (call (mem:SI (match_operand:SI 1 "" "X"))
5785                          (match_operand:SI 2 "general_operand" "g")))
5786               (clobber (reg:SI 14))])
5787    (return)]
5788   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5789     && !get_frame_size () && !current_function_calls_alloca
5790     && !frame_pointer_needed && !current_function_args_size)"
5791   "*
5793   extern rtx arm_target_insn;
5794   extern int arm_ccfsm_state;
5796   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5797   {
5798     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5799     output_return_instruction (NULL, TRUE, FALSE);
5800     arm_ccfsm_state = 0;
5801     arm_target_insn = NULL;
5802   }
5804   output_return_instruction (NULL, FALSE, FALSE);
5805   return \"b%?\\t%a1\";
5807 [(set_attr "type" "call")
5808  (set_attr "length" "8")])
5810 ;; As above but when this function is not void, we must be returning the
5811 ;; result of the called subroutine.
5813 (define_peephole
5814   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5815                    (call (mem:SI (match_operand:SI 1 "" "X"))
5816                          (match_operand:SI 2 "general_operand" "g")))
5817               (clobber (reg:SI 14))])
5818    (use (match_dup 0))
5819    (return)]
5820   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5821     && !get_frame_size () && !current_function_calls_alloca
5822     && !frame_pointer_needed && !current_function_args_size)"
5823   "*
5825   extern rtx arm_target_insn;
5826   extern int arm_ccfsm_state;
5828   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5829   {
5830     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5831     output_return_instruction (NULL, TRUE, FALSE);
5832     arm_ccfsm_state = 0;
5833     arm_target_insn = NULL;
5834   }
5836   output_return_instruction (NULL, FALSE, FALSE);
5837   return \"b%?\\t%a1\";
5839 [(set_attr "type" "call")
5840  (set_attr "length" "8")])
5842 (define_split
5843   [(set (match_operand:SI 0 "s_register_operand" "")
5844         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
5845                        (const_int 0))
5846                 (neg:SI (match_operator:SI 2 "comparison_operator"
5847                          [(match_operand:SI 3 "s_register_operand" "")
5848                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
5849    (clobber (match_operand:SI 5 "s_register_operand" ""))]
5850   ""
5851   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
5852    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5853                               (match_dup 5)))]
5854   "")
5856 ;; This split can be used because CC_Z mode implies that the following
5857 ;; branch will be an equality, or an unsigned inequality, so the sign
5858 ;; extension is not needed.
5860 (define_split
5861   [(set (reg:CC_Z 24)
5862         (compare:CC_Z
5863          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
5864                     (const_int 24))
5865          (match_operand 1 "const_int_operand" "")))
5866    (clobber (match_scratch:SI 2 ""))]
5867   "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
5868    == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
5869   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
5870    (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
5871   "
5872   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
5875 (define_expand "prologue"
5876   [(clobber (const_int 0))]
5877   ""
5878   "
5879   arm_expand_prologue ();
5880   DONE;
5883 ;; This split is only used during output to reduce the number of patterns
5884 ;; that need assembler instructions adding to them.  We allowed the setting
5885 ;; of the conditions to be implicit during rtl generation so that
5886 ;; the conditional compare patterns would work.  However this conflicts to
5887 ;; some extent with the conditional data operations, so we have to split them
5888 ;; up again here.
5890 (define_split
5891   [(set (match_operand:SI 0 "s_register_operand" "")
5892         (if_then_else:SI (match_operator 1 "comparison_operator"
5893                           [(match_operand 2 "" "") (match_operand 3 "" "")])
5894                          (match_operand 4 "" "")
5895                          (match_operand 5 "" "")))
5896    (clobber (reg 24))]
5897   "reload_completed"
5898   [(set (match_dup 6) (match_dup 7))
5899    (set (match_dup 0) 
5900         (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
5901                          (match_dup 4)
5902                          (match_dup 5)))]
5903   "
5905   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
5906                                            operands[3]);
5908   operands[6] = gen_rtx (REG, mode, 24);
5909   operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
5914 ;; The next two patterns occur when an AND operation is followed by a
5915 ;; scc insn sequence 
5917 (define_insn "*sign_extract_onebit"
5918   [(set (match_operand:SI 0 "s_register_operand" "=r")
5919         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5920                          (const_int 1)
5921                          (match_operand:SI 2 "const_int_operand" "n")))]
5922   ""
5923   "*
5924   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5925   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
5926   return \"mvnne\\t%0, #0\";
5928 [(set_attr "conds" "clob")
5929  (set_attr "length" "8")])
5931 (define_insn "*not_signextract_onebit"
5932   [(set (match_operand:SI 0 "s_register_operand" "=r")
5933         (not:SI
5934          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5935                           (const_int 1)
5936                           (match_operand:SI 2 "const_int_operand" "n"))))]
5937   ""
5938   "*
5939   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5940   output_asm_insn (\"tst\\t%1, %2\", operands);
5941   output_asm_insn (\"mvneq\\t%0, #0\", operands);
5942   return \"movne\\t%0, #0\";
5944 [(set_attr "conds" "clob")
5945  (set_attr "length" "12")])
5947 ;; Push multiple registers to the stack.  The first register is in the
5948 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
5949 ;; expressions.
5950 (define_insn "*push_multi"
5951   [(match_parallel 2 "multi_register_push"
5952     [(set (match_operand:BLK 0 "memory_operand" "=m")
5953           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
5954   ""
5955   "*
5957   char pattern[100];
5958   int i;
5959   extern int lr_save_eliminated;
5961   if (lr_save_eliminated)
5962     {
5963       if (XVECLEN (operands[2], 0) > 1)
5964         abort ();
5965       return \"\";
5966     }
5967   strcpy (pattern, \"stmfd\\t%m0!, {%1\");
5968   for (i = 1; i < XVECLEN (operands[2], 0); i++)
5969     {
5970       strcat (pattern, \", %|\");
5971       strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
5972                                               0))]);
5973     }
5974   strcat (pattern, \"}\");
5975   output_asm_insn (pattern, operands);
5976   return \"\";
5978 [(set_attr "type" "store4")])
5980 ;; Special patterns for dealing with the constant pool
5982 (define_insn "consttable_4"
5983   [(unspec_volatile [(match_operand 0 "" "")] 2)]
5984   ""
5985   "*
5987   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
5988     {
5989     case MODE_FLOAT:
5990     {
5991       union real_extract u;
5992       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
5993       assemble_real (u.d, GET_MODE (operands[0]));
5994       break;
5995     }
5996     default:
5997       assemble_integer (operands[0], 4, 1);
5998       break;
5999     }
6000   return \"\";
6002 [(set_attr "length" "4")])
6004 (define_insn "consttable_8"
6005   [(unspec_volatile [(match_operand 0 "" "")] 3)]
6006   ""
6007   "*
6009   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6010     {
6011     case MODE_FLOAT:
6012     {
6013       union real_extract u;
6014       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6015       assemble_real (u.d, GET_MODE (operands[0]));
6016       break;
6017     }
6018     default:
6019       assemble_integer (operands[0], 8, 1);
6020       break;
6021     }
6022   return \"\";
6024 [(set_attr "length" "8")])
6026 (define_insn "consttable_end"
6027   [(unspec_volatile [(const_int 0)] 4)]
6028   ""
6029   "*
6030   /* Nothing to do (currently).  */
6031   return \"\";
6034 (define_insn "align_4"
6035   [(unspec_volatile [(const_int 0)] 5)]
6036   ""
6037   "*
6038   assemble_align (32);
6039   return \"\";