Delete target options -m2 -m3 & -m6.
[official-gcc.git] / gcc / config / arm / arm.md
blob41b612407d0d680ba27484c57413a9414c068fc8
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright (C) 1991, 93-98, 1999 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 (rearnsha@arm.com).
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 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
50 ; Floating Point Unit.  If we only have floating point emulation, then there
51 ; is no point in scheduling the floating point insns.  (Well, for best
52 ; performance we should try and group them together).
54 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
56 ; LENGTH of an instruction (in bytes)
57 (define_attr "length" "" (const_int 4))
59 ; An assembler sequence may clobber the condition codes without us knowing
60 (define_asm_attributes
61  [(set_attr "conds" "clob")
62   (set_attr "length" "4")])
64 ; TYPE attribute is used to detect floating point instructions which, if
65 ; running on a co-processor can run in parallel with other, basic instructions
66 ; If write-buffer scheduling is enabled then it can also be used in the
67 ; scheduling of writes.
69 ; Classification of each insn
70 ; normal        any data instruction that doesn't hit memory or fp regs
71 ; mult          a multiply instruction
72 ; block         blockage insn, this blocks all functional units
73 ; float         a floating point arithmetic operation (subject to expansion)
74 ; fdivx         XFmode floating point division
75 ; fdivd         DFmode floating point division
76 ; fdivs         SFmode floating point division
77 ; fmul          Floating point multiply
78 ; ffmul         Fast floating point multiply
79 ; farith        Floating point arithmetic (4 cycle)
80 ; ffarith       Fast floating point arithmetic (2 cycle)
81 ; float_em      a floating point arithmetic operation that is normally emulated
82 ;               even on a machine with an fpa.
83 ; f_load        a floating point load from memory
84 ; f_store       a floating point store to memory
85 ; f_mem_r       a transfer of a floating point register to a real reg via mem
86 ; r_mem_f       the reverse of f_mem_r
87 ; f_2_r         fast transfer float to arm (no memory needed)
88 ; r_2_f         fast transfer arm to float
89 ; call          a subroutine call
90 ; load          any load from memory
91 ; store1        store 1 word to memory from arm registers
92 ; store2        store 2 words
93 ; store3        store 3 words
94 ; store4        store 4 words
96 (define_attr "type"
97         "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" 
98         (const_string "normal"))
100 ; Load scheduling, set from the arm_ld_sched variable
101 ; initialised by arm_override_options() 
102 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
104 ; condition codes: this one is used by final_prescan_insn to speed up
105 ; conditionalizing instructions.  It saves having to scan the rtl to see if
106 ; it uses or alters the condition codes.
108 ; USE means that the condition codes are used by the insn in the process of
109 ; outputting code, this means (at present) that we can't use the insn in
110 ; inlined branches
112 ; SET means that the purpose of the insn is to set the condition codes in a
113 ; well defined manner.
115 ; CLOB means that the condition codes are altered in an undefined manner, if
116 ; they are altered at all
118 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
119 ; but are if the branch wasn't taken; the effect is to limit the branch
120 ; elimination scanning.
122 ; NOCOND means that the condition codes are neither altered nor affect the
123 ; output of this insn
125 (define_attr "conds" "use,set,clob,jump_clob,nocond"
126         (if_then_else (eq_attr "type" "call")
127          (if_then_else (eq_attr "prog_mode" "prog32")
128           (const_string "clob") (const_string "nocond"))
129          (const_string "nocond")))
131 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
132 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
133 ; suffer blockages enough to warrent modelling this (and it can adversely
134 ; affect the schedule).
135 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
137 (define_attr "write_conflict" "no,yes"
138   (if_then_else (eq_attr "type"
139                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
140                 (const_string "yes")
141                 (const_string "no")))
143 (define_attr "core_cycles" "single,multi"
144   (if_then_else (eq_attr "type"
145                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
146                 (const_string "single")
147                 (const_string "multi")))
149 ; The write buffer on some of the arm6 processors is hard to model exactly.
150 ; There is room in the buffer for up to two addresses and up to eight words
151 ; of memory, but the two needn't be split evenly.  When writing the two
152 ; addresses are fully pipelined.  However, a read from memory that is not
153 ; currently in the cache will block until the writes have completed.
154 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
155 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
156 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
157 ; cycle to add as well.
159 ;; (define_function_unit {name} {num-units} {n-users} {test}
160 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
161 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
162                                      (eq_attr "type" "fdivx")) 71 69)
164 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
165                                      (eq_attr "type" "fdivd")) 59 57)
167 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
168                                      (eq_attr "type" "fdivs")) 31 29)
170 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
171                                      (eq_attr "type" "fmul")) 9 7)
173 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
174                                      (eq_attr "type" "ffmul")) 6 4)
176 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
177                                      (eq_attr "type" "farith")) 4 2)
179 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
180                                      (eq_attr "type" "ffarith")) 2 2)
182 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
183                                      (eq_attr "type" "r_2_f")) 5 3)
185 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
186                                      (eq_attr "type" "f_2_r")) 1 2)
188 ;; The fpa10 doesn't really have a memory read unit, but it can start to
189 ;; speculatively execute the instruction in the pipeline, provided the data
190 ;; is already loaded, so pretend reads have a delay of 2 (and that the
191 ;; pipeline is infinite.
193 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
194                                          (eq_attr "type" "f_load")) 3 1)
196 ;;--------------------------------------------------------------------
197 ;; Write buffer
198 ;;--------------------------------------------------------------------
199 ;; Strictly we should model a 4-deep write buffer for ARM7xx based chips
200 (define_function_unit "write_buf" 1 2
201   (and (eq_attr "model_wbuf" "yes")
202        (eq_attr "type" "store1,r_mem_f")) 5 3)
203 (define_function_unit "write_buf" 1 2 
204   (and (eq_attr "model_wbuf" "yes")
205        (eq_attr "type" "store2")) 7 4)
206 (define_function_unit "write_buf" 1 2
207   (and (eq_attr "model_wbuf" "yes")
208        (eq_attr "type" "store3")) 9 5)
209 (define_function_unit "write_buf" 1 2
210   (and (eq_attr "model_wbuf" "yes")
211        (eq_attr "type" "store4")) 11 6)
213 ;;--------------------------------------------------------------------
214 ;; Write blockage unit
215 ;;--------------------------------------------------------------------
216 ;; The write_blockage unit models (partially), the fact that reads will stall
217 ;; until the write buffer empties.
218 ;; The f_mem_r and r_mem_f could also block, but they are to the stack,
219 ;; so we don't model them here
220 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
221                                                 (eq_attr "type" "store1")) 5 5
222         [(eq_attr "write_conflict" "yes")])
223 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
224                                                 (eq_attr "type" "store2")) 7 7
225         [(eq_attr "write_conflict" "yes")])
226 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
227                                                 (eq_attr "type" "store3")) 9 9
228         [(eq_attr "write_conflict" "yes")])
229 (define_function_unit "write_blockage" 1 0
230         (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
231         [(eq_attr "write_conflict" "yes")])
232 (define_function_unit "write_blockage" 1 0
233         (and (eq_attr "model_wbuf" "yes")
234              (eq_attr "write_conflict" "yes")) 1 1)
236 ;;--------------------------------------------------------------------
237 ;; Core unit
238 ;;--------------------------------------------------------------------
239 ;; Everything must spend at least one cycle in the core unit
240 (define_function_unit "core" 1 0
241   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
243 (define_function_unit "core" 1 0
244   (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
246 (define_function_unit "core" 1 0
247   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
249 (define_function_unit "core" 1 0
250   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
252 (define_function_unit "core" 1 0
253   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
255 (define_function_unit "core" 1 0
256   (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
258 (define_function_unit "core" 1 0
259   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
261 (define_function_unit "core" 1 0
262   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
264 (define_function_unit "core" 1 0
265   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
266        (eq_attr "type" "mult")) 4 4)
268 (define_function_unit "core" 1 0
269   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
270        (eq_attr "type" "mult")) 3 2)
272 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
274 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
276 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
278 ;; Note: For DImode insns, there is normally no reason why operands should
279 ;; not be in the same register, what we don't want is for something being
280 ;; written to partially overlap something that is an input.
282 ;; Addition insns.
284 (define_insn "adddi3"
285   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
286         (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
287                  (match_operand:DI 2 "s_register_operand" "r,0")))
288    (clobber (reg:CC 24))]
289   ""
290   "adds\\t%Q0, %Q1, %Q2\;adc\\t%R0, %R1, %R2"
291 [(set_attr "conds" "clob")
292  (set_attr "length" "8")])
294 (define_insn "*adddi_sesidi_di"
295   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
296         (plus:DI (sign_extend:DI
297                   (match_operand:SI 2 "s_register_operand" "r,r"))
298                  (match_operand:DI 1 "s_register_operand" "r,0")))
299    (clobber (reg:CC 24))]
300   ""
301   "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, %2, asr #31"
302 [(set_attr "conds" "clob")
303  (set_attr "length" "8")])
305 (define_insn "*adddi_zesidi_di"
306   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
307         (plus:DI (zero_extend:DI
308                   (match_operand:SI 2 "s_register_operand" "r,r"))
309                  (match_operand:DI 1 "s_register_operand" "r,0")))
310    (clobber (reg:CC 24))]
311   ""
312   "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, #0"
313 [(set_attr "conds" "clob")
314  (set_attr "length" "8")])
316 (define_expand "addsi3"
317   [(set (match_operand:SI 0 "s_register_operand" "")
318         (plus:SI (match_operand:SI 1 "s_register_operand" "")
319                  (match_operand:SI 2 "reg_or_int_operand" "")))]
320   ""
321   "
322   if (GET_CODE (operands[2]) == CONST_INT)
323     {
324       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
325                           operands[1],
326                           (reload_in_progress || reload_completed ? 0
327                            : preserve_subexpressions_p ()));
328       DONE;
329     }
332 (define_split
333   [(set (match_operand:SI 0 "s_register_operand" "")
334         (plus:SI (match_operand:SI 1 "s_register_operand" "")
335                  (match_operand:SI 2 "const_int_operand" "")))]
336   "! (const_ok_for_arm (INTVAL (operands[2]))
337       || const_ok_for_arm (-INTVAL (operands[2])))"
338   [(clobber (const_int 0))]
339   "
340   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
341                       operands[1], 0);
342   DONE;
345 (define_insn "*addsi3_insn"
346   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
347         (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
348                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
349   ""
350   "@
351    add%?\\t%0, %1, %2
352    sub%?\\t%0, %1, #%n2
353    #"
354 [(set_attr "length" "4,4,16")])
356 (define_insn "*addsi3_compare0"
357   [(set (reg:CC_NOOV 24)
358         (compare:CC_NOOV
359          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
360                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
361          (const_int 0)))
362    (set (match_operand:SI 0 "s_register_operand" "=r,r")
363         (plus:SI (match_dup 1) (match_dup 2)))]
364   ""
365   "@
366    add%?s\\t%0, %1, %2
367    sub%?s\\t%0, %1, #%n2"
368 [(set_attr "conds" "set")])
370 (define_insn "*addsi3_compare0_scratch"
371   [(set (reg:CC_NOOV 24)
372         (compare:CC_NOOV
373          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
374                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
375          (const_int 0)))]
376   ""
377   "@
378    cmn%?\\t%0, %1
379    cmp%?\\t%0, #%n1"
380 [(set_attr "conds" "set")])
382 ;; The next four insns work because they compare the result with one of
383 ;; the operands, and we know that the use of the condition code is
384 ;; either GEU or LTU, so we can use the carry flag from the addition
385 ;; instead of doing the compare a second time.
386 (define_insn "*addsi3_compare_op1"
387   [(set (reg:CC_C 24)
388         (compare:CC_C
389          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
390                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
391          (match_dup 1)))
392    (set (match_operand:SI 0 "s_register_operand" "=r,r")
393         (plus:SI (match_dup 1) (match_dup 2)))]
394   ""
395   "@
396    add%?s\\t%0, %1, %2
397    sub%?s\\t%0, %1, #%n2"
398 [(set_attr "conds" "set")])
400 (define_insn "*addsi3_compare_op2"
401   [(set (reg:CC_C 24)
402         (compare:CC_C
403          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
404                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
405          (match_dup 2)))
406    (set (match_operand:SI 0 "s_register_operand" "=r,r")
407         (plus:SI (match_dup 1) (match_dup 2)))]
408   ""
409   "@
410    add%?s\\t%0, %1, %2
411    sub%?s\\t%0, %1, #%n2"
412 [(set_attr "conds" "set")])
414 (define_insn "*compare_addsi2_op0"
415   [(set (reg:CC_C 24)
416         (compare:CC_C
417          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
418                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
419          (match_dup 0)))]
420   ""
421   "@
422    cmn%?\\t%0, %1
423    cmp%?\\t%0, #%n1"
424 [(set_attr "conds" "set")])
426 (define_insn "*compare_addsi2_op1"
427   [(set (reg:CC_C 24)
428         (compare:CC_C
429          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
430                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
431          (match_dup 1)))]
432   ""
433   "@
434    cmn%?\\t%0, %1
435    cmp%?\\t%0, #%n1"
436 [(set_attr "conds" "set")])
438 (define_insn "*addsi3_carryin"
439   [(set (match_operand:SI 0 "s_register_operand" "=r")
440         (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
441                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
442                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
443   ""
444   "adc%?\\t%0, %1, %2"
445 [(set_attr "conds" "use")])
447 (define_insn "*addsi3_carryin_alt1"
448   [(set (match_operand:SI 0 "s_register_operand" "=r")
449         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
450                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
451                  (ltu:SI (reg:CC_C 24) (const_int 0))))]
452   ""
453   "adc%?\\t%0, %1, %2"
454 [(set_attr "conds" "use")])
456 (define_insn "*addsi3_carryin_alt2"
457   [(set (match_operand:SI 0 "s_register_operand" "=r")
458         (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
459                           (match_operand:SI 1 "s_register_operand" "r"))
460                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
461   ""
462   "adc%?\\t%0, %1, %2"
463 [(set_attr "conds" "use")])
465 (define_insn "*addsi3_carryin_alt3"
466   [(set (match_operand:SI 0 "s_register_operand" "=r")
467         (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
468                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
469                  (match_operand:SI 1 "s_register_operand" "r")))]
470   ""
471   "adc%?\\t%0, %1, %2"
472 [(set_attr "conds" "use")])
474 (define_insn "incscc"
475   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
476         (plus:SI (match_operator:SI 2 "comparison_operator"
477                     [(match_operand 3 "cc_register" "") (const_int 0)])
478                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
479   ""
480   "@
481   add%d2\\t%0, %1, #1
482   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
483 [(set_attr "conds" "use")
484  (set_attr "length" "4,8")])
486 ; If a constant is too big to fit in a single instruction then the constant
487 ; will be pre-loaded into a register taking at least two insns, we might be
488 ; able to merge it with an add, but it depends on the exact value.
490 (define_split
491   [(set (match_operand:SI 0 "s_register_operand" "=r")
492         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
493                  (match_operand:SI 2 "const_int_operand" "n")))]
494   "!(const_ok_for_arm (INTVAL (operands[2]))
495      || const_ok_for_arm (-INTVAL (operands[2])))"
496   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
497    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
498   "
500   unsigned int val = (unsigned) INTVAL (operands[2]);
501   int i;
502   unsigned int temp;
504   /* this code is similar to the approach followed in movsi, but it must
505      generate exactly two insns */
507   for (i = 30; i >= 0; i -= 2)
508     {
509       if (val & (3 << i))
510         {
511           i -= 6;
512           if (i < 0) i = 0;
513           if (const_ok_for_arm (temp = (val & ~(255 << i))))
514             {
515               val &= 255 << i;
516               break;
517             }
518           /* we might be able to do this as (larger number - small number) */
519           temp = ((val >> i) & 255) + 1;
520           if (temp > 255 && i < 24)
521             {
522               i += 2;
523               temp = ((val >> i) & 255) + 1;
524             }
525           if (const_ok_for_arm ((temp << i) - val))
526             {
527               i = temp << i;
528               temp = (unsigned) - (int) (i - val);
529               val = i;
530               break;
531             }
532           FAIL;
533         }
534     }
535   /* if we got here, we have found a way of doing it in two instructions.
536      the two constants are in val and temp */
537   operands[2] = GEN_INT ((int)val);
538   operands[3] = GEN_INT ((int)temp);
542 (define_insn "addsf3"
543   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
544         (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
545                  (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
546   "TARGET_HARD_FLOAT"
547   "@
548    adf%?s\\t%0, %1, %2
549    suf%?s\\t%0, %1, #%N2"
550 [(set_attr "type" "farith")])
552 (define_insn "adddf3"
553   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
554         (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
555                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
556   "TARGET_HARD_FLOAT"
557   "@
558    adf%?d\\t%0, %1, %2
559    suf%?d\\t%0, %1, #%N2"
560 [(set_attr "type" "farith")])
562 (define_insn "*adddf_df_esfdf"
563   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
564         (plus:DF (float_extend:DF
565                   (match_operand:SF 1 "s_register_operand" "f,f"))
566                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
567   "TARGET_HARD_FLOAT"
568   "@
569    adf%?d\\t%0, %1, %2
570    suf%?d\\t%0, %1, #%N2"
571 [(set_attr "type" "farith")])
573 (define_insn "*adddf_df_esfdf"
574   [(set (match_operand:DF 0 "s_register_operand" "=f")
575         (plus:DF (match_operand:DF 1 "s_register_operand" "f")
576                  (float_extend:DF
577                   (match_operand:SF 2 "s_register_operand" "f"))))]
578   "TARGET_HARD_FLOAT"
579   "adf%?d\\t%0, %1, %2"
580 [(set_attr "type" "farith")])
582 (define_insn "*adddf_esfdf_esfdf"
583   [(set (match_operand:DF 0 "s_register_operand" "=f")
584         (plus:DF (float_extend:DF 
585                   (match_operand:SF 1 "s_register_operand" "f"))
586                  (float_extend:DF
587                   (match_operand:SF 2 "s_register_operand" "f"))))]
588   "TARGET_HARD_FLOAT"
589   "adf%?d\\t%0, %1, %2"
590 [(set_attr "type" "farith")])
592 (define_insn "addxf3"
593   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
594         (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
595                  (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
596   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
597   "@
598    adf%?e\\t%0, %1, %2
599    suf%?e\\t%0, %1, #%N2"
600 [(set_attr "type" "farith")])
602 (define_insn "subdi3"
603   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
604         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
605                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
606    (clobber (reg:CC 24))]
607   ""
608   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
609 [(set_attr "conds" "clob")
610  (set_attr "length" "8")])
612 (define_insn "*subdi_di_zesidi"
613   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
614         (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
615                   (zero_extend:DI
616                    (match_operand:SI 2 "s_register_operand" "r,r"))))
617    (clobber (reg:CC 24))]
618   ""
619   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
620 [(set_attr "conds" "clob")
621  (set_attr "length" "8")])
623 (define_insn "*subdi_di_sesidi"
624   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
625         (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
626                   (sign_extend:DI
627                    (match_operand:SI 2 "s_register_operand" "r,r"))))
628    (clobber (reg:CC 24))]
629   ""
630   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
631 [(set_attr "conds" "clob")
632  (set_attr "length" "8")])
634 (define_insn "*subdi_zesidi_di"
635   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
636         (minus:DI (zero_extend:DI
637                    (match_operand:SI 2 "s_register_operand" "r,r"))
638                   (match_operand:DI 1 "s_register_operand" "?r,0")))
639    (clobber (reg:CC 24))]
640   ""
641   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
642 [(set_attr "conds" "clob")
643  (set_attr "length" "8")])
645 (define_insn "*subdi_sesidi_di"
646   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
647         (minus:DI (sign_extend:DI
648                    (match_operand:SI 2 "s_register_operand" "r,r"))
649                   (match_operand:DI 1 "s_register_operand" "?r,0")))
650    (clobber (reg:CC 24))]
651   ""
652   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
653 [(set_attr "conds" "clob")
654  (set_attr "length" "8")])
656 (define_insn "*subdi_zesidi_zesidi"
657   [(set (match_operand:DI 0 "s_register_operand" "=r")
658         (minus:DI (zero_extend:DI
659                    (match_operand:SI 1 "s_register_operand" "r"))
660                   (zero_extend:DI
661                    (match_operand:SI 2 "s_register_operand" "r"))))
662    (clobber (reg:CC 24))]
663   ""
664   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
665 [(set_attr "conds" "clob")
666  (set_attr "length" "8")])
668 (define_expand "subsi3"
669   [(set (match_operand:SI 0 "s_register_operand" "")
670         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
671                   (match_operand:SI 2 "s_register_operand" "")))]
672   ""
673   "
674   if (GET_CODE (operands[1]) == CONST_INT)
675     {
676       arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
677                           operands[2],
678                           (reload_in_progress || reload_completed ? 0
679                            : preserve_subexpressions_p ()));
680       DONE;
681     }
684 (define_insn "*subsi3_insn"
685   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
686         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
687                   (match_operand:SI 2 "s_register_operand" "r,r")))]
688   ""
689   "@
690    rsb%?\\t%0, %2, %1
691    #"
692 [(set_attr "length" "4,16")])
694 (define_split
695   [(set (match_operand:SI 0 "s_register_operand" "")
696         (minus:SI (match_operand:SI 1 "const_int_operand" "")
697                   (match_operand:SI 2 "s_register_operand" "")))]
698   "! const_ok_for_arm (INTVAL (operands[1]))"
699   [(clobber (const_int 0))]
700   "
701   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
702                       operands[2], 0);
703   DONE;
706 (define_insn "*subsi3_compare0"
707   [(set (reg:CC_NOOV 24)
708         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
709                                  (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
710                          (const_int 0)))
711    (set (match_operand:SI 0 "s_register_operand" "=r,r")
712         (minus:SI (match_dup 1) (match_dup 2)))]
713   ""
714   "@
715    sub%?s\\t%0, %1, %2
716    rsb%?s\\t%0, %2, %1"
717 [(set_attr "conds" "set")])
719 (define_insn "decscc"
720   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
721         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
722                   (match_operator:SI 2 "comparison_operator"
723                    [(match_operand 3 "cc_register" "") (const_int 0)])))]
724   ""
725   "@
726   sub%d2\\t%0, %1, #1
727   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
728 [(set_attr "conds" "use")
729  (set_attr "length" "*,8")])
731 (define_insn "subsf3"
732   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
733         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
734                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
735   "TARGET_HARD_FLOAT"
736   "@
737    suf%?s\\t%0, %1, %2
738    rsf%?s\\t%0, %2, %1"
739 [(set_attr "type" "farith")])
741 (define_insn "subdf3"
742   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
743         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
744                   (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
745   "TARGET_HARD_FLOAT"
746   "@
747    suf%?d\\t%0, %1, %2
748    rsf%?d\\t%0, %2, %1"
749 [(set_attr "type" "farith")])
751 (define_insn "*subdf_esfdf_df"
752   [(set (match_operand:DF 0 "s_register_operand" "=f")
753         (minus:DF (float_extend:DF
754                    (match_operand:SF 1 "s_register_operand" "f"))
755                   (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
756   "TARGET_HARD_FLOAT"
757   "suf%?d\\t%0, %1, %2"
758 [(set_attr "type" "farith")])
760 (define_insn "*subdf_df_esfdf"
761   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
762         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
763                   (float_extend:DF
764                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
765   "TARGET_HARD_FLOAT"
766   "@
767    suf%?d\\t%0, %1, %2
768    rsf%?d\\t%0, %2, %1"
769 [(set_attr "type" "farith")])
771 (define_insn "*subdf_esfdf_esfdf"
772   [(set (match_operand:DF 0 "s_register_operand" "=f")
773         (minus:DF (float_extend:DF
774                    (match_operand:SF 1 "s_register_operand" "f"))
775                   (float_extend:DF
776                    (match_operand:SF 2 "s_register_operand" "f"))))]
777   "TARGET_HARD_FLOAT"
778   "suf%?d\\t%0, %1, %2"
779 [(set_attr "type" "farith")])
781 (define_insn "subxf3"
782   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
783         (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
784                   (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
785   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
786   "@
787    suf%?e\\t%0, %1, %2
788    rsf%?e\\t%0, %2, %1"
789 [(set_attr "type" "farith")])
791 ;; Multiplication insns
793 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
794 (define_insn "mulsi3"
795   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
796         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
797                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
798   ""
799   "mul%?\\t%0, %2, %1"
800 [(set_attr "type" "mult")])
802 (define_insn "*mulsi3_compare0"
803   [(set (reg:CC_NOOV 24)
804         (compare:CC_NOOV (mult:SI
805                           (match_operand:SI 2 "s_register_operand" "r,r")
806                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
807                          (const_int 0)))
808    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
809         (mult:SI (match_dup 2) (match_dup 1)))]
810   ""
811   "mul%?s\\t%0, %2, %1"
812 [(set_attr "conds" "set")
813  (set_attr "type" "mult")])
815 (define_insn "*mulsi_compare0_scratch"
816   [(set (reg:CC_NOOV 24)
817         (compare:CC_NOOV (mult:SI
818                           (match_operand:SI 2 "s_register_operand" "r,r")
819                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
820                          (const_int 0)))
821    (clobber (match_scratch:SI 0 "=&r,&r"))]
822   ""
823   "mul%?s\\t%0, %2, %1"
824 [(set_attr "conds" "set")
825  (set_attr "type" "mult")])
827 ;; Unnamed templates to match MLA instruction.
829 (define_insn "*mulsi3addsi"
830   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
831         (plus:SI
832           (mult:SI (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   ""
836   "mla%?\\t%0, %2, %1, %3"
837 [(set_attr "type" "mult")])
839 (define_insn "*mulsi3addsi_compare0"
840   [(set (reg:CC_NOOV 24)
841         (compare:CC_NOOV (plus:SI
842                           (mult:SI
843                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
844                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
845                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
846                          (const_int 0)))
847    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
848         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
849                  (match_dup 3)))]
850   ""
851   "mla%?s\\t%0, %2, %1, %3"
852 [(set_attr "conds" "set")
853  (set_attr "type" "mult")])
855 (define_insn "*mulsi3addsi_compare0_scratch"
856   [(set (reg:CC_NOOV 24)
857         (compare:CC_NOOV (plus:SI
858                           (mult:SI
859                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
860                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
861                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
862                          (const_int 0)))
863    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
864   ""
865   "mla%?s\\t%0, %2, %1, %3"
866 [(set_attr "conds" "set")
867  (set_attr "type" "mult")])
869 (define_insn "mulsidi3"
870   [(set (match_operand:DI 0 "s_register_operand" "=&r")
871       (mult:DI (sign_extend:DI
872                 (match_operand:SI 1 "s_register_operand" "%r"))
873                (sign_extend:DI
874                (match_operand:SI 2 "s_register_operand" "r"))))]
875   "arm_fast_multiply"
876   "smull%?\\t%Q0, %R0, %1, %2"
877 [(set_attr "type" "mult")])
879 (define_insn "umulsidi3"
880   [(set (match_operand:DI 0 "s_register_operand" "=&r")
881       (mult:DI (zero_extend:DI
882                 (match_operand:SI 1 "s_register_operand" "%r"))
883                (zero_extend:DI
884                 (match_operand:SI 2 "s_register_operand" "r"))))]
885   "arm_fast_multiply"
886   "umull%?\\t%Q0, %R0, %1, %2"
887 [(set_attr "type" "mult")])
889 (define_insn "smulsi3_highpart"
890   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
891         (truncate:SI
892          (lshiftrt:DI
893           (mult:DI (sign_extend:DI
894                     (match_operand:SI 1 "s_register_operand" "%r,0"))
895                    (sign_extend:DI
896                     (match_operand:SI 2 "s_register_operand" "r,r")))
897           (const_int 32))))
898    (clobber (match_scratch:SI 3 "=&r,&r"))]
899   "arm_fast_multiply"
900   "smull%?\\t%3, %0, %2, %1"
901 [(set_attr "type" "mult")])
903 (define_insn "umulsi3_highpart"
904   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
905         (truncate:SI
906          (lshiftrt:DI
907           (mult:DI (zero_extend:DI
908                     (match_operand:SI 1 "s_register_operand" "%r,0"))
909                    (zero_extend:DI
910                     (match_operand:SI 2 "s_register_operand" "r,r")))
911           (const_int 32))))
912    (clobber (match_scratch:SI 3 "=&r,&r"))]
913   "arm_fast_multiply"
914   "umull%?\\t%3, %0, %2, %1"
915 [(set_attr "type" "mult")])
917 (define_insn "mulsf3"
918   [(set (match_operand:SF 0 "s_register_operand" "=f")
919         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
920                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
921   "TARGET_HARD_FLOAT"
922   "fml%?s\\t%0, %1, %2"
923 [(set_attr "type" "ffmul")])
925 (define_insn "muldf3"
926   [(set (match_operand:DF 0 "s_register_operand" "=f")
927         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
928                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
929   "TARGET_HARD_FLOAT"
930   "muf%?d\\t%0, %1, %2"
931 [(set_attr "type" "fmul")])
933 (define_insn "*muldf_esfdf_df"
934   [(set (match_operand:DF 0 "s_register_operand" "=f")
935         (mult:DF (float_extend:DF
936                   (match_operand:SF 1 "s_register_operand" "f"))
937                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
938   "TARGET_HARD_FLOAT"
939   "muf%?d\\t%0, %1, %2"
940 [(set_attr "type" "fmul")])
942 (define_insn "*muldf_df_esfdf"
943   [(set (match_operand:DF 0 "s_register_operand" "=f")
944         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
945                  (float_extend:DF
946                   (match_operand:SF 2 "s_register_operand" "f"))))]
947   "TARGET_HARD_FLOAT"
948   "muf%?d\\t%0, %1, %2"
949 [(set_attr "type" "fmul")])
951 (define_insn "*muldf_esfdf_esfdf"
952   [(set (match_operand:DF 0 "s_register_operand" "=f")
953         (mult:DF (float_extend:DF
954                   (match_operand:SF 1 "s_register_operand" "f"))
955                  (float_extend:DF
956                   (match_operand:SF 2 "s_register_operand" "f"))))]
957   "TARGET_HARD_FLOAT"
958   "muf%?d\\t%0, %1, %2"
959 [(set_attr "type" "fmul")])
961 (define_insn "mulxf3"
962   [(set (match_operand:XF 0 "s_register_operand" "=f")
963         (mult:XF (match_operand:XF 1 "s_register_operand" "f")
964                  (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
965   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
966   "muf%?e\\t%0, %1, %2"
967 [(set_attr "type" "fmul")])
969 ;; Division insns
971 (define_insn "divsf3"
972   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
973         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
974                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
975   "TARGET_HARD_FLOAT"
976   "@
977    fdv%?s\\t%0, %1, %2
978    frd%?s\\t%0, %2, %1"
979 [(set_attr "type" "fdivs")])
981 (define_insn "divdf3"
982   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
983         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
984                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
985   "TARGET_HARD_FLOAT"
986   "@
987    dvf%?d\\t%0, %1, %2
988    rdf%?d\\t%0, %2, %1"
989 [(set_attr "type" "fdivd")])
991 (define_insn "*divdf_esfdf_df"
992   [(set (match_operand:DF 0 "s_register_operand" "=f")
993         (div:DF (float_extend:DF
994                  (match_operand:SF 1 "s_register_operand" "f"))
995                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
996   "TARGET_HARD_FLOAT"
997   "dvf%?d\\t%0, %1, %2"
998 [(set_attr "type" "fdivd")])
1000 (define_insn "*divdf_df_esfdf"
1001   [(set (match_operand:DF 0 "s_register_operand" "=f")
1002         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1003                 (float_extend:DF
1004                  (match_operand:SF 2 "s_register_operand" "f"))))]
1005   "TARGET_HARD_FLOAT"
1006   "rdf%?d\\t%0, %2, %1"
1007 [(set_attr "type" "fdivd")])
1009 (define_insn "*divdf_esfdf_esfdf"
1010   [(set (match_operand:DF 0 "s_register_operand" "=f")
1011         (div:DF (float_extend:DF
1012                  (match_operand:SF 1 "s_register_operand" "f"))
1013                 (float_extend:DF
1014                  (match_operand:SF 2 "s_register_operand" "f"))))]
1015   "TARGET_HARD_FLOAT"
1016   "dvf%?d\\t%0, %1, %2"
1017 [(set_attr "type" "fdivd")])
1019 (define_insn "divxf3"
1020   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1021         (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1022                 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1023   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1024   "@
1025    dvf%?e\\t%0, %1, %2
1026    rdf%?e\\t%0, %2, %1"
1027 [(set_attr "type" "fdivx")])
1029 ;; Modulo insns
1031 (define_insn "modsf3"
1032   [(set (match_operand:SF 0 "s_register_operand" "=f")
1033         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1034                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1035   "TARGET_HARD_FLOAT"
1036   "rmf%?s\\t%0, %1, %2"
1037 [(set_attr "type" "fdivs")])
1039 (define_insn "moddf3"
1040   [(set (match_operand:DF 0 "s_register_operand" "=f")
1041         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1042                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1043   "TARGET_HARD_FLOAT"
1044   "rmf%?d\\t%0, %1, %2"
1045 [(set_attr "type" "fdivd")])
1047 (define_insn "*moddf_esfdf_df"
1048   [(set (match_operand:DF 0 "s_register_operand" "=f")
1049         (mod:DF (float_extend:DF
1050                  (match_operand:SF 1 "s_register_operand" "f"))
1051                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1052   "TARGET_HARD_FLOAT"
1053   "rmf%?d\\t%0, %1, %2"
1054 [(set_attr "type" "fdivd")])
1056 (define_insn "*moddf_df_esfdf"
1057   [(set (match_operand:DF 0 "s_register_operand" "=f")
1058         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1059                 (float_extend:DF
1060                  (match_operand:SF 2 "s_register_operand" "f"))))]
1061   "TARGET_HARD_FLOAT"
1062   "rmf%?d\\t%0, %1, %2"
1063 [(set_attr "type" "fdivd")])
1065 (define_insn "*moddf_esfdf_esfdf"
1066   [(set (match_operand:DF 0 "s_register_operand" "=f")
1067         (mod:DF (float_extend:DF
1068                  (match_operand:SF 1 "s_register_operand" "f"))
1069                 (float_extend:DF
1070                  (match_operand:SF 2 "s_register_operand" "f"))))]
1071   "TARGET_HARD_FLOAT"
1072   "rmf%?d\\t%0, %1, %2"
1073 [(set_attr "type" "fdivd")])
1075 (define_insn "modxf3"
1076   [(set (match_operand:XF 0 "s_register_operand" "=f")
1077         (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1078                 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1079   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1080   "rmf%?e\\t%0, %1, %2"
1081 [(set_attr "type" "fdivx")])
1083 ;; Boolean and,ior,xor insns
1085 (define_insn "anddi3"
1086   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1087         (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1088                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1089   ""
1090   "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2"
1091 [(set_attr "length" "8")])
1093 (define_insn "*anddi_zesidi_di"
1094   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1095         (and:DI (zero_extend:DI
1096                  (match_operand:SI 2 "s_register_operand" "r,r"))
1097                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1098   ""
1099   "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0"
1100 [(set_attr "length" "8")])
1102 (define_insn "*anddi_sesdi_di"
1103   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1104         (and:DI (sign_extend:DI
1105                  (match_operand:SI 2 "s_register_operand" "r,r"))
1106                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1107   ""
1108   "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31"
1109 [(set_attr "length" "8")])
1111 (define_expand "andsi3"
1112   [(set (match_operand:SI 0 "s_register_operand" "")
1113         (and:SI (match_operand:SI 1 "s_register_operand" "")
1114                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1115   ""
1116   "
1117   if (GET_CODE (operands[2]) == CONST_INT)
1118     {
1119       arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1120                           operands[1],
1121                           (reload_in_progress || reload_completed
1122                            ? 0 : preserve_subexpressions_p ()));
1123       DONE;
1124     }
1127 (define_insn "*andsi3_insn"
1128   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1129         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1130                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1131   ""
1132   "@
1133    and%?\\t%0, %1, %2
1134    bic%?\\t%0, %1, #%B2
1135    #"
1136 [(set_attr "length" "4,4,16")])
1138 (define_split
1139   [(set (match_operand:SI 0 "s_register_operand" "")
1140         (and:SI (match_operand:SI 1 "s_register_operand" "")
1141                 (match_operand:SI 2 "const_int_operand" "")))]
1142   "! (const_ok_for_arm (INTVAL (operands[2]))
1143       || const_ok_for_arm (~ INTVAL (operands[2])))"
1144   [(clobber (const_int 0))]
1145   "
1146   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1147                        operands[1], 0);
1148   DONE;
1151 (define_insn "*andsi3_compare0"
1152   [(set (reg:CC_NOOV 24)
1153         (compare:CC_NOOV
1154          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1155                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1156          (const_int 0)))
1157    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1158         (and:SI (match_dup 1) (match_dup 2)))]
1159   ""
1160   "@
1161    and%?s\\t%0, %1, %2
1162    bic%?s\\t%0, %1, #%B2"
1163 [(set_attr "conds" "set")])
1165 (define_insn "*andsi3_compare0_scratch"
1166   [(set (reg:CC_NOOV 24)
1167         (compare:CC_NOOV
1168          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1169                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1170          (const_int 0)))
1171    (clobber (match_scratch:SI 3 "=X,r"))]
1172   ""
1173   "@
1174    tst%?\\t%0, %1
1175    bic%?s\\t%3, %0, #%B1"
1176 [(set_attr "conds" "set")])
1178 (define_insn "*zeroextractsi_compare0_scratch"
1179   [(set (reg:CC_NOOV 24)
1180         (compare:CC_NOOV (zero_extract:SI
1181                           (match_operand:SI 0 "s_register_operand" "r")
1182                           (match_operand 1 "const_int_operand" "n")
1183                           (match_operand 2 "const_int_operand" "n"))
1184                          (const_int 0)))]
1185   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1186    && INTVAL (operands[1]) > 0 
1187    && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1188    && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1189   "*
1190   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1191                          << INTVAL (operands[2]));
1192   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1193   return \"\";
1195 [(set_attr "conds" "set")])
1197 (define_insn "*ne_zeroextractsi"
1198   [(set (match_operand:SI 0 "s_register_operand" "=r")
1199         (ne:SI (zero_extract:SI
1200                 (match_operand:SI 1 "s_register_operand" "r")
1201                 (match_operand:SI 2 "const_int_operand" "n")
1202                 (match_operand:SI 3 "const_int_operand" "n"))
1203                (const_int 0)))]
1204   "INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1205    && INTVAL (operands[2]) > 0 
1206    && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1207    && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32"
1208   "*
1209   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1210                          << INTVAL (operands[3]));
1211   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1212   return \"movne\\t%0, #1\";
1214 [(set_attr "conds" "clob")
1215  (set_attr "length" "8")])
1217 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1218 ;;; represented by the bitfield, then this will produce incorrect results.
1219 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1220 ;;; which have a real bitfield insert instruction, the truncation happens
1221 ;;; in the bitfield insert instruction itself.  Since arm does not have a
1222 ;;; bitfield insert instruction, we would have to emit code here to truncate
1223 ;;; the value before we insert.  This loses some of the advantage of having
1224 ;;; this insv pattern, so this pattern needs to be reevalutated.
1226 (define_expand "insv"
1227   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1228                          (match_operand:SI 1 "general_operand" "")
1229                          (match_operand:SI 2 "general_operand" ""))
1230         (match_operand:SI 3 "nonmemory_operand" ""))]
1231   ""
1232   "
1234   int start_bit = INTVAL (operands[2]);
1235   int width = INTVAL (operands[1]);
1236   HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1237   rtx target, subtarget;
1238   
1239   target = operands[0];
1240   /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1241      subreg as the final target.  */
1242   if (GET_CODE (target) == SUBREG)
1243     {
1244       subtarget = gen_reg_rtx (SImode);
1245       if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1246           < GET_MODE_SIZE (SImode))
1247         target = SUBREG_REG (target);
1248     }
1249   else
1250     subtarget = target;    
1251     
1252   if (GET_CODE (operands[3]) == CONST_INT)
1253     {
1254       /* Since we are inserting a known constant, we may be able to
1255          reduce the number of bits that we have to clear so that
1256          the mask becomes simple.  */
1257       /* ??? This code does not check to see if the new mask is actually
1258          simpler.  It may not be.  */
1259       rtx op1 = gen_reg_rtx (SImode);
1260       /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1261          start of this pattern.  */
1262       HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1263       HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1265       emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1266       emit_insn (gen_iorsi3 (subtarget, op1,
1267                              GEN_INT (op3_value << start_bit)));
1268     }
1269   else if (start_bit == 0
1270            && ! (const_ok_for_arm (mask)
1271                  || const_ok_for_arm (~mask)))
1272     {
1273       /* A Trick, since we are setting the bottom bits in the word,
1274          we can shift operand[3] up, operand[0] down, OR them together
1275          and rotate the result back again.  This takes 3 insns, and
1276          the third might be mergable into another op.  */
1277       /* The shift up copes with the possibility that operand[3] is
1278          wider than the bitfield.  */
1279       rtx op0 = gen_reg_rtx (SImode);
1280       rtx op1 = gen_reg_rtx (SImode);
1282       emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1283       emit_insn (gen_iorsi3 (op1, gen_rtx_LSHIFTRT (SImode, operands[0],
1284                                                             operands[1]),
1285                              op0));
1286       emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1287     }
1288   else if ((width + start_bit == 32)
1289            && ! (const_ok_for_arm (mask)
1290                  || const_ok_for_arm (~mask)))
1291     {
1292       /* Similar trick, but slightly less efficient.  */
1294       rtx op0 = gen_reg_rtx (SImode);
1295       rtx op1 = gen_reg_rtx (SImode);
1297       emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1298       emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1299       emit_insn (gen_iorsi3 (subtarget,
1300                              gen_rtx_LSHIFTRT (SImode, op1, operands[1]),
1301                              op0));
1302     }
1303   else
1304     {
1305       rtx op0 = GEN_INT (mask);
1306       rtx op1 = gen_reg_rtx (SImode);
1307       rtx op2 = gen_reg_rtx (SImode);
1309       if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1310         {
1311           rtx tmp = gen_reg_rtx (SImode);
1313           emit_insn (gen_movsi (tmp, op0));
1314           op0 = tmp;
1315         }
1317       /* Mask out any bits in operand[3] that are not needed.  */
1318       emit_insn (gen_andsi3 (op1, operands[3], op0));
1320       if (GET_CODE (op0) == CONST_INT
1321           && (const_ok_for_arm (mask << start_bit)
1322               || const_ok_for_arm (~ (mask << start_bit))))
1323         {
1324           op0 = GEN_INT (~(mask << start_bit));
1325           emit_insn (gen_andsi3 (op2, operands[0], op0));
1326         }
1327       else
1328         {
1329           if (GET_CODE (op0) == CONST_INT)
1330             {
1331               rtx tmp = gen_reg_rtx (SImode);
1333               emit_insn (gen_movsi (tmp, op0));
1334               op0 = tmp;
1335             }
1337           if (start_bit != 0)
1338             op0 = gen_rtx_ASHIFT (SImode, op0, operands[2]);
1339             
1340           emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1341         }
1343       if (start_bit != 0)
1344         op1 = gen_rtx_ASHIFT (SImode, op1, operands[2]);
1346       emit_insn (gen_iorsi3 (subtarget, op1, op2));
1347     }
1349   if (subtarget != target)
1350     {
1351       /* If TARGET is still a SUBREG, then it must be wider than a word,
1352          so we must be careful only to set the subword we were asked to. */
1353       if (GET_CODE (target) == SUBREG)
1354         emit_move_insn (target, subtarget);
1355       else
1356         emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1357     }
1359   DONE;
1363 ;; constants for op 2 will never be given to these patterns.
1364 (define_insn "*anddi_notdi_di"
1365   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1366         (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1367                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1368   ""
1369   "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2"
1370 [(set_attr "length" "8")])
1371   
1372 (define_insn "*anddi_notzesidi_di"
1373   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1374         (and:DI (not:DI (zero_extend:DI
1375                          (match_operand:SI 2 "s_register_operand" "r,r")))
1376                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1377   ""
1378   "@
1379    bic%?\\t%Q0, %Q1, %2
1380    bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1381 [(set_attr "length" "4,8")])
1382   
1383 (define_insn "*anddi_notsesidi_di"
1384   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1385         (and:DI (not:DI (sign_extend:DI
1386                          (match_operand:SI 2 "s_register_operand" "r,r")))
1387                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1388   ""
1389   "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
1390 [(set_attr "length" "8")])
1391   
1392 (define_insn "andsi_notsi_si"
1393   [(set (match_operand:SI 0 "s_register_operand" "=r")
1394         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1395                 (match_operand:SI 1 "s_register_operand" "r")))]
1396   ""
1397   "bic%?\\t%0, %1, %2")
1399 (define_insn "andsi_not_shiftsi_si"
1400   [(set (match_operand:SI 0 "s_register_operand" "=r")
1401         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1402                          [(match_operand:SI 2 "s_register_operand" "r")
1403                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1404                 (match_operand:SI 1 "s_register_operand" "r")))]
1405   ""
1406   "bic%?\\t%0, %1, %2%S4")
1408 (define_insn "*andsi_notsi_si_compare0"
1409   [(set (reg:CC_NOOV 24)
1410         (compare:CC_NOOV
1411          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1412                  (match_operand:SI 1 "s_register_operand" "r"))
1413          (const_int 0)))
1414    (set (match_operand:SI 0 "s_register_operand" "=r")
1415         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1416   ""
1417   "bic%?s\\t%0, %1, %2"
1418 [(set_attr "conds" "set")])
1420 (define_insn "*andsi_notsi_si_compare0_scratch"
1421   [(set (reg:CC_NOOV 24)
1422         (compare:CC_NOOV
1423          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1424                  (match_operand:SI 1 "s_register_operand" "r"))
1425          (const_int 0)))
1426    (clobber (match_scratch:SI 0 "=r"))]
1427   ""
1428   "bic%?s\\t%0, %1, %2"
1429 [(set_attr "conds" "set")])
1431 (define_insn "iordi3"
1432   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1433         (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1434                 (match_operand:DI 2 "s_register_operand" "r")))]
1435   ""
1436   "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2"
1437 [(set_attr "length" "8")])
1439 (define_insn "*iordi_zesidi_di"
1440   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1441         (ior:DI (zero_extend:DI
1442                  (match_operand:SI 2 "s_register_operand" "r,r"))
1443                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1444   ""
1445   "@
1446    orr%?\\t%Q0, %Q1, %2
1447    orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1448 [(set_attr "length" "4,8")])
1450 (define_insn "*iordi_sesidi_di"
1451   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1452         (ior:DI (sign_extend:DI
1453                  (match_operand:SI 2 "s_register_operand" "r,r"))
1454                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1455   ""
1456   "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1457 [(set_attr "length" "8")])
1459 (define_expand "iorsi3"
1460   [(set (match_operand:SI 0 "s_register_operand" "")
1461         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1462                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1463   ""
1464   "
1465   if (GET_CODE (operands[2]) == CONST_INT)
1466     {
1467       arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1468                           operands[1],
1469                           (reload_in_progress || reload_completed
1470                            ? 0 : preserve_subexpressions_p ()));
1471       DONE;
1472     }
1475 (define_insn "*iorsi3_insn"
1476   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1477         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1478                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1479   ""
1480   "@
1481    orr%?\\t%0, %1, %2
1482    #"
1483 [(set_attr "length" "4,16")])
1485 (define_split
1486   [(set (match_operand:SI 0 "s_register_operand" "")
1487         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1488                 (match_operand:SI 2 "const_int_operand" "")))]
1489   "! const_ok_for_arm (INTVAL (operands[2]))"
1490   [(clobber (const_int 0))]
1491   "
1492   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1493                       operands[1], 0);
1494   DONE;
1496   
1497 (define_insn "*iorsi3_compare0"
1498   [(set (reg:CC_NOOV 24)
1499         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1500                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1501                          (const_int 0)))
1502    (set (match_operand:SI 0 "s_register_operand" "=r")
1503         (ior:SI (match_dup 1) (match_dup 2)))]
1504   ""
1505   "orr%?s\\t%0, %1, %2"
1506 [(set_attr "conds" "set")])
1508 (define_insn "*iorsi3_compare0_scratch"
1509   [(set (reg:CC_NOOV 24)
1510         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1511                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1512                          (const_int 0)))
1513    (clobber (match_scratch:SI 0 "=r"))]
1514   ""
1515   "orr%?s\\t%0, %1, %2"
1516 [(set_attr "conds" "set")])
1518 (define_insn "xordi3"
1519   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1520         (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1521                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1522   ""
1523   "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2"
1524 [(set_attr "length" "8")])
1526 (define_insn "*xordi_zesidi_di"
1527   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1528         (xor:DI (zero_extend:DI
1529                  (match_operand:SI 2 "s_register_operand" "r,r"))
1530                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1531   ""
1532   "@
1533    eor%?\\t%Q0, %Q1, %2
1534    eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1535 [(set_attr "length" "4,8")])
1537 (define_insn "*xordi_sesidi_di"
1538   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1539         (xor:DI (sign_extend:DI
1540                  (match_operand:SI 2 "s_register_operand" "r,r"))
1541                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1542   ""
1543   "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1544 [(set_attr "length" "8")])
1546 (define_insn "xorsi3"
1547   [(set (match_operand:SI 0 "s_register_operand" "=r")
1548         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1549                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1550   ""
1551   "eor%?\\t%0, %1, %2")
1553 (define_insn "*xorsi3_compare0"
1554   [(set (reg:CC_NOOV 24)
1555         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1556                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1557                          (const_int 0)))
1558    (set (match_operand:SI 0 "s_register_operand" "=r")
1559         (xor:SI (match_dup 1) (match_dup 2)))]
1560   ""
1561   "eor%?s\\t%0, %1, %2"
1562 [(set_attr "conds" "set")])
1564 (define_insn "*xorsi3_compare0_scratch"
1565   [(set (reg:CC_NOOV 24)
1566         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1567                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
1568                          (const_int 0)))]
1569   ""
1570   "teq%?\\t%0, %1"
1571 [(set_attr "conds" "set")])
1573 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
1574 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1575 ;; insns
1577 (define_split
1578   [(set (match_operand:SI 0 "s_register_operand" "=r")
1579         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1580                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1581                 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1582    (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1583   ""
1584   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1585                               (not:SI (match_dup 3))))
1586    (set (match_dup 0) (not:SI (match_dup 4)))]
1587   ""
1590 (define_insn "*andsi_iorsi3_notsi"
1591   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1592         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1593                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1594                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1595   ""
1596   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1597 [(set_attr "length" "8")])
1601 ;; Minimum and maximum insns
1603 (define_insn "smaxsi3"
1604   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1605         (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1606                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1607    (clobber (reg:CC 24))]
1608   ""
1609   "@
1610    cmp\\t%1, %2\;movlt\\t%0, %2
1611    cmp\\t%1, %2\;movge\\t%0, %1
1612    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1613 [(set_attr "conds" "clob")
1614  (set_attr "length" "8,8,12")])
1616 (define_insn "sminsi3"
1617   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1618         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1619                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1620    (clobber (reg:CC 24))]
1621   ""
1622   "@
1623    cmp\\t%1, %2\;movge\\t%0, %2
1624    cmp\\t%1, %2\;movlt\\t%0, %1
1625    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1626 [(set_attr "conds" "clob")
1627  (set_attr "length" "8,8,12")])
1629 (define_insn "umaxsi3"
1630   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1631         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1632                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1633    (clobber (reg:CC 24))]
1634   ""
1635   "@
1636    cmp\\t%1, %2\;movcc\\t%0, %2
1637    cmp\\t%1, %2\;movcs\\t%0, %1
1638    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1639 [(set_attr "conds" "clob")
1640  (set_attr "length" "8,8,12")])
1642 (define_insn "uminsi3"
1643   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1644         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1645                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1646    (clobber (reg:CC 24))]
1647   ""
1648   "@
1649    cmp\\t%1, %2\;movcs\\t%0, %2
1650    cmp\\t%1, %2\;movcc\\t%0, %1
1651    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1652 [(set_attr "conds" "clob")
1653  (set_attr "length" "8,8,12")])
1655 (define_insn "*store_minmaxsi"
1656   [(set (match_operand:SI 0 "memory_operand" "=m")
1657         (match_operator:SI 3 "minmax_operator"
1658          [(match_operand:SI 1 "s_register_operand" "r")
1659           (match_operand:SI 2 "s_register_operand" "r")]))
1660    (clobber (reg:CC 24))]
1661   ""
1662   "*
1663   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1664                          operands[2]);
1665   output_asm_insn (\"cmp\\t%1, %2\", operands);
1666   output_asm_insn (\"str%d3\\t%1, %0\", operands);
1667   output_asm_insn (\"str%D3\\t%2, %0\", operands);
1668   return \"\";
1670 [(set_attr "conds" "clob")
1671  (set_attr "length" "12")
1672  (set_attr "type" "store1")])
1674 ; Reject the frame pointer in operand[1], since reloading this after
1675 ; it has been eliminated can cause carnage.
1676 (define_insn "*minmax_arithsi"
1677   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1678         (match_operator:SI 4 "shiftable_operator"
1679          [(match_operator:SI 5 "minmax_operator"
1680            [(match_operand:SI 2 "s_register_operand" "r,r")
1681             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1682           (match_operand:SI 1 "s_register_operand" "0,?r")]))
1683    (clobber (reg:CC 24))]
1684   "GET_CODE (operands[1]) != REG
1685    || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
1686        && REGNO(operands[1]) != ARG_POINTER_REGNUM)"
1687   "*
1689   enum rtx_code code = GET_CODE (operands[4]);
1691   operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1692                          operands[3]);
1693   output_asm_insn (\"cmp\\t%2, %3\", operands);
1694   output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1695   if (which_alternative != 0 || operands[3] != const0_rtx
1696       || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1697     output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1698   return \"\";
1701 [(set_attr "conds" "clob")
1702  (set_attr "length" "12")])
1705 ;; Shift and rotation insns
1707 (define_expand "ashlsi3"
1708   [(set (match_operand:SI 0 "s_register_operand" "")
1709         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
1710                    (match_operand:SI 2 "arm_rhs_operand" "")))]
1711   ""
1712   "
1713   if (GET_CODE (operands[2]) == CONST_INT
1714       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1715     {
1716       emit_insn (gen_movsi (operands[0], const0_rtx));
1717       DONE;
1718     }
1721 (define_expand "ashrsi3"
1722   [(set (match_operand:SI 0 "s_register_operand" "")
1723         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1724                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1725   ""
1726   "
1727   if (GET_CODE (operands[2]) == CONST_INT
1728       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1729     operands[2] = GEN_INT (31);
1732 (define_expand "lshrsi3"
1733   [(set (match_operand:SI 0 "s_register_operand" "")
1734         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1735                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1736   ""
1737   "
1738   if (GET_CODE (operands[2]) == CONST_INT
1739       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1740     {
1741       emit_insn (gen_movsi (operands[0], const0_rtx));
1742       DONE;
1743     }
1746 (define_expand "rotlsi3"
1747   [(set (match_operand:SI 0 "s_register_operand" "")
1748         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1749                      (match_operand:SI 2 "reg_or_int_operand" "")))]
1750   ""
1751   "
1752   if (GET_CODE (operands[2]) == CONST_INT)
1753     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1754   else
1755     {
1756       rtx reg = gen_reg_rtx (SImode);
1757       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1758       operands[2] = reg;
1759     }
1762 (define_expand "rotrsi3"
1763   [(set (match_operand:SI 0 "s_register_operand" "")
1764         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1765                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1766   ""
1767   "
1768   if (GET_CODE (operands[2]) == CONST_INT
1769       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1770     operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1773 (define_insn "*shiftsi3"
1774   [(set (match_operand:SI 0 "s_register_operand" "=r")
1775         (match_operator:SI 3 "shift_operator"
1776          [(match_operand:SI 1 "s_register_operand" "r")
1777           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1778   ""
1779   "mov%?\\t%0, %1%S3")
1781 (define_insn "*shiftsi3_compare0"
1782   [(set (reg:CC_NOOV 24)
1783         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1784                           [(match_operand:SI 1 "s_register_operand" "r")
1785                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1786                          (const_int 0)))
1787    (set (match_operand:SI 0 "s_register_operand" "=r")
1788         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1789   ""
1790   "mov%?s\\t%0, %1%S3"
1791 [(set_attr "conds" "set")])
1793 (define_insn "*shiftsi3_compare0_scratch"
1794   [(set (reg:CC_NOOV 24)
1795         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1796                           [(match_operand:SI 1 "s_register_operand" "r")
1797                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1798                          (const_int 0)))
1799    (clobber (match_scratch:SI 0 "=r"))]
1800   ""
1801   "mov%?s\\t%0, %1%S3"
1802 [(set_attr "conds" "set")])
1804 (define_insn "*notsi_shiftsi"
1805   [(set (match_operand:SI 0 "s_register_operand" "=r")
1806         (not:SI (match_operator:SI 3 "shift_operator"
1807                  [(match_operand:SI 1 "s_register_operand" "r")
1808                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1809   ""
1810   "mvn%?\\t%0, %1%S3")
1812 (define_insn "*notsi_shiftsi_compare0"
1813   [(set (reg:CC_NOOV 24)
1814         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1815                           [(match_operand:SI 1 "s_register_operand" "r")
1816                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1817                          (const_int 0)))
1818    (set (match_operand:SI 0 "s_register_operand" "=r")
1819         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1820   ""
1821   "mvn%?s\\t%0, %1%S3"
1822 [(set_attr "conds" "set")])
1824 (define_insn "*not_shiftsi_compare0_scratch"
1825   [(set (reg:CC_NOOV 24)
1826         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1827                           [(match_operand:SI 1 "s_register_operand" "r")
1828                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1829                          (const_int 0)))
1830    (clobber (match_scratch:SI 0 "=r"))]
1831   ""
1832   "mvn%?s\\t%0, %1%S3"
1833 [(set_attr "conds" "set")])
1836 ;; Unary arithmetic insns
1838 (define_insn "negdi2"
1839   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1840         (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1841   ""
1842   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
1843 [(set_attr "conds" "clob")
1844  (set_attr "length" "8")])
1846 (define_insn "negsi2"
1847   [(set (match_operand:SI 0 "s_register_operand" "=r")
1848         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1849   ""
1850   "rsb%?\\t%0, %1, #0")
1852 (define_insn "negsf2"
1853   [(set (match_operand:SF 0 "s_register_operand" "=f")
1854         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1855   "TARGET_HARD_FLOAT"
1856   "mnf%?s\\t%0, %1"
1857 [(set_attr "type" "ffarith")])
1859 (define_insn "negdf2"
1860   [(set (match_operand:DF 0 "s_register_operand" "=f")
1861         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1862   "TARGET_HARD_FLOAT"
1863   "mnf%?d\\t%0, %1"
1864 [(set_attr "type" "ffarith")])
1866 (define_insn "*negdf_esfdf"
1867   [(set (match_operand:DF 0 "s_register_operand" "=f")
1868         (neg:DF (float_extend:DF
1869                  (match_operand:SF 1 "s_register_operand" "f"))))]
1870   "TARGET_HARD_FLOAT"
1871   "mnf%?d\\t%0, %1"
1872 [(set_attr "type" "ffarith")])
1874 (define_insn "negxf2"
1875   [(set (match_operand:XF 0 "s_register_operand" "=f")
1876         (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1877   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1878   "mnf%?e\\t%0, %1"
1879 [(set_attr "type" "ffarith")])
1881 ;; abssi2 doesn't really clobber the condition codes if a different register
1882 ;; is being set.  To keep things simple, assume during rtl manipulations that
1883 ;; it does, but tell the final scan operator the truth.  Similarly for
1884 ;; (neg (abs...))
1886 (define_insn "abssi2"
1887   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1888         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1889    (clobber (reg:CC 24))]
1890   ""
1891   "@
1892    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1893    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1894 [(set_attr "conds" "clob,*")
1895  (set_attr "length" "8")])
1897 (define_insn "*neg_abssi2"
1898   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1899         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1900    (clobber (reg:CC 24))]
1901   ""
1902   "@
1903    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1904    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1905 [(set_attr "conds" "clob,*")
1906  (set_attr "length" "8")])
1908 (define_insn "abssf2"
1909   [(set (match_operand:SF 0 "s_register_operand" "=f")
1910          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1911   "TARGET_HARD_FLOAT"
1912   "abs%?s\\t%0, %1"
1913 [(set_attr "type" "ffarith")])
1915 (define_insn "absdf2"
1916   [(set (match_operand:DF 0 "s_register_operand" "=f")
1917         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1918   "TARGET_HARD_FLOAT"
1919   "abs%?d\\t%0, %1"
1920 [(set_attr "type" "ffarith")])
1922 (define_insn "*absdf_esfdf"
1923   [(set (match_operand:DF 0 "s_register_operand" "=f")
1924         (abs:DF (float_extend:DF
1925                  (match_operand:SF 1 "s_register_operand" "f"))))]
1926   "TARGET_HARD_FLOAT"
1927   "abs%?d\\t%0, %1"
1928 [(set_attr "type" "ffarith")])
1930 (define_insn "absxf2"
1931   [(set (match_operand:XF 0 "s_register_operand" "=f")
1932         (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1933   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1934   "abs%?e\\t%0, %1"
1935 [(set_attr "type" "ffarith")])
1937 (define_insn "sqrtsf2"
1938   [(set (match_operand:SF 0 "s_register_operand" "=f")
1939         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1940   "TARGET_HARD_FLOAT"
1941   "sqt%?s\\t%0, %1"
1942 [(set_attr "type" "float_em")])
1944 (define_insn "sqrtdf2"
1945   [(set (match_operand:DF 0 "s_register_operand" "=f")
1946         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1947   "TARGET_HARD_FLOAT"
1948   "sqt%?d\\t%0, %1"
1949 [(set_attr "type" "float_em")])
1951 (define_insn "*sqrtdf_esfdf"
1952   [(set (match_operand:DF 0 "s_register_operand" "=f")
1953         (sqrt:DF (float_extend:DF
1954                   (match_operand:SF 1 "s_register_operand" "f"))))]
1955   "TARGET_HARD_FLOAT"
1956   "sqt%?d\\t%0, %1"
1957 [(set_attr "type" "float_em")])
1959 (define_insn "sqrtxf2"
1960   [(set (match_operand:XF 0 "s_register_operand" "=f")
1961         (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1962   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1963   "sqt%?e\\t%0, %1"
1964 [(set_attr "type" "float_em")])
1966 ;; SIN COS TAN and family are always emulated, so it's probably better
1967 ;; to always call a library function.
1968 ;(define_insn "sinsf2"
1969 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
1970 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1971 ;  "TARGET_HARD_FLOAT"
1972 ;  "sin%?s\\t%0, %1"
1973 ;[(set_attr "type" "float_em")])
1975 ;(define_insn "sindf2"
1976 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1977 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1978 ;  "TARGET_HARD_FLOAT"
1979 ;  "sin%?d\\t%0, %1"
1980 ;[(set_attr "type" "float_em")])
1982 ;(define_insn "*sindf_esfdf"
1983 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
1984 ;       (unspec:DF [(float_extend:DF
1985 ;                    (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1986 ;  "TARGET_HARD_FLOAT"
1987 ;  "sin%?d\\t%0, %1"
1988 ;[(set_attr "type" "float_em")])
1990 ;(define_insn "sinxf2"
1991 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
1992 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1993 ;  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1994 ;  "sin%?e\\t%0, %1"
1995 ;[(set_attr "type" "float_em")])
1997 ;(define_insn "cossf2"
1998 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
1999 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
2000 ;  "TARGET_HARD_FLOAT"
2001 ;  "cos%?s\\t%0, %1"
2002 ;[(set_attr "type" "float_em")])
2004 ;(define_insn "cosdf2"
2005 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2006 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
2007 ;  "TARGET_HARD_FLOAT"
2008 ;  "cos%?d\\t%0, %1"
2009 ;[(set_attr "type" "float_em")])
2011 ;(define_insn "*cosdf_esfdf"
2012 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2013 ;       (unspec:DF [(float_extend:DF
2014 ;                    (match_operand:SF 1 "s_register_operand" "f"))] 1))]
2015 ;  "TARGET_HARD_FLOAT"
2016 ;  "cos%?d\\t%0, %1"
2017 ;[(set_attr "type" "float_em")])
2019 ;(define_insn "cosxf2"
2020 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2021 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
2022 ;  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2023 ;  "cos%?e\\t%0, %1"
2024 ;[(set_attr "type" "float_em")])
2026 (define_insn "one_cmpldi2"
2027   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2028         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2029   ""
2030   "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1"
2031 [(set_attr "length" "8")])
2033 (define_insn "one_cmplsi2"
2034   [(set (match_operand:SI 0 "s_register_operand" "=r")
2035         (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2036   ""
2037   "mvn%?\\t%0, %1")
2039 (define_insn "*notsi_compare0"
2040   [(set (reg:CC_NOOV 24)
2041         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2042                          (const_int 0)))
2043    (set (match_operand:SI 0 "s_register_operand" "=r")
2044         (not:SI (match_dup 1)))]
2045   ""
2046   "mvn%?s\\t%0, %1"
2047 [(set_attr "conds" "set")])
2049 (define_insn "*notsi_compare0_scratch"
2050   [(set (reg:CC_NOOV 24)
2051         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2052                          (const_int 0)))
2053    (clobber (match_scratch:SI 0 "=r"))]
2054   ""
2055   "mvn%?s\\t%0, %1"
2056 [(set_attr "conds" "set")])
2058 ;; Fixed <--> Floating conversion insns
2060 (define_insn "floatsisf2"
2061   [(set (match_operand:SF 0 "s_register_operand" "=f")
2062         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2063   "TARGET_HARD_FLOAT"
2064   "flt%?s\\t%0, %1"
2065 [(set_attr "type" "r_2_f")])
2067 (define_insn "floatsidf2"
2068   [(set (match_operand:DF 0 "s_register_operand" "=f")
2069         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2070   "TARGET_HARD_FLOAT"
2071   "flt%?d\\t%0, %1"
2072 [(set_attr "type" "r_2_f")])
2074 (define_insn "floatsixf2"
2075   [(set (match_operand:XF 0 "s_register_operand" "=f")
2076         (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
2077   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2078   "flt%?e\\t%0, %1"
2079 [(set_attr "type" "r_2_f")])
2081 (define_insn "fix_truncsfsi2"
2082   [(set (match_operand:SI 0 "s_register_operand" "=r")
2083         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2084   "TARGET_HARD_FLOAT"
2085   "fix%?z\\t%0, %1"
2086 [(set_attr "type" "f_2_r")])
2088 (define_insn "fix_truncdfsi2"
2089   [(set (match_operand:SI 0 "s_register_operand" "=r")
2090         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2091   "TARGET_HARD_FLOAT"
2092   "fix%?z\\t%0, %1"
2093 [(set_attr "type" "f_2_r")])
2095 (define_insn "fix_truncxfsi2"
2096   [(set (match_operand:SI 0 "s_register_operand" "=r")
2097         (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
2098   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2099   "fix%?z\\t%0, %1"
2100 [(set_attr "type" "f_2_r")])
2102 ;; Truncation insns
2104 (define_insn "truncdfsf2"
2105   [(set (match_operand:SF 0 "s_register_operand" "=f")
2106         (float_truncate:SF
2107          (match_operand:DF 1 "s_register_operand" "f")))]
2108   "TARGET_HARD_FLOAT"
2109   "mvf%?s\\t%0, %1"
2110 [(set_attr "type" "ffarith")])
2112 (define_insn "truncxfsf2"
2113   [(set (match_operand:SF 0 "s_register_operand" "=f")
2114         (float_truncate:SF
2115          (match_operand:XF 1 "s_register_operand" "f")))]
2116   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2117   "mvf%?s\\t%0, %1"
2118 [(set_attr "type" "ffarith")])
2120 (define_insn "truncxfdf2"
2121   [(set (match_operand:DF 0 "s_register_operand" "=f")
2122         (float_truncate:DF
2123          (match_operand:XF 1 "s_register_operand" "f")))]
2124   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2125   "mvf%?d\\t%0, %1"
2126 [(set_attr "type" "ffarith")])
2128 ;; Zero and sign extension instructions.
2130 (define_insn "zero_extendsidi2"
2131   [(set (match_operand:DI 0 "s_register_operand" "=r")
2132         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2133   ""
2134   "*
2135   if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2136     output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2137   return \"mov%?\\t%R0, #0\";
2139 [(set_attr "length" "8")])
2141 (define_insn "zero_extendqidi2"
2142   [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2143         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2144   ""
2145   "@
2146    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2147    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2148 [(set_attr "length" "8")
2149  (set_attr "type" "*,load")])
2151 (define_insn "extendsidi2"
2152   [(set (match_operand:DI 0 "s_register_operand" "=r")
2153         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2154   ""
2155   "*
2156   if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2157     output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2158   return \"mov%?\\t%R0, %Q0, asr #31\";
2160 [(set_attr "length" "8")])
2162 (define_expand "zero_extendhisi2"
2163   [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2164                                  (const_int 16)))
2165    (set (match_operand:SI 0 "s_register_operand" "")
2166         (lshiftrt:SI (match_dup 2) (const_int 16)))]
2167   ""
2168   "
2170   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2171     {
2172      /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES
2173         here because the insn below will generate an LDRH instruction
2174         rather than an LDR instruction, so we cannot get an unaligned
2175         word access.  */
2176       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2177                               gen_rtx_ZERO_EXTEND (SImode, operands[1])));
2178       DONE;
2179     }
2180   if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2181     {
2182       emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2183       DONE;
2184     }
2185   if (! s_register_operand (operands[1], HImode))
2186     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2187   operands[1] = gen_lowpart (SImode, operands[1]);
2188   operands[2] = gen_reg_rtx (SImode); 
2191 (define_insn "*zero_extendhisi_insn"
2192   [(set (match_operand:SI 0 "s_register_operand" "=r")
2193         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2194   "arm_arch4"
2195   "ldr%?h\\t%0, %1"
2196 [(set_attr "type" "load")])
2198 (define_split
2199   [(set (match_operand:SI 0 "s_register_operand" "")
2200         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2201    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2202   "! arm_arch4"
2203   [(set (match_dup 2) (match_dup 1))
2204    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2205   "
2207   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2208     FAIL;
2211 (define_split
2212   [(set (match_operand:SI 0 "s_register_operand" "")
2213         (match_operator:SI 3 "shiftable_operator"
2214          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2215           (match_operand:SI 4 "s_register_operand" "")]))
2216    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2217   "! arm_arch4"
2218   [(set (match_dup 2) (match_dup 1))
2219    (set (match_dup 0)
2220         (match_op_dup 3
2221          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2222   "
2224   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2225     FAIL;
2228 (define_expand "zero_extendqisi2"
2229   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2230         (zero_extend:SI
2231          (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2232   ""
2233   "
2234   if (GET_CODE (operands[1]) != MEM)
2235     {
2236       emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
2237                              GEN_INT (255)));
2238       DONE;
2239     }
2242 (define_insn "*load_extendqisi"
2243   [(set (match_operand:SI 0 "s_register_operand" "=r")
2244         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2245   ""
2246   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
2247 [(set_attr "type" "load")])
2249 (define_split
2250   [(set (match_operand:SI 0 "s_register_operand" "")
2251         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
2252    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2253   "GET_CODE (operands[1]) != MEM"
2254   [(set (match_dup 2) (match_dup 1))
2255    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
2256   "")
2258 (define_insn "*compareqi_eq0"
2259   [(set (reg:CC_Z 24)
2260         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
2261                          (const_int 0)))]
2262   ""
2263   "tst\\t%0, #255"
2264 [(set_attr "conds" "set")])
2266 (define_expand "extendhisi2"
2267   [(set (match_dup 2)
2268         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2269                    (const_int 16)))
2270    (set (match_operand:SI 0 "s_register_operand" "")
2271         (ashiftrt:SI (match_dup 2)
2272                      (const_int 16)))]
2273   ""
2274   "
2276   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2277     {
2278      /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES
2279         here because the insn below will generate an LDRH instruction
2280         rather than an LDR instruction, so we cannot get an unaligned
2281         word access.  */
2282       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2283                  gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2284       DONE;
2285     }
2287   if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2288     {
2289       emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
2290       DONE;
2291     }
2292   if (! s_register_operand (operands[1], HImode))
2293     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2294   operands[1] = gen_lowpart (SImode, operands[1]);
2295   operands[2] = gen_reg_rtx (SImode);
2298 (define_expand "extendhisi2_mem"
2299   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
2300    (set (match_dup 3)
2301         (zero_extend:SI (match_dup 7)))
2302    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
2303    (set (match_operand:SI 0 "" "")
2304         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
2305   ""
2306   "
2308   rtx mem1, mem2;
2309   rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2311   mem1 = gen_rtx_MEM (QImode, addr);
2312   MEM_COPY_ATTRIBUTES (mem1, operands[1]);
2313   RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
2314   mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
2315   MEM_COPY_ATTRIBUTES (mem2, operands[1]);
2316   RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
2317   operands[0] = gen_lowpart (SImode, operands[0]);
2318   operands[1] = mem1;
2319   operands[2] = gen_reg_rtx (SImode);
2320   operands[3] = gen_reg_rtx (SImode);
2321   operands[6] = gen_reg_rtx (SImode);
2322   operands[7] = mem2;
2324   if (BYTES_BIG_ENDIAN)
2325     {
2326       operands[4] = operands[2];
2327       operands[5] = operands[3];
2328     }
2329   else
2330     {
2331       operands[4] = operands[3];
2332       operands[5] = operands[2];
2333     }
2337 (define_insn "*extendhisi_insn"
2338   [(set (match_operand:SI 0 "s_register_operand" "=r")
2339         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2340   "arm_arch4"
2341   "ldr%?sh\\t%0, %1"
2342 [(set_attr "type" "load")])
2344 (define_split
2345   [(set (match_operand:SI 0 "s_register_operand" "")
2346         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2347    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2348   "! arm_arch4"
2349   [(set (match_dup 2) (match_dup 1))
2350    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2351   "
2353   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2354     FAIL;
2357 (define_split
2358   [(set (match_operand:SI 0 "s_register_operand" "")
2359         (match_operator:SI 3 "shiftable_operator"
2360          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2361           (match_operand:SI 4 "s_register_operand" "")]))
2362    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2363   "! arm_arch4"
2364   [(set (match_dup 2) (match_dup 1))
2365    (set (match_dup 0)
2366         (match_op_dup 3
2367          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2368   "
2370   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2371     FAIL;
2374 (define_expand "extendqihi2"
2375   [(set (match_dup 2)
2376         (ashift:SI (match_operand:QI 1 "general_operand" "")
2377                    (const_int 24)))
2378    (set (match_operand:HI 0 "s_register_operand" "")
2379         (ashiftrt:SI (match_dup 2)
2380                      (const_int 24)))]
2381   ""
2382   "
2384   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2385     {
2386       emit_insn (gen_rtx_SET (VOIDmode,
2387                               operands[0],
2388                               gen_rtx_SIGN_EXTEND (HImode, operands[1])));
2389       DONE;
2390     }
2391   if (! s_register_operand (operands[1], QImode))
2392     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2393   operands[0] = gen_lowpart (SImode, operands[0]);
2394   operands[1] = gen_lowpart (SImode, operands[1]);
2395   operands[2] = gen_reg_rtx (SImode);
2398 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2399 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2400 (define_insn "*extendqihi_insn"
2401   [(set (match_operand:HI 0 "s_register_operand" "=r")
2402         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
2403   "arm_arch4"
2404   "*
2405   /* If the address is invalid, this will split the instruction into two. */
2406   if (bad_signed_byte_operand(operands[1], QImode))
2407     return \"#\";
2408   return \"ldr%?sb\\t%0, %1\";
2410 [(set_attr "type" "load")
2411  (set_attr "length" "8")])
2413 (define_split
2414   [(set (match_operand:HI 0 "s_register_operand" "")
2415         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2416   "arm_arch4 && reload_completed"
2417   [(set (match_dup 3) (match_dup 1))
2418    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
2419   "
2420   {
2421     HOST_WIDE_INT offset;
2423     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
2424     operands[2] = gen_rtx_MEM (QImode, operands[3]);
2425     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2426     RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2427     operands[1] = XEXP (operands[1], 0);
2428     if (GET_CODE (operands[1]) == PLUS
2429         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2430         && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2431               || const_ok_for_arm (-offset)))
2432       {
2433         HOST_WIDE_INT low = (offset > 0
2434                              ? (offset & 0xff) : -((-offset) & 0xff));
2435         XEXP (operands[2], 0) = plus_constant (operands[3], low);
2436         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2437       }
2438     /* Ensure the sum is in correct canonical form */
2439     else if (GET_CODE (operands[1]) == PLUS
2440              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2441              && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2442       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2443                                            XEXP (operands[1], 1),
2444                                            XEXP (operands[1], 0));
2445   }
2448 (define_expand "extendqisi2"
2449   [(set (match_dup 2)
2450         (ashift:SI (match_operand:QI 1 "general_operand" "")
2451                    (const_int 24)))
2452    (set (match_operand:SI 0 "s_register_operand" "")
2453         (ashiftrt:SI (match_dup 2)
2454                      (const_int 24)))]
2455   ""
2456   "
2458   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2459     {
2460       emit_insn (gen_rtx_SET (VOIDmode,
2461                               operands[0],
2462                               gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2463       DONE;
2464     }
2465   if (! s_register_operand (operands[1], QImode))
2466     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2467   operands[1] = gen_lowpart (SImode, operands[1]);
2468   operands[2] = gen_reg_rtx (SImode);
2471 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2472 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2473 (define_insn "*extendqisi_insn"
2474   [(set (match_operand:SI 0 "s_register_operand" "=r")
2475         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2476   "arm_arch4"
2477   "*
2478   /* If the address is invalid, this will split the instruction into two. */
2479   if (bad_signed_byte_operand(operands[1], QImode))
2480     return \"#\";
2481   return \"ldr%?sb\\t%0, %1\";
2483 [(set_attr "type" "load")
2484  (set_attr "length" "8")])
2486 (define_split
2487   [(set (match_operand:SI 0 "s_register_operand" "")
2488         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2489   "arm_arch4 && reload_completed"
2490   [(set (match_dup 0) (match_dup 1))
2491    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2492   "
2493   {
2494     HOST_WIDE_INT offset;
2496     operands[2] = gen_rtx_MEM (QImode, operands[0]);
2497     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2498     RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2499     operands[1] = XEXP (operands[1], 0);
2500     if (GET_CODE (operands[1]) == PLUS
2501         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2502         && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2503               || const_ok_for_arm (-offset)))
2504       {
2505         HOST_WIDE_INT low = (offset > 0
2506                              ? (offset & 0xff) : -((-offset) & 0xff));
2507         XEXP (operands[2], 0) = plus_constant (operands[0], low);
2508         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2509       }
2510     /* Ensure the sum is in correct canonical form */
2511     else if (GET_CODE (operands[1]) == PLUS
2512              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2513              && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2514       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2515                                            XEXP (operands[1], 1),
2516                                            XEXP (operands[1], 0));
2517   }
2520 (define_insn "extendsfdf2"
2521   [(set (match_operand:DF 0 "s_register_operand" "=f")
2522         (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2523   "TARGET_HARD_FLOAT"
2524   "mvf%?d\\t%0, %1"
2525 [(set_attr "type" "ffarith")])
2527 (define_insn "extendsfxf2"
2528   [(set (match_operand:XF 0 "s_register_operand" "=f")
2529         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2530   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2531   "mvf%?e\\t%0, %1"
2532 [(set_attr "type" "ffarith")])
2534 (define_insn "extenddfxf2"
2535   [(set (match_operand:XF 0 "s_register_operand" "=f")
2536         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2537   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2538   "mvf%?e\\t%0, %1"
2539 [(set_attr "type" "ffarith")])
2542 ;; Move insns (including loads and stores)
2544 ;; XXX Just some ideas about movti.
2545 ;; I don't think these are a good idea on the arm, there just aren't enough
2546 ;; registers
2547 ;;(define_expand "loadti"
2548 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
2549 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
2550 ;;  "" "")
2552 ;;(define_expand "storeti"
2553 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2554 ;;      (match_operand:TI 1 "s_register_operand" ""))]
2555 ;;  "" "")
2557 ;;(define_expand "movti"
2558 ;;  [(set (match_operand:TI 0 "general_operand" "")
2559 ;;      (match_operand:TI 1 "general_operand" ""))]
2560 ;;  ""
2561 ;;  "
2563 ;;  rtx insn;
2565 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2566 ;;    operands[1] = copy_to_reg (operands[1]);
2567 ;;  if (GET_CODE (operands[0]) == MEM)
2568 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2569 ;;  else if (GET_CODE (operands[1]) == MEM)
2570 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2571 ;;  else
2572 ;;    FAIL;
2574 ;;  emit_insn (insn);
2575 ;;  DONE;
2576 ;;}")
2578 ;; Recognise garbage generated above.
2580 ;;(define_insn ""
2581 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2582 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2583 ;;  ""
2584 ;;  "*
2585 ;;  {
2586 ;;    register mem = (which_alternative < 3);
2587 ;;    register char *template;
2589 ;;    operands[mem] = XEXP (operands[mem], 0);
2590 ;;    switch (which_alternative)
2591 ;;      {
2592 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2593 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
2594 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
2595 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
2596 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
2597 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
2598 ;;      }
2599 ;;    output_asm_insn (template, operands);
2600 ;;    return \"\";
2601 ;;  }")
2604 (define_insn "movdi"
2605   [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2606         (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2607   ""
2608   "*
2609   return (output_move_double (operands));
2611 [(set_attr "length" "8,8,8")
2612  (set_attr "type" "*,load,store2")])
2614 (define_expand "movsi"
2615   [(set (match_operand:SI 0 "general_operand" "")
2616         (match_operand:SI 1 "general_operand" ""))]
2617   ""
2618   "
2619   /* Everything except mem = const or mem = mem can be done easily */
2620   if (GET_CODE (operands[0]) == MEM)
2621     operands[1] = force_reg (SImode, operands[1]);
2622   if (GET_CODE (operands[1]) == CONST_INT
2623       && !(const_ok_for_arm (INTVAL (operands[1]))
2624            || const_ok_for_arm (~INTVAL (operands[1]))))
2625     {
2626       arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2627                           NULL_RTX,
2628                           (reload_in_progress || reload_completed ? 0
2629                            : preserve_subexpressions_p ()));
2630       DONE;
2631     }
2632   if (CONSTANT_P (operands[1]) && flag_pic)
2633     operands[1] = legitimize_pic_address (operands[1], SImode,
2634                                           ((reload_in_progress
2635                                             || reload_completed)
2636                                            ? operands[0] : 0));
2639 (define_insn "*movsi_insn"
2640   [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2641         (match_operand:SI 1 "general_operand"  "rI,K,mi,r"))]
2642   "register_operand (operands[0], SImode)
2643    || register_operand (operands[1], SImode)"
2644   "@
2645    mov%?\\t%0, %1
2646    mvn%?\\t%0, #%B1
2647    ldr%?\\t%0, %1
2648    str%?\\t%1, %0"
2649 [(set_attr "type" "*,*,load,store1")])
2651 (define_split
2652   [(set (match_operand:SI 0 "s_register_operand" "")
2653         (match_operand:SI 1 "const_int_operand" ""))]
2654   "! (const_ok_for_arm (INTVAL (operands[1]))
2655       || const_ok_for_arm (~INTVAL (operands[1])))"
2656   [(clobber (const_int 0))]
2657   "
2658   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2659                       NULL_RTX, 0);
2660   DONE;
2663 (define_expand "movaddr"
2664   [(set (match_operand:SI 0 "s_register_operand" "")
2665         (match_operand:DI 1 "address_operand" ""))]
2666   ""
2667   "")
2669 (define_insn "*movaddr_insn"
2670   [(set (match_operand:SI 0 "s_register_operand" "=r")
2671         (match_operand:DI 1 "address_operand" "p"))]
2672   "reload_completed
2673    && (GET_CODE (operands[1]) == LABEL_REF
2674        || (GET_CODE (operands[1]) == CONST
2675            && GET_CODE (XEXP (operands[1], 0)) == PLUS
2676            && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2677            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2678   "adr%?\\t%0, %a1")
2680 /* When generating pic, we need to load the symbol offset into a register.
2681    So that the optimizer does not confuse this with a normal symbol load
2682    we use an unspec.  The offset will be loaded from a constant pool entry,
2683    since that is the only type of relocation we can use.  */
2685 (define_insn "pic_load_addr"
2686   [(set (match_operand:SI 0 "s_register_operand" "=r")
2687         (unspec:SI [(match_operand 1 "" "")] 3))]
2688   "flag_pic"
2689   "ldr%?\\t%0, %a1"
2690  [(set_attr "type" "load")])
2692 ;; This variant is used for AOF assembly, since it needs to mention the
2693 ;; pic register in the rtl.
2694 (define_expand "pic_load_addr_based"
2695   [(set (match_operand:SI 0 "s_register_operand" "=r")
2696         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
2697   "flag_pic"
2698   "operands[2] = pic_offset_table_rtx;")
2700 (define_insn "*pic_load_addr_based_insn"
2701   [(set (match_operand:SI 0 "s_register_operand" "=r")
2702         (unspec:SI [(match_operand 1 "" "")
2703                     (match_operand 2 "s_register_operand" "r")] 3))]
2704   "flag_pic && operands[2] == pic_offset_table_rtx"
2705   "*
2706 #ifdef AOF_ASSEMBLER
2707   operands[1] = aof_pic_entry (operands[1]);
2708 #endif
2709   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
2710   return \"\";
2711 " [(set_attr "type" "load")])
2713 (define_insn "pic_add_dot_plus_eight"
2714   [(set (match_operand 0 "register_operand" "+r")
2715         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
2716    (use (label_ref (match_operand 1 "" "")))]
2717   "flag_pic"
2718   "*
2719   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
2720                              CODE_LABEL_NUMBER (operands[1]));
2721   return \"add%?\\t%0, %|pc, %0\";
2724 ;; If copying one reg to another we can set the condition codes according to
2725 ;; its value.  Such a move is common after a return from subroutine and the
2726 ;; result is being tested against zero.
2728 (define_insn "*movsi_compare0"
2729   [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
2730                                 (const_int 0)))
2731    (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2732   ""
2733   "@
2734    cmp%?\\t%0, #0
2735    sub%?s\\t%0, %1, #0"
2736 [(set_attr "conds" "set")])
2738 ;; Subroutine to store a half word from a register into memory.
2739 ;; Operand 0 is the source register (HImode)
2740 ;; Operand 1 is the destination address in a register (SImode)
2742 ;; In both this routine and the next, we must be careful not to spill
2743 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2744 ;; can generate unrecognizable rtl.
2746 (define_expand "storehi"
2747   [;; store the low byte
2748    (set (match_operand 1 "" "") (match_dup 3))
2749    ;; extract the high byte
2750    (set (match_dup 2)
2751         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2752    ;; store the high byte
2753    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
2754   ""
2755   "
2757   rtx addr = XEXP (operands[1], 0);
2758   enum rtx_code code = GET_CODE (addr);
2760   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2761       || code == MINUS)
2762     addr = force_reg (SImode, addr);
2764   operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2765   operands[1] = change_address (operands[1], QImode, NULL_RTX);
2766   operands[3] = gen_lowpart (QImode, operands[0]);
2767   operands[0] = gen_lowpart (SImode, operands[0]);
2768   operands[2] = gen_reg_rtx (SImode); 
2772 (define_expand "storehi_bigend"
2773   [(set (match_dup 4) (match_dup 3))
2774    (set (match_dup 2)
2775         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2776    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
2777   ""
2778   "
2780   rtx addr = XEXP (operands[1], 0);
2781   enum rtx_code code = GET_CODE (addr);
2783   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2784       || code == MINUS)
2785     addr = force_reg (SImode, addr);
2787   operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2788   operands[1] = change_address (operands[1], QImode, NULL_RTX);
2789   operands[3] = gen_lowpart (QImode, operands[0]);
2790   operands[0] = gen_lowpart (SImode, operands[0]);
2791   operands[2] = gen_reg_rtx (SImode);
2795 ;; Subroutine to store a half word integer constant into memory.
2796 (define_expand "storeinthi"
2797   [(set (match_operand 0 "" "")
2798         (subreg:QI (match_operand 1 "" "") 0))
2799    (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
2800   ""
2801   "
2803   HOST_WIDE_INT value = INTVAL (operands[1]);
2804   rtx addr = XEXP (operands[0], 0);
2805   enum rtx_code code = GET_CODE (addr);
2807   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2808       || code == MINUS)
2809     addr = force_reg (SImode, addr);
2811   operands[1] = gen_reg_rtx (SImode);
2812   if (BYTES_BIG_ENDIAN)
2813     {
2814       emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2815       if ((value & 255) == ((value >> 8) & 255))
2816         operands[2] = operands[1];
2817       else
2818         {
2819           operands[2] = gen_reg_rtx (SImode);
2820           emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2821         }
2822     }
2823   else
2824     {
2825       emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2826       if ((value & 255) == ((value >> 8) & 255))
2827         operands[2] = operands[1];
2828       else
2829         {
2830           operands[2] = gen_reg_rtx (SImode);
2831           emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2832         }
2833     }
2835   operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
2836   operands[0] = change_address (operands[0], QImode, NULL_RTX);
2840 (define_expand "storehi_single_op"
2841   [(set (match_operand:HI 0 "memory_operand" "")
2842         (match_operand:HI 1 "general_operand" ""))]
2843   "arm_arch4"
2844   "
2845   if (! s_register_operand (operands[1], HImode))
2846     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2849 (define_expand "movhi"
2850   [(set (match_operand:HI 0 "general_operand" "")
2851         (match_operand:HI 1 "general_operand" ""))]
2852   ""
2853   "
2855   rtx insn;
2857   if (! (reload_in_progress || reload_completed))
2858     {
2859       if (GET_CODE (operands[0]) == MEM)
2860         {
2861           if (arm_arch4)
2862             {
2863               emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2864               DONE;
2865             }
2866           if (GET_CODE (operands[1]) == CONST_INT)
2867             emit_insn (gen_storeinthi (operands[0], operands[1]));
2868           else
2869             {
2870               if (GET_CODE (operands[1]) == MEM)
2871                 operands[1] = force_reg (HImode, operands[1]);
2872               if (BYTES_BIG_ENDIAN)
2873                 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
2874               else
2875                 emit_insn (gen_storehi (operands[1], operands[0]));
2876             }
2877           DONE;
2878         }
2879       /* Sign extend a constant, and keep it in an SImode reg.  */
2880       else if (GET_CODE (operands[1]) == CONST_INT)
2881         {
2882           rtx reg = gen_reg_rtx (SImode);
2883           HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2885           /* If the constant is already valid, leave it alone.  */
2886           if (! const_ok_for_arm (val))
2887             {
2888               /* If setting all the top bits will make the constant 
2889                  loadable in a single instruction, then set them.  
2890                  Otherwise, sign extend the number.  */
2892               if (const_ok_for_arm (~ (val | ~0xffff)))
2893                 val |= ~0xffff;
2894               else if (val & 0x8000)
2895                 val |= ~0xffff;
2896             }
2898           emit_insn (gen_movsi (reg, GEN_INT (val)));
2899           operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
2900         }
2901       else if (! arm_arch4)
2902         {
2903          /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES
2904             for v4 and up architectures because LDRH instructions will
2905             be used to access the HI values, and these cannot generate
2906             unaligned word access faults in the MMU.  */
2907           if (GET_CODE (operands[1]) == MEM)
2908             {
2909               if (TARGET_SHORT_BY_BYTES)
2910                 {
2911                   rtx base;
2912                   rtx offset = const0_rtx;
2913                   rtx reg = gen_reg_rtx (SImode);
2915                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2916                        || (GET_CODE (base) == PLUS
2917                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2918                            && GET_CODE (base = XEXP (base, 0)) == REG))
2919                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2920                     {
2921                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~2;
2922                       rtx new;
2924                       new = gen_rtx_MEM (SImode,
2925                                          plus_constant (base, new_offset));
2926                       MEM_COPY_ATTRIBUTES (new, operands[1]);
2927                       RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2928                       emit_insn (gen_movsi (reg, new));
2929                       if (((INTVAL (offset) & 2) != 0)
2930                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
2931                         {
2932                           rtx reg2 = gen_reg_rtx (SImode);
2934                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
2935                           reg = reg2;
2936                         }
2937                     }
2938                   else
2939                     emit_insn (gen_movhi_bytes (reg, operands[1]));
2941                   operands[1] = gen_lowpart (HImode, reg);
2942                 }
2943               else if (BYTES_BIG_ENDIAN)
2944                 {
2945                   rtx base;
2946                   rtx offset = const0_rtx;
2948                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2949                        || (GET_CODE (base) == PLUS
2950                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2951                            && GET_CODE (base = XEXP (base, 0)) == REG))
2952                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2953                     {
2954                       rtx reg = gen_reg_rtx (SImode);
2955                       rtx new;
2957                       if ((INTVAL (offset) & 2) == 2)
2958                         {
2959                           HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
2960                           new = gen_rtx_MEM (SImode,
2961                                              plus_constant (base, new_offset));
2962                           MEM_COPY_ATTRIBUTES (new, operands[1]);
2963                           RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2964                           emit_insn (gen_movsi (reg, new));
2965                         }
2966                       else
2967                         {
2968                           new = gen_rtx_MEM (SImode, XEXP (operands[1], 0));
2969                           MEM_COPY_ATTRIBUTES (new, operands[1]);
2970                           RTX_UNCHANGING_P (new)
2971                             = RTX_UNCHANGING_P (operands[1]);
2972                           emit_insn (gen_rotated_loadsi (reg, new));
2973                         }
2975                       operands[1] = gen_lowpart (HImode, reg);
2976                     }
2977                   else
2978                     {
2979                       emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2980                       DONE;
2981                     }
2982                 }
2983             }
2984         }
2985     }
2986   /* Handle loading a large integer during reload */
2987   else if (GET_CODE (operands[1]) == CONST_INT
2988            && ! const_ok_for_arm (INTVAL (operands[1]))
2989            && ! const_ok_for_arm (~INTVAL (operands[1])))
2990     {
2991       /* Writing a constant to memory needs a scratch, which should
2992          be handled with SECONDARY_RELOADs.  */
2993       if (GET_CODE (operands[0]) != REG)
2994         abort ();
2996       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
2997       emit_insn (gen_movsi (operands[0], operands[1]));
2998       DONE;
2999     }
3003 (define_insn "rotated_loadsi"
3004   [(set (match_operand:SI 0 "s_register_operand" "=r")
3005         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
3006                    (const_int 16)))]
3007   "! TARGET_SHORT_BY_BYTES"
3008   "*
3010   rtx ops[2];
3012   ops[0] = operands[0];
3013   ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
3014   output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
3015   return \"\";
3017 [(set_attr "type" "load")])
3019 (define_expand "movhi_bytes"
3020   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3021    (set (match_dup 3)
3022         (zero_extend:SI (match_dup 6)))
3023    (set (match_operand:SI 0 "" "")
3024          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
3025   ""
3026   "
3028   rtx mem1, mem2;
3029   rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3031   mem1 = gen_rtx_MEM (QImode, addr);
3032   MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3033   RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
3034   mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3035   MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3036   RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
3037   operands[0] = gen_lowpart (SImode, operands[0]);
3038   operands[1] = mem1;
3039   operands[2] = gen_reg_rtx (SImode);
3040   operands[3] = gen_reg_rtx (SImode);
3041   operands[6] = mem2;
3043   if (BYTES_BIG_ENDIAN)
3044     {
3045       operands[4] = operands[2];
3046       operands[5] = operands[3];
3047     }
3048   else
3049     {
3050       operands[4] = operands[3];
3051       operands[5] = operands[2];
3052     }
3056 (define_expand "movhi_bigend"
3057   [(set (match_dup 2)
3058         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
3059                    (const_int 16)))
3060    (set (match_dup 3)
3061         (ashiftrt:SI (match_dup 2) (const_int 16)))
3062    (set (match_operand:HI 0 "s_register_operand" "")
3063         (subreg:HI (match_dup 3) 0))]
3064   ""
3065   "
3066   operands[2] = gen_reg_rtx (SImode);
3067   operands[3] = gen_reg_rtx (SImode);
3070 ;; Pattern to recognise insn generated default case above
3072 (define_insn "*movhi_insn_arch4"
3073   [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
3074         (match_operand:HI 1 "general_operand"  "rI,K,m,r"))]
3075   "arm_arch4
3076    && (GET_CODE (operands[1]) != CONST_INT
3077        || const_ok_for_arm (INTVAL (operands[1]))
3078        || const_ok_for_arm (~INTVAL (operands[1])))"
3079   "@
3080    mov%?\\t%0, %1\\t%@ movhi
3081    mvn%?\\t%0, #%B1\\t%@ movhi
3082    ldr%?h\\t%0, %1\\t%@ movhi
3083    str%?h\\t%1, %0\\t%@ movhi"
3084 [(set_attr "type" "*,*,load,store1")])
3086 (define_insn "*movhi_insn_littleend"
3087   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3088         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
3089   "! arm_arch4
3090    && ! BYTES_BIG_ENDIAN
3091    && ! TARGET_SHORT_BY_BYTES
3092    && (GET_CODE (operands[1]) != CONST_INT
3093        || const_ok_for_arm (INTVAL (operands[1]))
3094        || const_ok_for_arm (~INTVAL (operands[1])))"
3095   "@
3096    mov%?\\t%0, %1\\t%@ movhi
3097    mvn%?\\t%0, #%B1\\t%@ movhi
3098    ldr%?\\t%0, %1\\t%@ movhi"
3099 [(set_attr "type" "*,*,load")])
3101 (define_insn "*movhi_insn_bigend"
3102   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3103         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
3104   "! arm_arch4
3105    && BYTES_BIG_ENDIAN
3106    && ! TARGET_SHORT_BY_BYTES
3107    && (GET_CODE (operands[1]) != CONST_INT
3108        || const_ok_for_arm (INTVAL (operands[1]))
3109        || const_ok_for_arm (~INTVAL (operands[1])))"
3110   "@
3111    mov%?\\t%0, %1\\t%@ movhi
3112    mvn%?\\t%0, #%B1\\t%@ movhi
3113    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
3114 [(set_attr "type" "*,*,load")
3115  (set_attr "length" "4,4,8")])
3117 (define_insn "*loadhi_si_bigend"
3118   [(set (match_operand:SI 0 "s_register_operand" "=r")
3119         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
3120                    (const_int 16)))]
3121   "BYTES_BIG_ENDIAN
3122    && ! TARGET_SHORT_BY_BYTES"
3123   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
3124 [(set_attr "type" "load")])
3126 (define_insn "*movhi_bytes"
3127   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
3128         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
3129   "TARGET_SHORT_BY_BYTES"
3130   "@
3131    mov%?\\t%0, %1\\t%@ movhi
3132    mvn%?\\t%0, #%B1\\t%@ movhi")
3135 (define_expand "reload_outhi"
3136   [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
3137               (match_operand:HI 1 "s_register_operand" "r")
3138               (match_operand:SI 2 "s_register_operand" "=&r")])]
3139   ""
3140   "
3141   arm_reload_out_hi (operands);
3142   DONE;
3145 (define_expand "reload_inhi"
3146   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
3147               (match_operand:HI 1 "reload_memory_operand" "o")
3148               (match_operand:SI 2 "s_register_operand" "=&r")])]
3149   "TARGET_SHORT_BY_BYTES"
3150   "
3151   arm_reload_in_hi (operands);
3152   DONE;
3155 (define_expand "movqi"
3156   [(set (match_operand:QI 0 "general_operand" "")
3157         (match_operand:QI 1 "general_operand" ""))]
3158   ""
3159   "
3160   /* Everything except mem = const or mem = mem can be done easily */
3162   if (!(reload_in_progress || reload_completed))
3163     {
3164       if (GET_CODE (operands[1]) == CONST_INT)
3165         {
3166           rtx reg = gen_reg_rtx (SImode);
3168           emit_insn (gen_movsi (reg, operands[1]));
3169           operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
3170         }
3171       if (GET_CODE (operands[0]) == MEM)
3172         operands[1] = force_reg (QImode, operands[1]);
3173     }
3177 (define_insn "*movqi_insn"
3178   [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
3179         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
3180   "register_operand (operands[0], QImode)
3181    || register_operand (operands[1], QImode)"
3182   "@
3183    mov%?\\t%0, %1
3184    mvn%?\\t%0, #%B1
3185    ldr%?b\\t%0, %1
3186    str%?b\\t%1, %0"
3187 [(set_attr "type" "*,*,load,store1")])
3189 (define_expand "movsf"
3190   [(set (match_operand:SF 0 "general_operand" "")
3191         (match_operand:SF 1 "general_operand" ""))]
3192   ""
3193   "
3194   if (GET_CODE (operands[0]) == MEM)
3195     operands[1] = force_reg (SFmode, operands[1]);
3198 (define_insn "*movsf_hard_insn"
3199   [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
3200         (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
3201   "TARGET_HARD_FLOAT
3202    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3203   "@
3204    mvf%?s\\t%0, %1
3205    mnf%?s\\t%0, #%N1
3206    ldf%?s\\t%0, %1
3207    stf%?s\\t%1, %0
3208    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
3209    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
3210    mov%?\\t%0, %1
3211    ldr%?\\t%0, %1\\t%@ float
3212    str%?\\t%1, %0\\t%@ float"
3213 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
3214  (set_attr "type"
3215          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
3217 ;; Exactly the same as above, except that all `f' cases are deleted.
3218 ;; This is necessary to prevent reload from ever trying to use a `f' reg
3219 ;; when -msoft-float.
3221 (define_insn "*movsf_soft_insn"
3222   [(set (match_operand:SF 0 "general_operand" "=r,r,m")
3223         (match_operand:SF 1 "general_operand" "r,mE,r"))]
3224   "TARGET_SOFT_FLOAT
3225    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3226   "@
3227    mov%?\\t%0, %1
3228    ldr%?\\t%0, %1\\t%@ float
3229    str%?\\t%1, %0\\t%@ float"
3230 [(set_attr "length" "4,4,4")
3231  (set_attr "type" "*,load,store1")])
3233 (define_expand "movdf"
3234   [(set (match_operand:DF 0 "general_operand" "")
3235         (match_operand:DF 1 "general_operand" ""))]
3236   ""
3237   "
3238   if (GET_CODE (operands[0]) == MEM)
3239     operands[1] = force_reg (DFmode, operands[1]);
3242 ;; Reloading a df mode value stored in integer regs to memory can require a
3243 ;; scratch reg.
3244 (define_expand "reload_outdf"
3245   [(match_operand:DF 0 "reload_memory_operand" "=o")
3246    (match_operand:DF 1 "s_register_operand" "r")
3247    (match_operand:SI 2 "s_register_operand" "=&r")]
3248   ""
3249   "
3251   enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
3253   if (code == REG)
3254     operands[2] = XEXP (operands[0], 0);
3255   else if (code == POST_INC || code == PRE_DEC)
3256     {
3257       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
3258       operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
3259       emit_insn (gen_movdi (operands[0], operands[1]));
3260       DONE;
3261     }
3262   else if (code == PRE_INC)
3263     {
3264       rtx reg = XEXP (XEXP (operands[0], 0), 0);
3265       emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
3266       operands[2] = reg;
3267     }
3268   else if (code == POST_DEC)
3269     operands[2] = XEXP (XEXP (operands[0], 0), 0);
3270   else
3271     emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
3272                            XEXP (XEXP (operands[0], 0), 1)));
3274   emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
3275                                     operands[1]));
3277   if (code == POST_DEC)
3278     emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
3280   DONE;
3284 (define_insn "*movdf_hard_insn"
3285   [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
3286         (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
3287   "TARGET_HARD_FLOAT
3288    && (GET_CODE (operands[0]) != MEM
3289        || register_operand (operands[1], DFmode))"
3290   "*
3292   rtx ops[3];
3294   switch (which_alternative)
3295     {
3296     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3297     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3298     case 2: case 3: case 4: return output_move_double (operands);
3299     case 5: return \"mvf%?d\\t%0, %1\";
3300     case 6: return \"mnf%?d\\t%0, #%N1\";
3301     case 7: return \"ldf%?d\\t%0, %1\";
3302     case 8: return \"stf%?d\\t%1, %0\";
3303     case 9: return output_mov_double_fpu_from_arm (operands);
3304     case 10: return output_mov_double_arm_from_fpu (operands);
3305     }
3308 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3309  (set_attr "type"
3310 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
3312 ;; Software floating point version.  This is essentially the same as movdi.
3313 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
3314 ;; an `f' reg.
3316 (define_insn "*movdf_soft_insn"
3317   [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3318         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3319   "TARGET_SOFT_FLOAT"
3320   "* return output_move_double (operands);"
3321 [(set_attr "length" "8,8,8")
3322  (set_attr "type" "*,load,store2")])
3324 (define_expand "movxf"
3325   [(set (match_operand:XF 0 "general_operand" "")
3326         (match_operand:XF 1 "general_operand" ""))]
3327   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3328   "")
3330 ;; Even when the XFmode patterns aren't enabled, we enable this after
3331 ;; reloading so that we can push floating point registers in the prologue.
3333 (define_insn "*movxf_hard_insn"
3334   [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3335         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3336   "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3337   "*
3338   switch (which_alternative)
3339     {
3340     case 0: return \"mvf%?e\\t%0, %1\";
3341     case 1: return \"mnf%?e\\t%0, #%N1\";
3342     case 2: return \"ldf%?e\\t%0, %1\";
3343     case 3: return \"stf%?e\\t%1, %0\";
3344     case 4: return output_mov_long_double_fpu_from_arm (operands);
3345     case 5: return output_mov_long_double_arm_from_fpu (operands);
3346     case 6: return output_mov_long_double_arm_from_arm (operands);
3347     }
3349 [(set_attr "length" "4,4,4,4,8,8,12")
3350  (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
3353 ;; load- and store-multiple insns
3354 ;; The arm can load/store any set of registers, provided that they are in
3355 ;; ascending order; but that is beyond GCC so stick with what it knows.
3357 (define_expand "load_multiple"
3358   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3359                           (match_operand:SI 1 "" ""))
3360                      (use (match_operand:SI 2 "" ""))])]
3361   ""
3362   "
3363   /* Support only fixed point registers */
3364   if (GET_CODE (operands[2]) != CONST_INT
3365       || INTVAL (operands[2]) > 14
3366       || INTVAL (operands[2]) < 2
3367       || GET_CODE (operands[1]) != MEM
3368       || GET_CODE (operands[0]) != REG
3369       || REGNO (operands[0]) > 14
3370       || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
3371     FAIL;
3373   operands[3]
3374     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
3375                              force_reg (SImode, XEXP (operands[1], 0)),
3376                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
3377                              MEM_IN_STRUCT_P(operands[1]),
3378                              MEM_SCALAR_P (operands[1]));
3381 ;; Load multiple with write-back
3383 (define_insn "*ldmsi_postinc"
3384   [(match_parallel 0 "load_multiple_operation"
3385     [(set (match_operand:SI 1 "s_register_operand" "+r")
3386           (plus:SI (match_dup 1)
3387                    (match_operand:SI 2 "const_int_operand" "n")))
3388      (set (match_operand:SI 3 "s_register_operand" "=r")
3389           (mem:SI (match_dup 1)))])]
3390   "(INTVAL (operands[2])  == 4 * (XVECLEN (operands[0], 0) - 2))"
3391   "*
3393   rtx ops[3];
3394   int count = XVECLEN (operands[0], 0);
3396   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3397   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
3398   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
3400   output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
3401   return \"\";
3404 [(set_attr "type" "load")])
3406 ;; Ordinary load multiple
3408 (define_insn "*ldmsi"
3409   [(match_parallel 0 "load_multiple_operation"
3410     [(set (match_operand:SI 1 "s_register_operand" "=r")
3411           (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3412   ""
3413   "*
3415   rtx ops[3];
3416   int count = XVECLEN (operands[0], 0);
3418   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3419   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3420   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3422   output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3423   return \"\";
3426 [(set_attr "type" "load")])
3428 (define_expand "store_multiple"
3429   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3430                           (match_operand:SI 1 "" ""))
3431                      (use (match_operand:SI 2 "" ""))])]
3432   ""
3433   "
3434   /* Support only fixed point registers */
3435   if (GET_CODE (operands[2]) != CONST_INT
3436       || INTVAL (operands[2]) > 14
3437       || INTVAL (operands[2]) < 2
3438       || GET_CODE (operands[1]) != REG
3439       || GET_CODE (operands[0]) != MEM
3440       || REGNO (operands[1]) > 14
3441       || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3442     FAIL;
3444   operands[3]
3445     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3446                               force_reg (SImode, XEXP (operands[0], 0)),
3447                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
3448                               MEM_IN_STRUCT_P(operands[0]), 
3449                               MEM_SCALAR_P (operands[0]));
3452 ;; Store multiple with write-back
3454 (define_insn "*stmsi_postinc"
3455   [(match_parallel 0 "store_multiple_operation"
3456     [(set (match_operand:SI 1 "s_register_operand" "+r")
3457           (plus:SI (match_dup 1)
3458                    (match_operand:SI 2 "const_int_operand" "n")))
3459      (set (mem:SI (match_dup 1))
3460           (match_operand:SI 3 "s_register_operand" "r"))])]
3461   "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3462   "*
3464   rtx ops[3];
3465   int count = XVECLEN (operands[0], 0);
3467   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3468   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3469   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3471   output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3472   return \"\";
3475 [(set (attr "type")
3476       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3477                 (const_string "store2")
3478              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3479                 (const_string "store3")]
3480           (const_string "store4")))])
3482 ;; Ordinary store multiple
3484 (define_insn "*stmsi"
3485   [(match_parallel 0 "store_multiple_operation"
3486     [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3487           (match_operand:SI 1 "s_register_operand" "r"))])]
3488   ""
3489   "*
3491   rtx ops[3];
3492   int count = XVECLEN (operands[0], 0);
3494   ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3495   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3496   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3498   output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3499   return \"\";
3502 [(set (attr "type")
3503       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3504                 (const_string "store2")
3505              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3506                 (const_string "store3")]
3507           (const_string "store4")))])
3509 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
3510 ;; We could let this apply for blocks of less than this, but it clobbers so
3511 ;; many registers that there is then probably a better way.
3513 (define_expand "movstrqi"
3514   [(match_operand:BLK 0 "general_operand" "")
3515    (match_operand:BLK 1 "general_operand" "")
3516    (match_operand:SI 2 "const_int_operand" "")
3517    (match_operand:SI 3 "const_int_operand" "")]
3518   ""
3519   "
3520   if (arm_gen_movstrqi (operands))
3521     DONE;
3522   FAIL;
3526 ;; Comparison and test insns
3528 (define_expand "cmpsi"
3529   [(match_operand:SI 0 "s_register_operand" "")
3530    (match_operand:SI 1 "arm_add_operand" "")]
3531   ""
3532   "
3534   arm_compare_op0 = operands[0];
3535   arm_compare_op1 = operands[1];
3536   arm_compare_fp = 0;
3537   DONE;
3541 (define_expand "cmpsf"
3542   [(match_operand:SF 0 "s_register_operand" "")
3543    (match_operand:SF 1 "fpu_rhs_operand" "")]
3544   "TARGET_HARD_FLOAT"
3545   "
3547   arm_compare_op0 = operands[0];
3548   arm_compare_op1 = operands[1];
3549   arm_compare_fp = 1;
3550   DONE;
3554 (define_expand "cmpdf"
3555   [(match_operand:DF 0 "s_register_operand" "")
3556    (match_operand:DF 1 "fpu_rhs_operand" "")]
3557   "TARGET_HARD_FLOAT"
3558   "
3560   arm_compare_op0 = operands[0];
3561   arm_compare_op1 = operands[1];
3562   arm_compare_fp = 1;
3563   DONE;
3567 (define_expand "cmpxf"
3568   [(match_operand:XF 0 "s_register_operand" "")
3569    (match_operand:XF 1 "fpu_rhs_operand" "")]
3570   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3571   "
3573   arm_compare_op0 = operands[0];
3574   arm_compare_op1 = operands[1];
3575   arm_compare_fp = 1;
3576   DONE;
3580 (define_insn "*cmpsi_insn"
3581   [(set (reg:CC 24)
3582         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3583                     (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3584   ""
3585   "@
3586    cmp%?\\t%0, %1
3587    cmn%?\\t%0, #%n1"
3588 [(set_attr "conds" "set")])
3590 (define_insn "*cmpsi_shiftsi"
3591   [(set (reg:CC 24)
3592         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3593                     (match_operator:SI 3 "shift_operator"
3594                      [(match_operand:SI 1 "s_register_operand" "r")
3595                       (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3596   ""
3597   "cmp%?\\t%0, %1%S3"
3598 [(set_attr "conds" "set")])
3600 (define_insn "*cmpsi_shiftsi_swp"
3601   [(set (reg:CC_SWP 24)
3602         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3603                          [(match_operand:SI 1 "s_register_operand" "r")
3604                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
3605                         (match_operand:SI 0 "s_register_operand" "r")))]
3606   ""
3607   "cmp%?\\t%0, %1%S3"
3608 [(set_attr "conds" "set")])
3610 (define_insn "*cmpsi_neg_shiftsi"
3611   [(set (reg:CC 24)
3612         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3613                     (neg:SI (match_operator:SI 3 "shift_operator"
3614                              [(match_operand:SI 1 "s_register_operand" "r")
3615                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3616   ""
3617   "cmn%?\\t%0, %1%S3"
3618 [(set_attr "conds" "set")])
3620 (define_insn "*cmpsf_insn"
3621   [(set (reg:CCFP 24)
3622         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3623                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3624   "TARGET_HARD_FLOAT"
3625   "@
3626    cmf%?\\t%0, %1
3627    cnf%?\\t%0, #%N1"
3628 [(set_attr "conds" "set")
3629  (set_attr "type" "f_2_r")])
3631 (define_insn "*cmpdf_insn"
3632   [(set (reg:CCFP 24)
3633         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3634                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3635   "TARGET_HARD_FLOAT"
3636   "@
3637    cmf%?\\t%0, %1
3638    cnf%?\\t%0, #%N1"
3639 [(set_attr "conds" "set")
3640  (set_attr "type" "f_2_r")])
3642 (define_insn "*cmpesfdf_df"
3643   [(set (reg:CCFP 24)
3644         (compare:CCFP (float_extend:DF
3645                        (match_operand:SF 0 "s_register_operand" "f,f"))
3646                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3647   "TARGET_HARD_FLOAT"
3648   "@
3649    cmf%?\\t%0, %1
3650    cnf%?\\t%0, #%N1"
3651 [(set_attr "conds" "set")
3652  (set_attr "type" "f_2_r")])
3654 (define_insn "*cmpdf_esfdf"
3655   [(set (reg:CCFP 24)
3656         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3657                       (float_extend:DF
3658                        (match_operand:SF 1 "s_register_operand" "f"))))]
3659   "TARGET_HARD_FLOAT"
3660   "cmf%?\\t%0, %1"
3661 [(set_attr "conds" "set")
3662  (set_attr "type" "f_2_r")])
3664 (define_insn "*cmpxf_insn"
3665   [(set (reg:CCFP 24)
3666         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3667                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3668   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3669   "@
3670    cmf%?\\t%0, %1
3671    cnf%?\\t%0, #%N1"
3672 [(set_attr "conds" "set")
3673  (set_attr "type" "f_2_r")])
3675 (define_insn "*cmpsf_trap"
3676   [(set (reg:CCFPE 24)
3677         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3678                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3679   "TARGET_HARD_FLOAT"
3680   "@
3681    cmf%?e\\t%0, %1
3682    cnf%?e\\t%0, #%N1"
3683 [(set_attr "conds" "set")
3684  (set_attr "type" "f_2_r")])
3686 (define_insn "*cmpdf_trap"
3687   [(set (reg:CCFPE 24)
3688         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3689                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3690   "TARGET_HARD_FLOAT"
3691   "@
3692    cmf%?e\\t%0, %1
3693    cnf%?e\\t%0, #%N1"
3694 [(set_attr "conds" "set")
3695  (set_attr "type" "f_2_r")])
3697 (define_insn "*cmp_esfdf_df_trap"
3698   [(set (reg:CCFPE 24)
3699         (compare:CCFPE (float_extend:DF
3700                         (match_operand:SF 0 "s_register_operand" "f,f"))
3701                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3702   "TARGET_HARD_FLOAT"
3703   "@
3704    cmf%?e\\t%0, %1
3705    cnf%?e\\t%0, #%N1"
3706 [(set_attr "conds" "set")
3707  (set_attr "type" "f_2_r")])
3709 (define_insn "*cmp_df_esfdf_trap"
3710   [(set (reg:CCFPE 24)
3711         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3712                        (float_extend:DF
3713                         (match_operand:SF 1 "s_register_operand" "f"))))]
3714   "TARGET_HARD_FLOAT"
3715   "cmf%?e\\t%0, %1"
3716 [(set_attr "conds" "set")
3717  (set_attr "type" "f_2_r")])
3719 (define_insn "*cmpxf_trap"
3720   [(set (reg:CCFPE 24)
3721         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3722                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3723   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3724   "@
3725    cmf%?e\\t%0, %1
3726    cnf%?e\\t%0, #%N1"
3727 [(set_attr "conds" "set")
3728  (set_attr "type" "f_2_r")])
3730 ; This insn allows redundant compares to be removed by cse, nothing should
3731 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3732 ; is deleted later on. The match_dup will match the mode here, so that
3733 ; mode changes of the condition codes aren't lost by this even though we don't
3734 ; specify what they are.
3736 (define_insn "*deleted_compare"
3737   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3738   ""
3739   "\\t%@ deleted compare"
3740 [(set_attr "conds" "set")
3741  (set_attr "length" "0")])
3744 ;; Conditional branch insns
3746 (define_expand "beq"
3747   [(set (pc)
3748         (if_then_else (eq (match_dup 1) (const_int 0))
3749                       (label_ref (match_operand 0 "" ""))
3750                       (pc)))]
3751   ""
3752   "
3754   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3755                                  arm_compare_fp);
3759 (define_expand "bne"
3760   [(set (pc)
3761         (if_then_else (ne (match_dup 1) (const_int 0))
3762                       (label_ref (match_operand 0 "" ""))
3763                       (pc)))]
3764   ""
3765   "
3767   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3768                                  arm_compare_fp);
3772 (define_expand "bgt"
3773   [(set (pc)
3774         (if_then_else (gt (match_dup 1) (const_int 0))
3775                       (label_ref (match_operand 0 "" ""))
3776                       (pc)))]
3777   ""
3778   "
3780   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3781                                  arm_compare_fp);
3785 (define_expand "ble"
3786   [(set (pc)
3787         (if_then_else (le (match_dup 1) (const_int 0))
3788                       (label_ref (match_operand 0 "" ""))
3789                       (pc)))]
3790   ""
3791   "
3793   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3794                                  arm_compare_fp);
3798 (define_expand "bge"
3799   [(set (pc)
3800         (if_then_else (ge (match_dup 1) (const_int 0))
3801                       (label_ref (match_operand 0 "" ""))
3802                       (pc)))]
3803   ""
3804   "
3806   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3807                                  arm_compare_fp);
3811 (define_expand "blt"
3812   [(set (pc)
3813         (if_then_else (lt (match_dup 1) (const_int 0))
3814                       (label_ref (match_operand 0 "" ""))
3815                       (pc)))]
3816   ""
3817   "
3819   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3820                                  arm_compare_fp);
3824 (define_expand "bgtu"
3825   [(set (pc)
3826         (if_then_else (gtu (match_dup 1) (const_int 0))
3827                       (label_ref (match_operand 0 "" ""))
3828                       (pc)))]
3829   ""
3830   "
3832   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3833                                  arm_compare_fp);
3837 (define_expand "bleu"
3838   [(set (pc)
3839         (if_then_else (leu (match_dup 1) (const_int 0))
3840                       (label_ref (match_operand 0 "" ""))
3841                       (pc)))]
3842   ""
3843   "
3845   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3846                                  arm_compare_fp);
3850 (define_expand "bgeu"
3851   [(set (pc)
3852         (if_then_else (geu (match_dup 1) (const_int 0))
3853                       (label_ref (match_operand 0 "" ""))
3854                       (pc)))]
3855   ""
3856   "
3858   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3859                                  arm_compare_fp);
3863 (define_expand "bltu"
3864   [(set (pc)
3865         (if_then_else (ltu (match_dup 1) (const_int 0))
3866                       (label_ref (match_operand 0 "" ""))
3867                       (pc)))]
3868   ""
3869   "
3871   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3872                                  arm_compare_fp);
3876 ;; patterns to match conditional branch insns
3878 (define_insn "*condbranch"
3879   [(set (pc)
3880         (if_then_else (match_operator 1 "comparison_operator"
3881                        [(match_operand 2 "cc_register" "") (const_int 0)])
3882                       (label_ref (match_operand 0 "" ""))
3883                       (pc)))]
3884   ""
3885   "*
3887   extern int arm_ccfsm_state;
3889   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3890   {
3891     arm_ccfsm_state += 2;
3892     return \"\";
3893   }
3894   return \"b%d1\\t%l0\";
3896 [(set_attr "conds" "use")])
3898 (define_insn "*condbranch_reversed"
3899   [(set (pc)
3900         (if_then_else (match_operator 1 "comparison_operator"
3901                        [(match_operand 2 "cc_register" "") (const_int 0)])
3902                       (pc)
3903                       (label_ref (match_operand 0 "" ""))))]
3904   ""
3905   "*
3907   extern int arm_ccfsm_state;
3909   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3910   {
3911     arm_ccfsm_state += 2;
3912     return \"\";
3913   }
3914   return \"b%D1\\t%l0\";
3916 [(set_attr "conds" "use")])
3919 ; scc insns
3921 (define_expand "seq"
3922   [(set (match_operand:SI 0 "s_register_operand" "=r")
3923         (eq:SI (match_dup 1) (const_int 0)))]
3924   ""
3925   "
3927   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3928                                  arm_compare_fp);
3932 (define_expand "sne"
3933   [(set (match_operand:SI 0 "s_register_operand" "=r")
3934         (ne:SI (match_dup 1) (const_int 0)))]
3935   ""
3936   "
3938   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3939                                  arm_compare_fp);
3943 (define_expand "sgt"
3944   [(set (match_operand:SI 0 "s_register_operand" "=r")
3945         (gt:SI (match_dup 1) (const_int 0)))]
3946   ""
3947   "
3949   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3950                                  arm_compare_fp);
3954 (define_expand "sle"
3955   [(set (match_operand:SI 0 "s_register_operand" "=r")
3956         (le:SI (match_dup 1) (const_int 0)))]
3957   ""
3958   "
3960   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3961                                  arm_compare_fp);
3965 (define_expand "sge"
3966   [(set (match_operand:SI 0 "s_register_operand" "=r")
3967         (ge:SI (match_dup 1) (const_int 0)))]
3968   ""
3969   "
3971   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3972                                  arm_compare_fp);
3976 (define_expand "slt"
3977   [(set (match_operand:SI 0 "s_register_operand" "=r")
3978         (lt:SI (match_dup 1) (const_int 0)))]
3979   ""
3980   "
3982   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3983                                  arm_compare_fp);
3987 (define_expand "sgtu"
3988   [(set (match_operand:SI 0 "s_register_operand" "=r")
3989         (gtu:SI (match_dup 1) (const_int 0)))]
3990   ""
3991   "
3993   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3994                                  arm_compare_fp);
3998 (define_expand "sleu"
3999   [(set (match_operand:SI 0 "s_register_operand" "=r")
4000         (leu:SI (match_dup 1) (const_int 0)))]
4001   ""
4002   "
4004   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
4005                                  arm_compare_fp);
4009 (define_expand "sgeu"
4010   [(set (match_operand:SI 0 "s_register_operand" "=r")
4011         (geu:SI (match_dup 1) (const_int 0)))]
4012   ""
4013   "
4015   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
4016                                  arm_compare_fp);
4020 (define_expand "sltu"
4021   [(set (match_operand:SI 0 "s_register_operand" "=r")
4022         (ltu:SI (match_dup 1) (const_int 0)))]
4023   ""
4024   "
4026   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
4027                                  arm_compare_fp);
4031 (define_insn "*mov_scc"
4032   [(set (match_operand:SI 0 "s_register_operand" "=r")
4033         (match_operator:SI 1 "comparison_operator"
4034          [(match_operand 2 "cc_register" "") (const_int 0)]))]
4035   ""
4036   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
4037 [(set_attr "conds" "use")
4038  (set_attr "length" "8")])
4040 (define_insn "*mov_negscc"
4041   [(set (match_operand:SI 0 "s_register_operand" "=r")
4042         (neg:SI (match_operator:SI 1 "comparison_operator"
4043                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
4044   ""
4045   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
4046 [(set_attr "conds" "use")
4047  (set_attr "length" "8")])
4049 (define_insn "*mov_notscc"
4050   [(set (match_operand:SI 0 "s_register_operand" "=r")
4051         (not:SI (match_operator:SI 1 "comparison_operator"
4052                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
4053   ""
4054   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
4055 [(set_attr "conds" "use")
4056  (set_attr "length" "8")])
4059 ;; Conditional move insns
4061 (define_expand "movsicc"
4062   [(set (match_operand:SI 0 "s_register_operand" "")
4063         (if_then_else:SI (match_operand 1 "comparison_operator" "")
4064                          (match_operand:SI 2 "arm_not_operand" "")
4065                          (match_operand:SI 3 "arm_not_operand" "")))]
4066   ""
4067   "
4069   enum rtx_code code = GET_CODE (operands[1]);
4070   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4071                                arm_compare_fp);
4073   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4076 (define_expand "movsfcc"
4077   [(set (match_operand:SF 0 "s_register_operand" "")
4078         (if_then_else:SF (match_operand 1 "comparison_operator" "")
4079                          (match_operand:SF 2 "s_register_operand" "")
4080                          (match_operand:SF 3 "nonmemory_operand" "")))]
4081   ""
4082   "
4084   enum rtx_code code = GET_CODE (operands[1]);
4085   rtx ccreg;
4087   /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
4088      Otherwise, ensure it is a valid FP add operand */
4089   if ((! TARGET_HARD_FLOAT)
4090       || (! fpu_add_operand (operands[3], SFmode)))
4091     operands[3] = force_reg (SFmode, operands[3]);
4093   ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4094                            arm_compare_fp);
4096   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4099 (define_expand "movdfcc"
4100   [(set (match_operand:DF 0 "s_register_operand" "")
4101         (if_then_else:DF (match_operand 1 "comparison_operator" "")
4102                          (match_operand:DF 2 "s_register_operand" "")
4103                          (match_operand:DF 3 "fpu_add_operand" "")))]
4104   "TARGET_HARD_FLOAT"
4105   "
4107   enum rtx_code code = GET_CODE (operands[1]);
4108   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4109                                arm_compare_fp);
4111   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4114 (define_insn "*movsicc_insn"
4115   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
4116         (if_then_else:SI
4117          (match_operator 3 "comparison_operator"
4118           [(match_operand 4 "cc_register" "") (const_int 0)])
4119          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
4120          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
4121   ""
4122   "@
4123    mov%D3\\t%0, %2
4124    mvn%D3\\t%0, #%B2
4125    mov%d3\\t%0, %1
4126    mvn%d3\\t%0, #%B1
4127    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
4128    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
4129    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
4130    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
4131   [(set_attr "length" "4,4,4,4,8,8,8,8")
4132    (set_attr "conds" "use")])
4134 (define_insn "*movsfcc_hard_insn"
4135   [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4136         (if_then_else:SF
4137          (match_operator 3 "comparison_operator" 
4138           [(match_operand 4 "cc_register" "") (const_int 0)])
4139          (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4140          (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4141   "TARGET_HARD_FLOAT"
4142   "@
4143    mvf%D3s\\t%0, %2
4144    mnf%D3s\\t%0, #%N2
4145    mvf%d3s\\t%0, %1
4146    mnf%d3s\\t%0, #%N1
4147    mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
4148    mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
4149    mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
4150    mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
4151   [(set_attr "length" "4,4,4,4,8,8,8,8")
4152    (set_attr "type" "ffarith")
4153    (set_attr "conds" "use")])
4155 (define_insn "*movsfcc_soft_insn"
4156   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
4157         (if_then_else:SF (match_operator 3 "comparison_operator"
4158                           [(match_operand 4 "cc_register" "") (const_int 0)])
4159                          (match_operand:SF 1 "s_register_operand" "0,r")
4160                          (match_operand:SF 2 "s_register_operand" "r,0")))]
4161   "TARGET_SOFT_FLOAT"
4162   "@
4163    mov%D3\\t%0, %2
4164    mov%d3\\t%0, %1"
4165   [(set_attr "conds" "use")])
4167 (define_insn "*movdfcc_insn"
4168   [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4169         (if_then_else:DF
4170          (match_operator 3 "comparison_operator"
4171           [(match_operand 4 "cc_register" "") (const_int 0)])
4172          (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4173          (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4174   "TARGET_HARD_FLOAT"
4175   "@
4176    mvf%D3d\\t%0, %2
4177    mnf%D3d\\t%0, #%N2
4178    mvf%d3d\\t%0, %1
4179    mnf%d3d\\t%0, #%N1
4180    mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
4181    mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
4182    mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
4183    mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
4184   [(set_attr "length" "4,4,4,4,8,8,8,8")
4185    (set_attr "type" "ffarith")
4186    (set_attr "conds" "use")])
4188 ;; Jump and linkage insns
4190 (define_insn "jump"
4191   [(set (pc)
4192         (label_ref (match_operand 0 "" "")))]
4193   ""
4194   "*
4196   extern int arm_ccfsm_state;
4198   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4199     {
4200       arm_ccfsm_state += 2;
4201       return \"\";
4202     }
4203   return \"b%?\\t%l0\";
4206 (define_expand "call"
4207   [(parallel [(call (match_operand 0 "memory_operand" "")
4208                     (match_operand 1 "general_operand" ""))
4209               (clobber (reg:SI 14))])]
4210   ""
4211   "")
4213 (define_insn "*call_reg"
4214   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
4215          (match_operand 1 "" "g"))
4216    (clobber (reg:SI 14))]
4217   ""
4218   "*
4219   return output_call (operands);
4221 ;; length is worst case, normally it is only two
4222 [(set_attr "length" "12")
4223  (set_attr "type" "call")])
4225 (define_insn "*call_mem"
4226   [(call (mem:SI (match_operand 0 "memory_operand" "m"))
4227          (match_operand 1 "general_operand" "g"))
4228    (clobber (reg:SI 14))]
4229   ""
4230   "*
4231   return output_call_mem (operands);
4233 [(set_attr "length" "12")
4234  (set_attr "type" "call")])
4236 (define_expand "call_value"
4237   [(parallel [(set (match_operand 0 "" "=rf")
4238                    (call (match_operand 1 "memory_operand" "m")
4239                          (match_operand 2 "general_operand" "g")))
4240               (clobber (reg:SI 14))])]
4241   ""
4242   "")
4244 (define_insn "*call_value_reg"
4245   [(set (match_operand 0 "" "=rf")
4246         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4247               (match_operand 2 "general_operand" "g")))
4248    (clobber (reg:SI 14))]
4249   ""
4250   "*
4251   return output_call (&operands[1]);
4253 [(set_attr "length" "12")
4254  (set_attr "type" "call")])
4256 (define_insn "*call_value_mem"
4257   [(set (match_operand 0 "" "=rf")
4258         (call (mem:SI (match_operand 1 "memory_operand" "m"))
4259         (match_operand 2 "general_operand" "g")))
4260    (clobber (reg:SI 14))]
4261   "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4262   "*
4263   return output_call_mem (&operands[1]);
4265 [(set_attr "length" "12")
4266  (set_attr "type" "call")])
4268 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4269 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4271 (define_insn "*call_symbol"
4272   [(call (mem:SI (match_operand:SI 0 "" "X"))
4273          (match_operand:SI 1 "general_operand" "g"))
4274    (clobber (reg:SI 14))]
4275   "GET_CODE (operands[0]) == SYMBOL_REF"
4276   "bl%?\\t%a0"
4277 [(set_attr "type" "call")])
4279 (define_insn "*call_value_symbol"
4280   [(set (match_operand 0 "s_register_operand" "=rf")
4281         (call (mem:SI (match_operand:SI 1 "" "X"))
4282         (match_operand:SI 2 "general_operand" "g")))
4283    (clobber (reg:SI 14))]
4284   "GET_CODE(operands[1]) == SYMBOL_REF"
4285   "bl%?\\t%a1"
4286 [(set_attr "type" "call")])
4288 ;; Often the return insn will be the same as loading from memory, so set attr
4289 (define_insn "return"
4290   [(return)]
4291   "USE_RETURN_INSN(FALSE)"
4292   "*
4294   extern int arm_ccfsm_state;
4296   if (arm_ccfsm_state == 2)
4297   {
4298     arm_ccfsm_state += 2;
4299     return \"\";
4300   }
4301   return output_return_instruction (NULL, TRUE, FALSE);
4303 [(set_attr "type" "load")])
4305 (define_insn "*cond_return"
4306   [(set (pc)
4307         (if_then_else (match_operator 0 "comparison_operator"
4308                        [(match_operand 1 "cc_register" "") (const_int 0)])
4309                       (return)
4310                       (pc)))]
4311   "USE_RETURN_INSN(TRUE)"
4312   "*
4314   extern int arm_ccfsm_state;
4316   if (arm_ccfsm_state == 2)
4317   {
4318     arm_ccfsm_state += 2;
4319     return \"\";
4320   }
4321   return output_return_instruction (operands[0], TRUE, FALSE);
4323 [(set_attr "conds" "use")
4324  (set_attr "type" "load")])
4326 (define_insn "*cond_return_inverted"
4327   [(set (pc)
4328         (if_then_else (match_operator 0 "comparison_operator"
4329                        [(match_operand 1 "cc_register" "") (const_int 0)])
4330                       (pc)
4331                       (return)))]
4332   "USE_RETURN_INSN(TRUE)"
4333   "*
4335   extern int arm_ccfsm_state;
4337   if (arm_ccfsm_state == 2)
4338   {
4339     arm_ccfsm_state += 2;
4340     return \"\";
4341   }
4342   return output_return_instruction (operands[0], TRUE, TRUE);
4344 [(set_attr "conds" "use")
4345  (set_attr "type" "load")])
4347 ;; Call subroutine returning any type.
4349 (define_expand "untyped_call"
4350   [(parallel [(call (match_operand 0 "" "")
4351                     (const_int 0))
4352               (match_operand 1 "" "")
4353               (match_operand 2 "" "")])]
4354   ""
4355   "
4357   int i;
4359   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4361   for (i = 0; i < XVECLEN (operands[2], 0); i++)
4362     {
4363       rtx set = XVECEXP (operands[2], 0, i);
4364       emit_move_insn (SET_DEST (set), SET_SRC (set));
4365     }
4367   /* The optimizer does not know that the call sets the function value
4368      registers we stored in the result block.  We avoid problems by
4369      claiming that all hard registers are used and clobbered at this
4370      point.  */
4371   emit_insn (gen_blockage ());
4373   DONE;
4376 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4377 ;; all of memory.  This blocks insns from being moved across this point.
4379 (define_insn "blockage"
4380   [(unspec_volatile [(const_int 0)] 0)]
4381   ""
4382   ""
4383 [(set_attr "length" "0")
4384  (set_attr "type" "block")])
4386 (define_expand "casesi"
4387   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
4388    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
4389    (match_operand:SI 2 "const_int_operand" "")  ; total range
4390    (match_operand:SI 3 "" "")                   ; table label
4391    (match_operand:SI 4 "" "")]                  ; Out of range label
4392   ""
4393   "
4395   rtx reg;
4396   if (operands[1] != const0_rtx)
4397     {
4398       reg = gen_reg_rtx (SImode);
4399       emit_insn (gen_addsi3 (reg, operands[0],
4400                              GEN_INT (-INTVAL (operands[1]))));
4401       operands[0] = reg;
4402     }
4404   if (! const_ok_for_arm (INTVAL (operands[2])))
4405     operands[2] = force_reg (SImode, operands[2]);
4407   emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4408                                        operands[4]));
4409   DONE;
4412 ;; The USE in this pattern is needed to tell flow analysis that this is
4413 ;; a CASESI insn.  It has no other purpose.
4414 (define_insn "casesi_internal"
4415   [(parallel [(set (pc)
4416                (if_then_else
4417                 (leu (match_operand:SI 0 "s_register_operand" "r")
4418                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
4419                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4420                                  (label_ref (match_operand 2 "" ""))))
4421                 (label_ref (match_operand 3 "" ""))))
4422               (use (label_ref (match_dup 2)))])]
4423   ""
4424   "*
4425   if (flag_pic)
4426     return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4427   return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4429 [(set_attr "conds" "clob")
4430  (set_attr "length" "12")])
4432 (define_insn "indirect_jump"
4433   [(set (pc)
4434         (match_operand:SI 0 "s_register_operand" "r"))]
4435   ""
4436   "mov%?\\t%|pc, %0\\t%@ indirect jump")
4438 (define_insn "*load_indirect_jump"
4439   [(set (pc)
4440         (match_operand:SI 0 "memory_operand" "m"))]
4441   ""
4442   "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4443 [(set_attr "type" "load")])
4445 ;; Misc insns
4447 (define_insn "nop"
4448   [(const_int 0)]
4449   ""
4450   "mov%?\\tr0, r0\\t%@ nop")
4452 ;; Patterns to allow combination of arithmetic, cond code and shifts
4454 (define_insn "*arith_shiftsi"
4455   [(set (match_operand:SI 0 "s_register_operand" "=r")
4456         (match_operator:SI 1 "shiftable_operator"
4457           [(match_operator:SI 3 "shift_operator"
4458              [(match_operand:SI 4 "s_register_operand" "r")
4459               (match_operand:SI 5 "reg_or_int_operand" "rI")])
4460            (match_operand:SI 2 "s_register_operand" "r")]))]
4461   ""
4462   "%i1%?\\t%0, %2, %4%S3")
4464 (define_insn "*arith_shiftsi_compare0"
4465   [(set (reg:CC_NOOV 24)
4466         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4467                           [(match_operator:SI 3 "shift_operator"
4468                             [(match_operand:SI 4 "s_register_operand" "r")
4469                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4470                            (match_operand:SI 2 "s_register_operand" "r")])
4471                          (const_int 0)))
4472    (set (match_operand:SI 0 "s_register_operand" "=r")
4473         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4474                          (match_dup 2)]))]
4475   ""
4476   "%i1%?s\\t%0, %2, %4%S3"
4477 [(set_attr "conds" "set")])
4479 (define_insn "*arith_shiftsi_compare0_scratch"
4480   [(set (reg:CC_NOOV 24)
4481         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4482                           [(match_operator:SI 3 "shift_operator"
4483                             [(match_operand:SI 4 "s_register_operand" "r")
4484                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4485                            (match_operand:SI 2 "s_register_operand" "r")])
4486                          (const_int 0)))
4487    (clobber (match_scratch:SI 0 "=r"))]
4488   ""
4489   "%i1%?s\\t%0, %2, %4%S3"
4490 [(set_attr "conds" "set")])
4492 (define_insn "*sub_shiftsi"
4493   [(set (match_operand:SI 0 "s_register_operand" "=r")
4494         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4495                   (match_operator:SI 2 "shift_operator"
4496                    [(match_operand:SI 3 "s_register_operand" "r")
4497                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4498   ""
4499   "sub%?\\t%0, %1, %3%S2")
4501 (define_insn "*sub_shiftsi_compare0"
4502   [(set (reg:CC_NOOV 24)
4503         (compare:CC_NOOV
4504          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4505                    (match_operator:SI 2 "shift_operator"
4506                     [(match_operand:SI 3 "s_register_operand" "r")
4507                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4508          (const_int 0)))
4509    (set (match_operand:SI 0 "s_register_operand" "=r")
4510         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4511                                                  (match_dup 4)])))]
4512   ""
4513   "sub%?s\\t%0, %1, %3%S2"
4514 [(set_attr "conds" "set")])
4516 (define_insn "*sub_shiftsi_compare0_scratch"
4517   [(set (reg:CC_NOOV 24)
4518         (compare:CC_NOOV
4519          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4520                    (match_operator:SI 2 "shift_operator"
4521                     [(match_operand:SI 3 "s_register_operand" "r")
4522                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4523          (const_int 0)))
4524    (clobber (match_scratch:SI 0 "=r"))]
4525   ""
4526   "sub%?s\\t%0, %1, %3%S2"
4527 [(set_attr "conds" "set")])
4529 ;; These variants of the above insns can occur if the first operand is the
4530 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
4531 ;; seem to be a way around it.  Most of the predicates have to be null
4532 ;; because the format can be generated part way through reload, so
4533 ;; if we don't match it as soon as it becomes available, reload doesn't know
4534 ;; how to reload pseudos that haven't got hard registers; the constraints will
4535 ;; sort everything out.
4537 (define_insn "*reload_mulsi3"
4538   [(set (match_operand:SI 0 "" "=&r")
4539         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4540                            [(match_operand:SI 3 "" "r")
4541                             (match_operand:SI 4 "" "rM")])
4542                           (match_operand:SI 2 "" "r"))
4543                  (match_operand:SI 1 "const_int_operand" "n")))]
4544   "reload_in_progress"
4545   "*
4546   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4547   operands[2] = operands[1];
4548   operands[1] = operands[0];
4549   return output_add_immediate (operands);
4551 ; we have no idea how long the add_immediate is, it could be up to 4.
4552 [(set_attr "length" "20")])
4554 (define_insn "*reload_mulsi_compare0"
4555   [(set (reg:CC_NOOV 24)
4556         (compare:CC_NOOV (plus:SI
4557                           (plus:SI 
4558                            (match_operator:SI 5 "shift_operator"
4559                             [(match_operand:SI 3 "" "r")
4560                              (match_operand:SI 4 "" "rM")])
4561                            (match_operand:SI 1 "" "r"))
4562                           (match_operand:SI 2 "const_int_operand" "n"))
4563                          (const_int 0)))
4564    (set (match_operand:SI 0 "" "=&r")
4565         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4566                           (match_dup 1))
4567                  (match_dup 2)))]
4568   "reload_in_progress"
4569   "*
4570   output_add_immediate (operands);
4571   return \"add%?s\\t%0, %0, %3%S5\";
4573 [(set_attr "conds" "set")
4574  (set_attr "length" "20")])
4576 (define_insn "*reload_mulsi_compare0_scratch"
4577   [(set (reg:CC_NOOV 24)
4578         (compare:CC_NOOV (plus:SI
4579                           (plus:SI 
4580                            (match_operator:SI 5 "shift_operator"
4581                             [(match_operand:SI 3 "" "r")
4582                              (match_operand:SI 4 "" "rM")])
4583                            (match_operand:SI 1 "" "r"))
4584                           (match_operand:SI 2 "const_int_operand" "n"))
4585                          (const_int 0)))
4586    (clobber (match_scratch:SI 0 "=&r"))]
4587   "reload_in_progress"
4588   "*
4589   output_add_immediate (operands);
4590   return \"add%?s\\t%0, %0, %3%S5\";
4592 [(set_attr "conds" "set")
4593  (set_attr "length" "20")])
4595 ;; These are similar, but are needed when the mla pattern contains the
4596 ;; eliminated register as operand 3.
4598 (define_insn "*reload_muladdsi"
4599   [(set (match_operand:SI 0 "" "=&r,&r")
4600         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4601                                    (match_operand:SI 2 "" "r,r"))
4602                           (match_operand:SI 3 "" "r,r"))
4603                  (match_operand:SI 4 "const_int_operand" "n,n")))]
4604   "reload_in_progress"
4605   "*
4606   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4607   operands[2] = operands[4];
4608   operands[1] = operands[0];
4609   return output_add_immediate (operands);
4611 [(set_attr "length" "20")
4612  (set_attr "type" "mult")])
4614 (define_insn "*reload_muladdsi_compare0"
4615   [(set (reg:CC_NOOV 24)
4616         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4617                                             (match_operand:SI 3 "" "r")
4618                                             (match_operand:SI 4 "" "r"))
4619                                            (match_operand:SI 1 "" "r"))
4620                                   (match_operand:SI 2 "const_int_operand" "n"))
4621                          (const_int 0)))
4622    (set (match_operand:SI 0 "" "=&r")
4623         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4624                  (match_dup 2)))]
4625   "reload_in_progress"
4626   "*
4627   output_add_immediate (operands);
4628   output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4629   return \"\";
4631 [(set_attr "length" "20")
4632  (set_attr "conds" "set")
4633  (set_attr "type" "mult")])
4635 (define_insn "*reload_muladdsi_compare0_scratch"
4636   [(set (reg:CC_NOOV 24)
4637         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4638                                             (match_operand:SI 3 "" "r")
4639                                             (match_operand:SI 4 "" "r"))
4640                                            (match_operand:SI 1 "" "r"))
4641                                   (match_operand:SI 2 "const_int_operand" "n"))
4642                          (const_int 0)))
4643    (clobber (match_scratch:SI 0 "=&r"))]
4644   "reload_in_progress"
4645   "*
4646   output_add_immediate (operands);
4647   return \"mla%?s\\t%0, %3, %4, %0\";
4649 [(set_attr "length" "20")
4650  (set_attr "conds" "set")
4651  (set_attr "type" "mult")])
4655 (define_insn "*and_scc"
4656   [(set (match_operand:SI 0 "s_register_operand" "=r")
4657         (and:SI (match_operator 1 "comparison_operator"
4658                  [(match_operand 3 "cc_register" "") (const_int 0)])
4659                 (match_operand:SI 2 "s_register_operand" "r")))]
4660   ""
4661   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
4662 [(set_attr "conds" "use")
4663  (set_attr "length" "8")])
4665 (define_insn "*ior_scc"
4666   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4667         (ior:SI (match_operator 2 "comparison_operator"
4668                  [(match_operand 3 "cc_register" "") (const_int 0)])
4669                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
4670   ""
4671   "@
4672    orr%d2\\t%0, %1, #1
4673    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
4674 [(set_attr "conds" "use")
4675  (set_attr "length" "4,8")])
4677 (define_insn "*compare_scc"
4678   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4679         (match_operator 1 "comparison_operator"
4680          [(match_operand:SI 2 "s_register_operand" "r,r")
4681           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4682    (clobber (reg:CC 24))]
4683   ""
4684   "*
4685   if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4686     return \"mov\\t%0, %2, lsr #31\";
4688   if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4689     return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4691   if (GET_CODE (operands[1]) == NE)
4692     {
4693       if (which_alternative == 1)
4694         return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4695       return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4696     }
4697   if (which_alternative == 1)
4698     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4699   else
4700     output_asm_insn (\"cmp\\t%2, %3\", operands);
4701   return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4703 [(set_attr "conds" "clob")
4704  (set_attr "length" "12")])
4706 (define_insn "*cond_move"
4707   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4708         (if_then_else:SI (match_operator 3 "equality_operator"
4709                           [(match_operator 4 "comparison_operator"
4710                             [(match_operand 5 "cc_register" "") (const_int 0)])
4711                            (const_int 0)])
4712                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4713                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4714   ""
4715   "*
4716   if (GET_CODE (operands[3]) == NE)
4717     {
4718       if (which_alternative != 1)
4719         output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4720       if (which_alternative != 0)
4721         output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4722       return \"\";
4723     }
4724   if (which_alternative != 0)
4725     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4726   if (which_alternative != 1)
4727     output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4728   return \"\";
4730 [(set_attr "conds" "use")
4731  (set_attr "length" "4,4,8")])
4733 (define_insn "*cond_arith"
4734   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4735         (match_operator:SI 5 "shiftable_operator" 
4736          [(match_operator:SI 4 "comparison_operator"
4737            [(match_operand:SI 2 "s_register_operand" "r,r")
4738             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4739           (match_operand:SI 1 "s_register_operand" "0,?r")]))
4740    (clobber (reg:CC 24))]
4741   ""
4742   "*
4743   if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4744     return \"%i5\\t%0, %1, %2, lsr #31\";
4746   output_asm_insn (\"cmp\\t%2, %3\", operands);
4747   if (GET_CODE (operands[5]) == AND)
4748     output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4749   else if (GET_CODE (operands[5]) == MINUS)
4750     output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4751   else if (which_alternative != 0)
4752     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4753   return \"%i5%d4\\t%0, %1, #1\";
4755 [(set_attr "conds" "clob")
4756  (set_attr "length" "12")])
4758 (define_insn "*cond_sub"
4759   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4760         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4761                   (match_operator:SI 4 "comparison_operator"
4762                    [(match_operand:SI 2 "s_register_operand" "r,r")
4763                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4764    (clobber (reg:CC 24))]
4765   ""
4766   "*
4767   output_asm_insn (\"cmp\\t%2, %3\", operands);
4768   if (which_alternative != 0)
4769     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4770   return \"sub%d4\\t%0, %1, #1\";
4772 [(set_attr "conds" "clob")
4773  (set_attr "length" "8,12")])
4775 (define_insn "*cmp_ite0"
4776   [(set (match_operand 6 "dominant_cc_register" "")
4777         (compare
4778          (if_then_else:SI
4779           (match_operator 4 "comparison_operator"
4780            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4781             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4782           (match_operator:SI 5 "comparison_operator"
4783            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4784             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4785           (const_int 0))
4786          (const_int 0)))]
4787   ""
4788   "*
4790   char* opcodes[4][2] =
4791   {
4792     {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
4793     {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
4794     {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
4795     {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
4796      \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
4797   };
4798   int swap =
4799     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
4801   return opcodes[which_alternative][swap];
4804 [(set_attr "conds" "set")
4805  (set_attr "length" "8")])
4807 (define_insn "*cmp_ite1"
4808   [(set (match_operand 6 "dominant_cc_register" "")
4809         (compare
4810          (if_then_else:SI
4811           (match_operator 4 "comparison_operator"
4812            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4813             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4814           (match_operator:SI 5 "comparison_operator"
4815            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4816             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4817           (const_int 1))
4818          (const_int 0)))]
4819   ""
4820   "*
4822   char* opcodes[4][2] =
4823   {
4824     {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
4825     {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
4826     {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
4827     {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
4828      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
4829   };
4830   int swap =
4831     comparison_dominates_p (GET_CODE (operands[5]),
4832                             reverse_condition (GET_CODE (operands[4])));
4834   return opcodes[which_alternative][swap];
4837 [(set_attr "conds" "set")
4838  (set_attr "length" "8")])
4840 (define_insn "*negscc"
4841   [(set (match_operand:SI 0 "s_register_operand" "=r")
4842         (neg:SI (match_operator 3 "comparison_operator"
4843                  [(match_operand:SI 1 "s_register_operand" "r")
4844                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4845    (clobber (reg:CC 24))]
4846   ""
4847   "*
4848   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4849     return \"mov\\t%0, %1, asr #31\";
4851   if (GET_CODE (operands[3]) == NE)
4852     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4854   if (GET_CODE (operands[3]) == GT)
4855     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4857   output_asm_insn (\"cmp\\t%1, %2\", operands);
4858   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4859   return \"mvn%d3\\t%0, #0\";
4861 [(set_attr "conds" "clob")
4862  (set_attr "length" "12")])
4864 (define_insn "movcond"
4865   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4866         (if_then_else:SI
4867          (match_operator 5 "comparison_operator"
4868           [(match_operand:SI 3 "s_register_operand" "r,r,r")
4869            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4870          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4871          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4872    (clobber (reg:CC 24))]
4873   ""
4874   "*
4875   if (GET_CODE (operands[5]) == LT
4876       && (operands[4] == const0_rtx))
4877     {
4878       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4879         {
4880           if (operands[2] == const0_rtx)
4881             return \"and\\t%0, %1, %3, asr #31\";
4882           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4883         }
4884       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4885         {
4886           if (operands[1] == const0_rtx)
4887             return \"bic\\t%0, %2, %3, asr #31\";
4888           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4889         }
4890       /* The only case that falls through to here is when both ops 1 & 2
4891          are constants */
4892     }
4894   if (GET_CODE (operands[5]) == GE
4895       && (operands[4] == const0_rtx))
4896     {
4897       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4898         {
4899           if (operands[2] == const0_rtx)
4900             return \"bic\\t%0, %1, %3, asr #31\";
4901           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4902         }
4903       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4904         {
4905           if (operands[1] == const0_rtx)
4906             return \"and\\t%0, %2, %3, asr #31\";
4907           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4908         }
4909       /* The only case that falls through to here is when both ops 1 & 2
4910          are constants */
4911     }
4912   if (GET_CODE (operands[4]) == CONST_INT
4913       && !const_ok_for_arm (INTVAL (operands[4])))
4914     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4915   else
4916     output_asm_insn (\"cmp\\t%3, %4\", operands);
4917   if (which_alternative != 0)
4918     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4919   if (which_alternative != 1)
4920     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4921   return \"\";
4923 [(set_attr "conds" "clob")
4924  (set_attr "length" "8,8,12")])
4926 (define_insn "*ifcompare_plus_move"
4927   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4928         (if_then_else:SI (match_operator 6 "comparison_operator"
4929                           [(match_operand:SI 4 "s_register_operand" "r,r")
4930                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4931                          (plus:SI
4932                           (match_operand:SI 2 "s_register_operand" "r,r")
4933                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
4934                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
4935    (clobber (reg:CC 24))]
4936   ""
4937   "#"
4938 [(set_attr "conds" "clob")
4939  (set_attr "length" "8,12")])
4941 (define_insn "*if_plus_move"
4942   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4943         (if_then_else:SI
4944          (match_operator 4 "comparison_operator"
4945           [(match_operand 5 "cc_register" "") (const_int 0)])
4946          (plus:SI
4947           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4948           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
4949          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
4950   ""
4951   "@
4952    add%d4\\t%0, %2, %3
4953    sub%d4\\t%0, %2, #%n3
4954    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4955    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
4956 [(set_attr "conds" "use")
4957  (set_attr "length" "4,4,8,8")
4958  (set_attr "type" "*,*,*,*")])
4960 (define_insn "*ifcompare_move_plus"
4961   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4962         (if_then_else:SI (match_operator 6 "comparison_operator"
4963                           [(match_operand:SI 4 "s_register_operand" "r,r")
4964                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4965                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4966                          (plus:SI
4967                           (match_operand:SI 2 "s_register_operand" "r,r")
4968                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4969    (clobber (reg:CC 24))]
4970   ""
4971   "#"
4972 [(set_attr "conds" "clob")
4973  (set_attr "length" "8,12")])
4975 (define_insn "*if_move_plus"
4976   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4977         (if_then_else:SI
4978          (match_operator 4 "comparison_operator"
4979           [(match_operand 5 "cc_register" "") (const_int 0)])
4980          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4981          (plus:SI
4982           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4983           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
4984   ""
4985   "@
4986    add%D4\\t%0, %2, %3
4987    sub%D4\\t%0, %2, #%n3
4988    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4989    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
4990 [(set_attr "conds" "use")
4991  (set_attr "length" "4,4,8,8")
4992  (set_attr "type" "*,*,*,*")])
4994 (define_insn "*ifcompare_arith_arith"
4995   [(set (match_operand:SI 0 "s_register_operand" "=r")
4996         (if_then_else:SI (match_operator 9 "comparison_operator"
4997                           [(match_operand:SI 5 "s_register_operand" "r")
4998                            (match_operand:SI 6 "arm_add_operand" "rIL")])
4999                          (match_operator:SI 8 "shiftable_operator"
5000                           [(match_operand:SI 1 "s_register_operand" "r")
5001                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
5002                          (match_operator:SI 7 "shiftable_operator"
5003                           [(match_operand:SI 3 "s_register_operand" "r")
5004                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
5005    (clobber (reg:CC 24))]
5006   ""
5007   "#"
5008 [(set_attr "conds" "clob")
5009  (set_attr "length" "12")])
5011 (define_insn "*if_arith_arith"
5012   [(set (match_operand:SI 0 "s_register_operand" "=r")
5013         (if_then_else:SI (match_operator 5 "comparison_operator"
5014                           [(match_operand 8 "cc_register" "") (const_int 0)])
5015                          (match_operator:SI 6 "shiftable_operator"
5016                           [(match_operand:SI 1 "s_register_operand" "r")
5017                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
5018                          (match_operator:SI 7 "shiftable_operator"
5019                           [(match_operand:SI 3 "s_register_operand" "r")
5020                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
5021   ""
5022   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
5023 [(set_attr "conds" "use")
5024  (set_attr "length" "8")])
5026 (define_insn "*ifcompare_arith_move"
5027   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5028         (if_then_else:SI (match_operator 6 "comparison_operator"
5029                           [(match_operand:SI 2 "s_register_operand" "r,r")
5030                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
5031                          (match_operator:SI 7 "shiftable_operator"
5032                           [(match_operand:SI 4 "s_register_operand" "r,r")
5033                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
5034                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5035    (clobber (reg:CC 24))]
5036   ""
5037   "*
5038   /* If we have an operation where (op x 0) is the identity operation and
5039      the conditional operator is LT or GE and we are comparing against zero and
5040      everything is in registers then we can do this in two instructions */
5041   if (operands[3] == const0_rtx
5042       && GET_CODE (operands[7]) != AND
5043       && GET_CODE (operands[5]) == REG
5044       && GET_CODE (operands[1]) == REG 
5045       && REGNO (operands[1]) == REGNO (operands[4])
5046       && REGNO (operands[4]) != REGNO (operands[0]))
5047     {
5048       if (GET_CODE (operands[6]) == LT)
5049         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5050       else if (GET_CODE (operands[6]) == GE)
5051         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5052     }
5053   if (GET_CODE (operands[3]) == CONST_INT
5054       && !const_ok_for_arm (INTVAL (operands[3])))
5055     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
5056   else
5057     output_asm_insn (\"cmp\\t%2, %3\", operands);
5058   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
5059   if (which_alternative != 0)
5060     return \"mov%D6\\t%0, %1\";
5061   return \"\";
5063 [(set_attr "conds" "clob")
5064  (set_attr "length" "8,12")])
5066 (define_insn "*if_arith_move"
5067   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5068         (if_then_else:SI (match_operator 4 "comparison_operator"
5069                           [(match_operand 6 "cc_register" "") (const_int 0)])
5070                          (match_operator:SI 5 "shiftable_operator"
5071                           [(match_operand:SI 2 "s_register_operand" "r,r")
5072                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
5073                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
5074   ""
5075   "@
5076    %I5%d4\\t%0, %2, %3
5077    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
5078 [(set_attr "conds" "use")
5079  (set_attr "length" "4,8")
5080  (set_attr "type" "*,*")])
5082 (define_insn "*ifcompare_move_arith"
5083   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5084         (if_then_else:SI (match_operator 6 "comparison_operator"
5085                           [(match_operand:SI 4 "s_register_operand" "r,r")
5086                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5087                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5088                          (match_operator:SI 7 "shiftable_operator"
5089                           [(match_operand:SI 2 "s_register_operand" "r,r")
5090                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
5091    (clobber (reg:CC 24))]
5092   ""
5093   "*
5094   /* If we have an operation where (op x 0) is the identity operation and
5095      the conditional operator is LT or GE and we are comparing against zero and
5096      everything is in registers then we can do this in two instructions */
5097   if (operands[5] == const0_rtx
5098       && GET_CODE (operands[7]) != AND
5099       && GET_CODE (operands[3]) == REG
5100       && GET_CODE (operands[1]) == REG 
5101       && REGNO (operands[1]) == REGNO (operands[2])
5102       && REGNO (operands[2]) != REGNO (operands[0]))
5103     {
5104       if (GET_CODE (operands[6]) == GE)
5105         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5106       else if (GET_CODE (operands[6]) == LT)
5107         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5108     }
5110   if (GET_CODE (operands[5]) == CONST_INT
5111       && !const_ok_for_arm (INTVAL (operands[5])))
5112     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5113   else
5114     output_asm_insn (\"cmp\\t%4, %5\", operands);
5116   if (which_alternative != 0)
5117     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
5118   return \"%I7%D6\\t%0, %2, %3\";
5120 [(set_attr "conds" "clob")
5121  (set_attr "length" "8,12")])
5123 (define_insn "*if_move_arith"
5124   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5125         (if_then_else:SI
5126          (match_operator 4 "comparison_operator"
5127           [(match_operand 6 "cc_register" "") (const_int 0)])
5128          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5129          (match_operator:SI 5 "shiftable_operator"
5130           [(match_operand:SI 2 "s_register_operand" "r,r")
5131            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
5132   ""
5133   "@
5134    %I5%D4\\t%0, %2, %3
5135    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
5136 [(set_attr "conds" "use")
5137  (set_attr "length" "4,8")
5138  (set_attr "type" "*,*")])
5140 (define_insn "*ifcompare_move_not"
5141   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5142         (if_then_else:SI
5143          (match_operator 5 "comparison_operator"
5144           [(match_operand:SI 3 "s_register_operand" "r,r")
5145            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5146          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5147          (not:SI
5148           (match_operand:SI 2 "s_register_operand" "r,r"))))
5149    (clobber (reg:CC 24))]
5150   ""
5151   "#"
5152 [(set_attr "conds" "clob")
5153  (set_attr "length" "8,12")])
5155 (define_insn "*if_move_not"
5156   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5157         (if_then_else:SI
5158          (match_operator 4 "comparison_operator"
5159           [(match_operand 3 "cc_register" "") (const_int 0)])
5160          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5161          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5162   ""
5163   "@
5164    mvn%D4\\t%0, %2
5165    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
5166    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
5167 [(set_attr "conds" "use")
5168  (set_attr "length" "4,8,8")])
5170 (define_insn "*ifcompare_not_move"
5171   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5172         (if_then_else:SI 
5173          (match_operator 5 "comparison_operator"
5174           [(match_operand:SI 3 "s_register_operand" "r,r")
5175            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5176          (not:SI
5177           (match_operand:SI 2 "s_register_operand" "r,r"))
5178          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5179    (clobber (reg:CC 24))]
5180   ""
5181   "#"
5182 [(set_attr "conds" "clob")
5183  (set_attr "length" "8,12")])
5185 (define_insn "*if_not_move"
5186   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5187         (if_then_else:SI
5188          (match_operator 4 "comparison_operator"
5189           [(match_operand 3 "cc_register" "") (const_int 0)])
5190          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5191          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5192   ""
5193   "@
5194    mvn%d4\\t%0, %2
5195    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
5196    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
5197 [(set_attr "conds" "use")
5198  (set_attr "length" "4,8,8")])
5200 (define_insn "*ifcompare_shift_move"
5201   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5202         (if_then_else:SI
5203          (match_operator 6 "comparison_operator"
5204           [(match_operand:SI 4 "s_register_operand" "r,r")
5205            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5206          (match_operator:SI 7 "shift_operator"
5207           [(match_operand:SI 2 "s_register_operand" "r,r")
5208            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
5209          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5210    (clobber (reg:CC 24))]
5211   ""
5212   "#"
5213 [(set_attr "conds" "clob")
5214  (set_attr "length" "8,12")])
5216 (define_insn "*if_shift_move"
5217   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5218         (if_then_else:SI
5219          (match_operator 5 "comparison_operator"
5220           [(match_operand 6 "cc_register" "") (const_int 0)])
5221          (match_operator:SI 4 "shift_operator"
5222           [(match_operand:SI 2 "s_register_operand" "r,r,r")
5223            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
5224          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5225   ""
5226   "@
5227    mov%d5\\t%0, %2%S4
5228    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
5229    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
5230 [(set_attr "conds" "use")
5231  (set_attr "length" "4,8,8")])
5233 (define_insn "*ifcompare_move_shift"
5234   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5235         (if_then_else:SI
5236          (match_operator 6 "comparison_operator"
5237           [(match_operand:SI 4 "s_register_operand" "r,r")
5238            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5239          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5240          (match_operator:SI 7 "shift_operator"
5241           [(match_operand:SI 2 "s_register_operand" "r,r")
5242            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5243    (clobber (reg:CC 24))]
5244   ""
5245   "#"
5246 [(set_attr "conds" "clob")
5247  (set_attr "length" "8,12")])
5249 (define_insn "*if_move_shift"
5250   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5251         (if_then_else:SI
5252          (match_operator 5 "comparison_operator"
5253           [(match_operand 6 "cc_register" "") (const_int 0)])
5254          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5255          (match_operator:SI 4 "shift_operator"
5256           [(match_operand:SI 2 "s_register_operand" "r,r,r")
5257            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5258   ""
5259   "@
5260    mov%D5\\t%0, %2%S4
5261    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5262    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5263 [(set_attr "conds" "use")
5264  (set_attr "length" "4,8,8")])
5266 (define_insn "*ifcompare_shift_shift"
5267   [(set (match_operand:SI 0 "s_register_operand" "=r")
5268         (if_then_else:SI
5269          (match_operator 7 "comparison_operator"
5270           [(match_operand:SI 5 "s_register_operand" "r")
5271            (match_operand:SI 6 "arm_add_operand" "rIL")])
5272          (match_operator:SI 8 "shift_operator"
5273           [(match_operand:SI 1 "s_register_operand" "r")
5274            (match_operand:SI 2 "arm_rhs_operand" "rM")])
5275          (match_operator:SI 9 "shift_operator"
5276           [(match_operand:SI 3 "s_register_operand" "r")
5277            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5278    (clobber (reg:CC 24))]
5279   ""
5280   "#"
5281 [(set_attr "conds" "clob")
5282  (set_attr "length" "12")])
5284 (define_insn "*if_shift_shift"
5285   [(set (match_operand:SI 0 "s_register_operand" "=r")
5286         (if_then_else:SI
5287          (match_operator 5 "comparison_operator"
5288           [(match_operand 8 "cc_register" "") (const_int 0)])
5289          (match_operator:SI 6 "shift_operator"
5290           [(match_operand:SI 1 "s_register_operand" "r")
5291            (match_operand:SI 2 "arm_rhs_operand" "rM")])
5292          (match_operator:SI 7 "shift_operator"
5293           [(match_operand:SI 3 "s_register_operand" "r")
5294            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5295   ""
5296   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5297 [(set_attr "conds" "use")
5298  (set_attr "length" "8")])
5300 (define_insn "*ifcompare_not_arith"
5301   [(set (match_operand:SI 0 "s_register_operand" "=r")
5302         (if_then_else:SI
5303          (match_operator 6 "comparison_operator"
5304           [(match_operand:SI 4 "s_register_operand" "r")
5305            (match_operand:SI 5 "arm_add_operand" "rIL")])
5306          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5307          (match_operator:SI 7 "shiftable_operator"
5308           [(match_operand:SI 2 "s_register_operand" "r")
5309            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5310    (clobber (reg:CC 24))]
5311   ""
5312   "#"
5313 [(set_attr "conds" "clob")
5314  (set_attr "length" "12")])
5316 (define_insn "*if_not_arith"
5317   [(set (match_operand:SI 0 "s_register_operand" "=r")
5318         (if_then_else:SI
5319          (match_operator 5 "comparison_operator"
5320           [(match_operand 4 "cc_register" "") (const_int 0)])
5321          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5322          (match_operator:SI 6 "shiftable_operator"
5323           [(match_operand:SI 2 "s_register_operand" "r")
5324            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5325   ""
5326   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5327 [(set_attr "conds" "use")
5328  (set_attr "length" "8")])
5330 (define_insn "*ifcompare_arith_not"
5331   [(set (match_operand:SI 0 "s_register_operand" "=r")
5332         (if_then_else:SI
5333          (match_operator 6 "comparison_operator"
5334           [(match_operand:SI 4 "s_register_operand" "r")
5335            (match_operand:SI 5 "arm_add_operand" "rIL")])
5336          (match_operator:SI 7 "shiftable_operator"
5337           [(match_operand:SI 2 "s_register_operand" "r")
5338            (match_operand:SI 3 "arm_rhs_operand" "rI")])
5339          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5340    (clobber (reg:CC 24))]
5341   ""
5342   "#"
5343 [(set_attr "conds" "clob")
5344  (set_attr "length" "12")])
5346 (define_insn "*if_arith_not"
5347   [(set (match_operand:SI 0 "s_register_operand" "=r")
5348         (if_then_else:SI
5349          (match_operator 5 "comparison_operator"
5350           [(match_operand 4 "cc_register" "") (const_int 0)])
5351          (match_operator:SI 6 "shiftable_operator"
5352           [(match_operand:SI 2 "s_register_operand" "r")
5353            (match_operand:SI 3 "arm_rhs_operand" "rI")])
5354          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5355   ""
5356   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5357 [(set_attr "conds" "use")
5358  (set_attr "length" "8")])
5360 (define_insn "*ifcompare_neg_move"
5361   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5362         (if_then_else:SI
5363          (match_operator 5 "comparison_operator"
5364           [(match_operand:SI 3 "s_register_operand" "r,r")
5365            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5366          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5367          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5368    (clobber (reg:CC 24))]
5369   ""
5370   "#"
5371 [(set_attr "conds" "clob")
5372  (set_attr "length" "8,12")])
5374 (define_insn "*if_neg_move"
5375   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5376         (if_then_else:SI
5377          (match_operator 4 "comparison_operator"
5378           [(match_operand 3 "cc_register" "") (const_int 0)])
5379          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5380          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5381   ""
5382   "@
5383    rsb%d4\\t%0, %2, #0
5384    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5385    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5386 [(set_attr "conds" "use")
5387  (set_attr "length" "4,8,8")])
5389 (define_insn "*ifcompare_move_neg"
5390   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5391         (if_then_else:SI
5392          (match_operator 5 "comparison_operator"
5393           [(match_operand:SI 3 "s_register_operand" "r,r")
5394            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5395          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5396          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5397    (clobber (reg:CC 24))]
5398   ""
5399   "#"
5400 [(set_attr "conds" "clob")
5401  (set_attr "length" "8,12")])
5403 (define_insn "*if_move_neg"
5404   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5405         (if_then_else:SI
5406          (match_operator 4 "comparison_operator"
5407           [(match_operand 3 "cc_register" "") (const_int 0)])
5408          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5409          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5410   ""
5411   "@
5412    rsb%D4\\t%0, %2, #0
5413    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5414    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5415 [(set_attr "conds" "use")
5416  (set_attr "length" "4,8,8")])
5418 (define_insn "*arith_adjacentmem"
5419   [(set (match_operand:SI 0 "s_register_operand" "=r")
5420         (match_operator:SI 1 "shiftable_operator"
5421          [(match_operand:SI 2 "memory_operand" "m")
5422           (match_operand:SI 3 "memory_operand" "m")]))
5423    (clobber (match_scratch:SI 4 "=r"))]
5424   "adjacent_mem_locations (operands[2], operands[3])"
5425   "*
5427   rtx ldm[3];
5428   rtx arith[4];
5429   int val1 = 0, val2 = 0;
5431   if (REGNO (operands[0]) > REGNO (operands[4]))
5432     {
5433       ldm[1] = operands[4];
5434       ldm[2] = operands[0];
5435     }
5436   else
5437     {
5438       ldm[1] = operands[0];
5439       ldm[2] = operands[4];
5440     }
5441   if (GET_CODE (XEXP (operands[2], 0)) != REG)
5442     val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5443   if (GET_CODE (XEXP (operands[3], 0)) != REG)
5444     val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5445   arith[0] = operands[0];
5446   arith[3] = operands[1];
5447   if (val1 < val2)
5448     {
5449       arith[1] = ldm[1];
5450       arith[2] = ldm[2];
5451     }
5452   else
5453     {
5454       arith[1] = ldm[2];
5455       arith[2] = ldm[1];
5456     }
5457   if (val1 && val2)
5458     {
5459       rtx ops[3];
5460       ldm[0] = ops[0] = operands[4];
5461       ops[1] = XEXP (XEXP (operands[2], 0), 0);
5462       ops[2] = XEXP (XEXP (operands[2], 0), 1);
5463       output_add_immediate (ops);
5464       if (val1 < val2)
5465         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5466       else
5467         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5468     }
5469   else if (val1)
5470     {
5471       ldm[0] = XEXP (operands[3], 0);
5472       if (val1 < val2)
5473         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5474       else
5475         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5476     }
5477   else
5478     {
5479       ldm[0] = XEXP (operands[2], 0);
5480       if (val1 < val2)
5481         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5482       else
5483         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5484     }
5485   output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5486   return \"\";
5489 [(set_attr "length" "12")
5490  (set_attr "type" "load")])
5492 ;; the arm can support extended pre-inc instructions
5494 ;; In all these cases, we use operands 0 and 1 for the register being
5495 ;; incremented because those are the operands that local-alloc will
5496 ;; tie and these are the pair most likely to be tieable (and the ones
5497 ;; that will benefit the most).
5499 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5500 ;; elimination will cause too many headaches.
5502 (define_insn "*strqi_preinc"
5503   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5504                          (match_operand:SI 2 "index_operand" "rJ")))
5505         (match_operand:QI 3 "s_register_operand" "r"))
5506    (set (match_operand:SI 0 "s_register_operand" "=r")
5507         (plus:SI (match_dup 1) (match_dup 2)))]
5508   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5509    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5510    && (GET_CODE (operands[2]) != REG
5511        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5512   "str%?b\\t%3, [%0, %2]!"
5513 [(set_attr "type" "store1")])
5515 (define_insn "*strqi_predec"
5516   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5517                           (match_operand:SI 2 "s_register_operand" "r")))
5518         (match_operand:QI 3 "s_register_operand" "r"))
5519    (set (match_operand:SI 0 "s_register_operand" "=r")
5520         (minus:SI (match_dup 1) (match_dup 2)))]
5521   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5522    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5523    && (GET_CODE (operands[2]) != REG
5524        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5525   "str%?b\\t%3, [%0, -%2]!"
5526 [(set_attr "type" "store1")])
5528 (define_insn "*loadqi_preinc"
5529   [(set (match_operand:QI 3 "s_register_operand" "=r")
5530         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5531                          (match_operand:SI 2 "index_operand" "rJ"))))
5532    (set (match_operand:SI 0 "s_register_operand" "=r")
5533         (plus:SI (match_dup 1) (match_dup 2)))]
5534   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5535    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5536    && (GET_CODE (operands[2]) != REG
5537        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5538   "ldr%?b\\t%3, [%0, %2]!"
5539 [(set_attr "type" "load")])
5541 (define_insn "*loadqi_predec"
5542   [(set (match_operand:QI 3 "s_register_operand" "=r")
5543         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5544                           (match_operand:SI 2 "s_register_operand" "r"))))
5545    (set (match_operand:SI 0 "s_register_operand" "=r")
5546         (minus:SI (match_dup 1) (match_dup 2)))]
5547   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5548    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5549    && (GET_CODE (operands[2]) != REG
5550        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5551   "ldr%?b\\t%3, [%0, -%2]!"
5552 [(set_attr "type" "load")])
5554 (define_insn "*loadqisi_preinc"
5555   [(set (match_operand:SI 3 "s_register_operand" "=r")
5556         (zero_extend:SI
5557          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5558                           (match_operand:SI 2 "index_operand" "rJ")))))
5559    (set (match_operand:SI 0 "s_register_operand" "=r")
5560         (plus:SI (match_dup 1) (match_dup 2)))]
5561   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5562    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5563    && (GET_CODE (operands[2]) != REG
5564        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5565   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5566 [(set_attr "type" "load")])
5568 (define_insn "*loadqisi_predec"
5569   [(set (match_operand:SI 3 "s_register_operand" "=r")
5570         (zero_extend:SI
5571          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5572                            (match_operand:SI 2 "s_register_operand" "r")))))
5573    (set (match_operand:SI 0 "s_register_operand" "=r")
5574         (minus:SI (match_dup 1) (match_dup 2)))]
5575   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5576    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5577    && (GET_CODE (operands[2]) != REG
5578        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5579   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5580 [(set_attr "type" "load")])
5582 (define_insn "*strsi_preinc"
5583   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5584                          (match_operand:SI 2 "index_operand" "rJ")))
5585         (match_operand:SI 3 "s_register_operand" "r"))
5586    (set (match_operand:SI 0 "s_register_operand" "=r")
5587         (plus:SI (match_dup 1) (match_dup 2)))]
5588   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5589    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5590    && (GET_CODE (operands[2]) != REG
5591        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5592   "str%?\\t%3, [%0, %2]!"
5593 [(set_attr "type" "store1")])
5595 (define_insn "*strqi_predec"
5596   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5597                           (match_operand:SI 2 "s_register_operand" "r")))
5598         (match_operand:SI 3 "s_register_operand" "r"))
5599    (set (match_operand:SI 0 "s_register_operand" "=r")
5600         (minus:SI (match_dup 1) (match_dup 2)))]
5601   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5602    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5603    && (GET_CODE (operands[2]) != REG
5604        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5605   "str%?\\t%3, [%0, -%2]!"
5606 [(set_attr "type" "store1")])
5608 (define_insn "*loadsi_preinc"
5609   [(set (match_operand:SI 3 "s_register_operand" "=r")
5610         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5611                          (match_operand:SI 2 "index_operand" "rJ"))))
5612    (set (match_operand:SI 0 "s_register_operand" "=r")
5613         (plus:SI (match_dup 1) (match_dup 2)))]
5614   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5615    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5616    && (GET_CODE (operands[2]) != REG
5617        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5618   "ldr%?\\t%3, [%0, %2]!"
5619 [(set_attr "type" "load")])
5621 (define_insn "*loadsi_predec"
5622   [(set (match_operand:SI 3 "s_register_operand" "=r")
5623         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5624                           (match_operand:SI 2 "s_register_operand" "r"))))
5625    (set (match_operand:SI 0 "s_register_operand" "=r")
5626         (minus:SI (match_dup 1) (match_dup 2)))]
5627   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5628    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5629    && (GET_CODE (operands[2]) != REG
5630        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5631   "ldr%?\\t%3, [%0, -%2]!"
5632 [(set_attr "type" "load")])
5634 (define_insn "*loadhi_preinc"
5635   [(set (match_operand:HI 3 "s_register_operand" "=r")
5636         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5637                          (match_operand:SI 2 "index_operand" "rJ"))))
5638    (set (match_operand:SI 0 "s_register_operand" "=r")
5639         (plus:SI (match_dup 1) (match_dup 2)))]
5640   "(! BYTES_BIG_ENDIAN)
5641    && ! TARGET_SHORT_BY_BYTES
5642    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5643    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5644    && (GET_CODE (operands[2]) != REG
5645        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5646   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5647 [(set_attr "type" "load")])
5649 (define_insn "*loadhi_predec"
5650   [(set (match_operand:HI 3 "s_register_operand" "=r")
5651         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5652                           (match_operand:SI 2 "s_register_operand" "r"))))
5653    (set (match_operand:SI 0 "s_register_operand" "=r")
5654         (minus:SI (match_dup 1) (match_dup 2)))]
5655   "(!BYTES_BIG_ENDIAN)
5656    && ! TARGET_SHORT_BY_BYTES
5657    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5658    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5659    && (GET_CODE (operands[2]) != REG
5660        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5661   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5662 [(set_attr "type" "load")])
5664 (define_insn "*strqi_shiftpreinc"
5665   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5666                           [(match_operand:SI 3 "s_register_operand" "r")
5667                            (match_operand:SI 4 "const_shift_operand" "n")])
5668                          (match_operand:SI 1 "s_register_operand" "0")))
5669         (match_operand:QI 5 "s_register_operand" "r"))
5670    (set (match_operand:SI 0 "s_register_operand" "=r")
5671         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5672                  (match_dup 1)))]
5673   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5674    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5675    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5676   "str%?b\\t%5, [%0, %3%S2]!"
5677 [(set_attr "type" "store1")])
5679 (define_insn "*strqi_shiftpredec"
5680   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5681                           (match_operator:SI 2 "shift_operator"
5682                            [(match_operand:SI 3 "s_register_operand" "r")
5683                             (match_operand:SI 4 "const_shift_operand" "n")])))
5684         (match_operand:QI 5 "s_register_operand" "r"))
5685    (set (match_operand:SI 0 "s_register_operand" "=r")
5686         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5687                                                  (match_dup 4)])))]
5688   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5689    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5690    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5691   "str%?b\\t%5, [%0, -%3%S2]!"
5692 [(set_attr "type" "store1")])
5694 (define_insn "*loadqi_shiftpreinc"
5695   [(set (match_operand:QI 5 "s_register_operand" "=r")
5696         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5697                           [(match_operand:SI 3 "s_register_operand" "r")
5698                            (match_operand:SI 4 "const_shift_operand" "n")])
5699                          (match_operand:SI 1 "s_register_operand" "0"))))
5700    (set (match_operand:SI 0 "s_register_operand" "=r")
5701         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5702                  (match_dup 1)))]
5703   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5704    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5705    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5706   "ldr%?b\\t%5, [%0, %3%S2]!"
5707 [(set_attr "type" "load")])
5709 (define_insn "*loadqi_shiftpredec"
5710   [(set (match_operand:QI 5 "s_register_operand" "=r")
5711         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5712                           (match_operator:SI 2 "shift_operator"
5713                            [(match_operand:SI 3 "s_register_operand" "r")
5714                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5715    (set (match_operand:SI 0 "s_register_operand" "=r")
5716         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5717                                                  (match_dup 4)])))]
5718   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5719    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5720    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5721   "ldr%?b\\t%5, [%0, -%3%S2]!"
5722 [(set_attr "type" "load")])
5724 (define_insn "*strsi_shiftpreinc"
5725   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5726                           [(match_operand:SI 3 "s_register_operand" "r")
5727                            (match_operand:SI 4 "const_shift_operand" "n")])
5728                          (match_operand:SI 1 "s_register_operand" "0")))
5729         (match_operand:SI 5 "s_register_operand" "r"))
5730    (set (match_operand:SI 0 "s_register_operand" "=r")
5731         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5732                  (match_dup 1)))]
5733   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5734    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5735    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5736   "str%?\\t%5, [%0, %3%S2]!"
5737 [(set_attr "type" "store1")])
5739 (define_insn "*strsi_shiftpredec"
5740   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5741                           (match_operator:SI 2 "shift_operator"
5742                            [(match_operand:SI 3 "s_register_operand" "r")
5743                             (match_operand:SI 4 "const_shift_operand" "n")])))
5744         (match_operand:SI 5 "s_register_operand" "r"))
5745    (set (match_operand:SI 0 "s_register_operand" "=r")
5746         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5747                                                  (match_dup 4)])))]
5748   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5749    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5750    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5751   "str%?\\t%5, [%0, -%3%S2]!"
5752 [(set_attr "type" "store1")])
5754 (define_insn "*loadqi_shiftpreinc"
5755   [(set (match_operand:SI 5 "s_register_operand" "=r")
5756         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5757                           [(match_operand:SI 3 "s_register_operand" "r")
5758                            (match_operand:SI 4 "const_shift_operand" "n")])
5759                          (match_operand:SI 1 "s_register_operand" "0"))))
5760    (set (match_operand:SI 0 "s_register_operand" "=r")
5761         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5762                  (match_dup 1)))]
5763   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5764    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5765    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5766   "ldr%?\\t%5, [%0, %3%S2]!"
5767 [(set_attr "type" "load")])
5769 (define_insn "*loadqi_shiftpredec"
5770   [(set (match_operand:SI 5 "s_register_operand" "=r")
5771         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5772                           (match_operator:SI 2 "shift_operator"
5773                            [(match_operand:SI 3 "s_register_operand" "r")
5774                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5775    (set (match_operand:SI 0 "s_register_operand" "=r")
5776         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5777                                                  (match_dup 4)])))]
5778   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5779    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5780    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5781   "ldr%?\\t%5, [%0, -%3%S2]!"
5782 [(set_attr "type" "load")])
5784 (define_insn "*loadhi_shiftpreinc"
5785   [(set (match_operand:HI 5 "s_register_operand" "=r")
5786         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5787                           [(match_operand:SI 3 "s_register_operand" "r")
5788                            (match_operand:SI 4 "const_shift_operand" "n")])
5789                          (match_operand:SI 1 "s_register_operand" "0"))))
5790    (set (match_operand:SI 0 "s_register_operand" "=r")
5791         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5792                  (match_dup 1)))]
5793   "(! BYTES_BIG_ENDIAN)
5794    && ! TARGET_SHORT_BY_BYTES
5795    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5796    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5797    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5798   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5799 [(set_attr "type" "load")])
5801 (define_insn "*loadhi_shiftpredec"
5802   [(set (match_operand:HI 5 "s_register_operand" "=r")
5803         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5804                           (match_operator:SI 2 "shift_operator"
5805                            [(match_operand:SI 3 "s_register_operand" "r")
5806                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5807    (set (match_operand:SI 0 "s_register_operand" "=r")
5808         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5809                                                  (match_dup 4)])))]
5810   "(! BYTES_BIG_ENDIAN)
5811    && ! TARGET_SHORT_BY_BYTES
5812    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5813    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5814    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5815   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5816 [(set_attr "type" "load")])
5818 ; It can also support extended post-inc expressions, but combine doesn't
5819 ; try these....
5820 ; It doesn't seem worth adding peepholes for anything but the most common
5821 ; cases since, unlike combine, the increment must immediately follow the load
5822 ; for this pattern to match.
5823 ; When loading we must watch to see that the base register isn't trampled by
5824 ; the load.  In such cases this isn't a post-inc expression.
5826 (define_peephole
5827   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5828         (match_operand:QI 2 "s_register_operand" "r"))
5829    (set (match_dup 0)
5830         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5831   ""
5832   "str%?b\\t%2, [%0], %1")
5834 (define_peephole
5835   [(set (match_operand:QI 0 "s_register_operand" "=r")
5836         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5837    (set (match_dup 1)
5838         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5839   "REGNO(operands[0]) != REGNO(operands[1])
5840    && (GET_CODE (operands[2]) != REG
5841        || REGNO(operands[0]) != REGNO (operands[2]))"
5842   "ldr%?b\\t%0, [%1], %2")
5844 (define_peephole
5845   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5846         (match_operand:SI 2 "s_register_operand" "r"))
5847    (set (match_dup 0)
5848         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5849   ""
5850   "str%?\\t%2, [%0], %1")
5852 (define_peephole
5853   [(set (match_operand:HI 0 "s_register_operand" "=r")
5854         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5855    (set (match_dup 1)
5856         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5857   "(! BYTES_BIG_ENDIAN)
5858    && ! TARGET_SHORT_BY_BYTES
5859    && REGNO(operands[0]) != REGNO(operands[1])
5860    && (GET_CODE (operands[2]) != REG
5861        || REGNO(operands[0]) != REGNO (operands[2]))"
5862   "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5864 (define_peephole
5865   [(set (match_operand:SI 0 "s_register_operand" "=r")
5866         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5867    (set (match_dup 1)
5868         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5869   "REGNO(operands[0]) != REGNO(operands[1])
5870    && (GET_CODE (operands[2]) != REG
5871        || REGNO(operands[0]) != REGNO (operands[2]))"
5872   "ldr%?\\t%0, [%1], %2")
5874 (define_peephole
5875   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5876                          (match_operand:SI 1 "index_operand" "rJ")))
5877         (match_operand:QI 2 "s_register_operand" "r"))
5878    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5879   ""
5880   "str%?b\\t%2, [%0, %1]!")
5882 (define_peephole
5883   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5884                           [(match_operand:SI 0 "s_register_operand" "r")
5885                            (match_operand:SI 1 "const_int_operand" "n")])
5886                          (match_operand:SI 2 "s_register_operand" "+r")))
5887         (match_operand:QI 3 "s_register_operand" "r"))
5888    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5889                                (match_dup 2)))]
5890   ""
5891   "str%?b\\t%3, [%2, %0%S4]!")
5893 ; This pattern is never tried by combine, so do it as a peephole
5895 (define_peephole
5896   [(set (match_operand:SI 0 "s_register_operand" "=r")
5897         (match_operand:SI 1 "s_register_operand" "r"))
5898    (set (reg:CC 24)
5899         (compare:CC (match_dup 1) (const_int 0)))]
5900   ""
5901   "sub%?s\\t%0, %1, #0"
5902 [(set_attr "conds" "set")])
5904 ; Peepholes to spot possible load- and store-multiples, if the ordering is
5905 ; reversed, check that the memory references aren't volatile.
5907 (define_peephole
5908   [(set (match_operand:SI 0 "s_register_operand" "=r")
5909         (match_operand:SI 4 "memory_operand" "m"))
5910    (set (match_operand:SI 1 "s_register_operand" "=r")
5911         (match_operand:SI 5 "memory_operand" "m"))
5912    (set (match_operand:SI 2 "s_register_operand" "=r")
5913         (match_operand:SI 6 "memory_operand" "m"))
5914    (set (match_operand:SI 3 "s_register_operand" "=r")
5915         (match_operand:SI 7 "memory_operand" "m"))]
5916   "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5917   "*
5918   return emit_ldm_seq (operands, 4);
5921 (define_peephole
5922   [(set (match_operand:SI 0 "s_register_operand" "=r")
5923         (match_operand:SI 3 "memory_operand" "m"))
5924    (set (match_operand:SI 1 "s_register_operand" "=r")
5925         (match_operand:SI 4 "memory_operand" "m"))
5926    (set (match_operand:SI 2 "s_register_operand" "=r")
5927         (match_operand:SI 5 "memory_operand" "m"))]
5928   "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5929   "*
5930   return emit_ldm_seq (operands, 3);
5933 (define_peephole
5934   [(set (match_operand:SI 0 "s_register_operand" "=r")
5935         (match_operand:SI 2 "memory_operand" "m"))
5936    (set (match_operand:SI 1 "s_register_operand" "=r")
5937         (match_operand:SI 3 "memory_operand" "m"))]
5938   "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5939   "*
5940   return emit_ldm_seq (operands, 2);
5943 (define_peephole
5944   [(set (match_operand:SI 4 "memory_operand" "=m")
5945         (match_operand:SI 0 "s_register_operand" "r"))
5946    (set (match_operand:SI 5 "memory_operand" "=m")
5947         (match_operand:SI 1 "s_register_operand" "r"))
5948    (set (match_operand:SI 6 "memory_operand" "=m")
5949         (match_operand:SI 2 "s_register_operand" "r"))
5950    (set (match_operand:SI 7 "memory_operand" "=m")
5951         (match_operand:SI 3 "s_register_operand" "r"))]
5952   "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5953   "*
5954   return emit_stm_seq (operands, 4);
5957 (define_peephole
5958   [(set (match_operand:SI 3 "memory_operand" "=m")
5959         (match_operand:SI 0 "s_register_operand" "r"))
5960    (set (match_operand:SI 4 "memory_operand" "=m")
5961         (match_operand:SI 1 "s_register_operand" "r"))
5962    (set (match_operand:SI 5 "memory_operand" "=m")
5963         (match_operand:SI 2 "s_register_operand" "r"))]
5964   "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5965   "*
5966   return emit_stm_seq (operands, 3);
5969 (define_peephole
5970   [(set (match_operand:SI 2 "memory_operand" "=m")
5971         (match_operand:SI 0 "s_register_operand" "r"))
5972    (set (match_operand:SI 3 "memory_operand" "=m")
5973         (match_operand:SI 1 "s_register_operand" "r"))]
5974   "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5975   "*
5976   return emit_stm_seq (operands, 2);
5979 ;; A call followed by return can be replaced by restoring the regs and
5980 ;; jumping to the subroutine, provided we aren't passing the address of
5981 ;; any of our local variables.  If we call alloca then this is unsafe
5982 ;; since restoring the frame frees the memory, which is not what we want.
5983 ;; Sometimes the return might have been targeted by the final prescan:
5984 ;; if so then emit a proper return insn as well.
5985 ;; Unfortunately, if the frame pointer is required, we don't know if the
5986 ;; current function has any implicit stack pointer adjustments that will 
5987 ;; be restored by the return: we can't therefore do a tail call.
5988 ;; Another unfortunate that we can't handle is if current_function_args_size
5989 ;; is non-zero: in this case elimination of the argument pointer assumed
5990 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5991 ;; calculations.
5993 (define_peephole
5994   [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5995                           (match_operand:SI 1 "general_operand" "g"))
5996                     (clobber (reg:SI 14))])
5997    (return)]
5998   "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
5999     && !get_frame_size () && !current_function_calls_alloca
6000     && !frame_pointer_needed && !current_function_args_size)"
6001   "*
6003   extern rtx arm_target_insn;
6004   extern int arm_ccfsm_state;
6006   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6007   {
6008     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6009     output_return_instruction (NULL, TRUE, FALSE);
6010     arm_ccfsm_state = 0;
6011     arm_target_insn = NULL;
6012   }
6014   output_return_instruction (NULL, FALSE, FALSE);
6015   return \"b%?\\t%a0\";
6017 [(set_attr "type" "call")
6018  (set_attr "length" "8")])
6020 (define_peephole
6021   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6022                    (call (mem:SI (match_operand:SI 1 "" "X"))
6023                          (match_operand:SI 2 "general_operand" "g")))
6024               (clobber (reg:SI 14))])
6025    (return)]
6026   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6027     && !get_frame_size () && !current_function_calls_alloca
6028     && !frame_pointer_needed && !current_function_args_size)"
6029   "*
6031   extern rtx arm_target_insn;
6032   extern int arm_ccfsm_state;
6034   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6035   {
6036     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6037     output_return_instruction (NULL, TRUE, FALSE);
6038     arm_ccfsm_state = 0;
6039     arm_target_insn = NULL;
6040   }
6042   output_return_instruction (NULL, FALSE, FALSE);
6043   return \"b%?\\t%a1\";
6045 [(set_attr "type" "call")
6046  (set_attr "length" "8")])
6048 ;; As above but when this function is not void, we must be returning the
6049 ;; result of the called subroutine.
6051 (define_peephole
6052   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6053                    (call (mem:SI (match_operand:SI 1 "" "X"))
6054                          (match_operand:SI 2 "general_operand" "g")))
6055               (clobber (reg:SI 14))])
6056    (use (match_dup 0))
6057    (return)]
6058   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6059     && !get_frame_size () && !current_function_calls_alloca
6060     && !frame_pointer_needed && !current_function_args_size)"
6061   "*
6063   extern rtx arm_target_insn;
6064   extern int arm_ccfsm_state;
6066   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6067   {
6068     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6069     output_return_instruction (NULL, TRUE, FALSE);
6070     arm_ccfsm_state = 0;
6071     arm_target_insn = NULL;
6072   }
6074   output_return_instruction (NULL, FALSE, FALSE);
6075   return \"b%?\\t%a1\";
6077 [(set_attr "type" "call")
6078  (set_attr "length" "8")])
6080 (define_split
6081   [(set (match_operand:SI 0 "s_register_operand" "")
6082         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
6083                        (const_int 0))
6084                 (neg:SI (match_operator:SI 2 "comparison_operator"
6085                          [(match_operand:SI 3 "s_register_operand" "")
6086                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
6087    (clobber (match_operand:SI 5 "s_register_operand" ""))]
6088   ""
6089   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
6090    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6091                               (match_dup 5)))]
6092   "")
6094 ;; This split can be used because CC_Z mode implies that the following
6095 ;; branch will be an equality, or an unsigned inequality, so the sign
6096 ;; extension is not needed.
6098 (define_split
6099   [(set (reg:CC_Z 24)
6100         (compare:CC_Z
6101          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
6102                     (const_int 24))
6103          (match_operand 1 "const_int_operand" "")))
6104    (clobber (match_scratch:SI 2 ""))]
6105   "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
6106    == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
6107   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
6108    (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
6109   "
6110   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
6113 (define_expand "prologue"
6114   [(clobber (const_int 0))]
6115   ""
6116   "
6117   arm_expand_prologue ();
6118   DONE;
6121 ;; This split is only used during output to reduce the number of patterns
6122 ;; that need assembler instructions adding to them.  We allowed the setting
6123 ;; of the conditions to be implicit during rtl generation so that
6124 ;; the conditional compare patterns would work.  However this conflicts to
6125 ;; some extent with the conditional data operations, so we have to split them
6126 ;; up again here.
6128 (define_split
6129   [(set (match_operand:SI 0 "s_register_operand" "")
6130         (if_then_else:SI (match_operator 1 "comparison_operator"
6131                           [(match_operand 2 "" "") (match_operand 3 "" "")])
6132                          (match_operand 4 "" "")
6133                          (match_operand 5 "" "")))
6134    (clobber (reg:CC 24))]
6135   "reload_completed"
6136   [(set (match_dup 6) (match_dup 7))
6137    (set (match_dup 0) 
6138         (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
6139                          (match_dup 4)
6140                          (match_dup 5)))]
6141   "
6143   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
6144                                            operands[3]);
6146   operands[6] = gen_rtx_REG (mode, 24);
6147   operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
6151 ;; The next two patterns occur when an AND operation is followed by a
6152 ;; scc insn sequence 
6154 (define_insn "*sign_extract_onebit"
6155   [(set (match_operand:SI 0 "s_register_operand" "=r")
6156         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6157                          (const_int 1)
6158                          (match_operand:SI 2 "const_int_operand" "n")))]
6159   ""
6160   "*
6161   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6162   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6163   return \"mvnne\\t%0, #0\";
6165 [(set_attr "conds" "clob")
6166  (set_attr "length" "8")])
6168 (define_insn "*not_signextract_onebit"
6169   [(set (match_operand:SI 0 "s_register_operand" "=r")
6170         (not:SI
6171          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6172                           (const_int 1)
6173                           (match_operand:SI 2 "const_int_operand" "n"))))]
6174   ""
6175   "*
6176   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6177   output_asm_insn (\"tst\\t%1, %2\", operands);
6178   output_asm_insn (\"mvneq\\t%0, #0\", operands);
6179   return \"movne\\t%0, #0\";
6181 [(set_attr "conds" "clob")
6182  (set_attr "length" "12")])
6184 ;; Push multiple registers to the stack.  The first register is in the
6185 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
6186 ;; expressions.
6187 (define_insn "*push_multi"
6188   [(match_parallel 2 "multi_register_push"
6189     [(set (match_operand:BLK 0 "memory_operand" "=m")
6190           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
6191   ""
6192   "*
6194   char pattern[100];
6195   int i;
6196   extern int lr_save_eliminated;
6198   if (lr_save_eliminated)
6199     {
6200       if (XVECLEN (operands[2], 0) > 1)
6201         abort ();
6202       return \"\";
6203     }
6204   strcpy (pattern, \"stmfd\\t%m0!, {%1\");
6205   for (i = 1; i < XVECLEN (operands[2], 0); i++)
6206     {
6207       strcat (pattern, \", %|\");
6208       strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
6209                                               0))]);
6210     }
6211   strcat (pattern, \"}\");
6212   output_asm_insn (pattern, operands);
6213   return \"\";
6215 [(set_attr "type" "store4")])
6217 ;; Similarly for the floating point registers
6218 (define_insn "*push_fp_multi"
6219   [(match_parallel 2 "multi_register_push"
6220     [(set (match_operand:BLK 0 "memory_operand" "=m")
6221           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
6222   ""
6223   "*
6225   char pattern[100];
6226   int i;
6228   sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
6229   output_asm_insn (pattern, operands);
6230   return \"\";
6232 [(set_attr "type" "f_store")])
6234 ;; Special patterns for dealing with the constant pool
6236 (define_insn "consttable_4"
6237   [(unspec_volatile [(match_operand 0 "" "")] 2)]
6238   ""
6239   "*
6241   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6242     {
6243     case MODE_FLOAT:
6244     {
6245       union real_extract u;
6246       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6247       assemble_real (u.d, GET_MODE (operands[0]));
6248       break;
6249     }
6250     default:
6251       assemble_integer (operands[0], 4, 1);
6252       break;
6253     }
6254   return \"\";
6256 [(set_attr "length" "4")])
6258 (define_insn "consttable_8"
6259   [(unspec_volatile [(match_operand 0 "" "")] 3)]
6260   ""
6261   "*
6263   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6264     {
6265     case MODE_FLOAT:
6266     {
6267       union real_extract u;
6268       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6269       assemble_real (u.d, GET_MODE (operands[0]));
6270       break;
6271     }
6272     default:
6273       assemble_integer (operands[0], 8, 1);
6274       break;
6275     }
6276   return \"\";
6278 [(set_attr "length" "8")])
6280 (define_insn "consttable_end"
6281   [(unspec_volatile [(const_int 0)] 4)]
6282   ""
6283   "*
6284   /* Nothing to do (currently).  */
6285   return \"\";
6288 (define_insn "align_4"
6289   [(unspec_volatile [(const_int 0)] 5)]
6290   ""
6291   "*
6292   assemble_align (32);
6293   return \"\";