(movhi): Handle generation of large constants during
[official-gcc.git] / gcc / config / arm / arm.md
blob33cce5467176b467d02784b67a596103c9b2a9b6
1 ;;- Machine description for Advanced RISC Machines' ARM for GNU compiler
2 ;;  Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
3 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
4 ;;             and Martin Simmons (@harleqn.co.uk).
5 ;;  More major hacks by Richard Earnshaw (rwe11@cl.cam.ac.uk)
7 ;; This file is part of GNU CC.
9 ;; GNU CC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
14 ;; GNU CC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU CC; see the file COPYING.  If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26 ;; There are patterns in this file to support XFmode arithmetic.
27 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
28 ;; (See arm.h)
30 ;; UNSPEC Usage:
31 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
32 ;;   the mode is MODE_FLOAT
33 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
34 ;;   the mode is MODE_FLOAT
35 ;; 2 `push multiple' operation: operand 0 is the first register.  Subsequent
36 ;;   registers are in parallel (use...) expressions.
37 ;; 3 A symbol that has been treated properly for pic usage, that is, we
38 ;;   will add the pic_register value to it before trying to dereference it.
40 ;; Attributes
42 ; PROG_MODE attribute is used to determine whether condition codes are
43 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
44 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
45 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
47 ; CPU attribute is used to determine whether condition codes are clobbered
48 ; by a call insn: on the arm6 they are if in 32-bit addressing mode; on the
49 ; arm2 and arm3 the condition codes are restored by the return.
51 (define_attr "cpu" "arm2,arm3,arm6,arm7"
52         (const (symbol_ref "arm_cpu_attr")))
54 ; Floating Point Unit.  If we only have floating point emulation, then there
55 ; is no point in scheduling the floating point insns.  (Well, for best
56 ; performance we should try and group them together).
58 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
60 ; LENGTH of an instruction (in bytes)
61 (define_attr "length" "" (const_int 4))
63 ; An assembler sequence may clobber the condition codes without us knowing
64 (define_asm_attributes
65  [(set_attr "conds" "clob")
66   (set_attr "length" "4")])
68 ; TYPE attribute is used to detect floating point instructions which, if
69 ; running on a co-processor can run in parallel with other, basic instructions
70 ; If write-buffer scheduling is enabled then it can also be used in the
71 ; scheduling of writes.
73 ; Classification of each insn
74 ; normal        any data instruction that doesn't hit memory or fp regs
75 ; mult          a multiply instruction
76 ; block         blockage insn, this blocks all functional units
77 ; float         a floating point arithmetic operation (subject to expansion)
78 ; fdivx         XFmode floating point division
79 ; fdivd         DFmode floating point division
80 ; fdivs         SFmode floating point division
81 ; fmul          Floating point multiply
82 ; ffmul         Fast floating point multiply
83 ; farith        Floating point arithmetic (4 cycle)
84 ; ffarith       Fast floating point arithmetic (2 cycle)
85 ; float_em      a floating point arithmetic operation that is normally emulated
86 ;               even on a machine with an fpa.
87 ; f_load        a floating point load from memory
88 ; f_store       a floating point store to memory
89 ; f_mem_r       a transfer of a floating point register to a real reg via mem
90 ; r_mem_f       the reverse of f_mem_r
91 ; f_2_r         fast transfer float to arm (no memory needed)
92 ; r_2_f         fast transfer arm to float
93 ; call          a subroutine call
94 ; load          any load from memory
95 ; store1        store 1 word to memory from arm registers
96 ; store2        store 2 words
97 ; store3        store 3 words
98 ; store4        store 4 words
100 (define_attr "type"
101         "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" 
102         (const_string "normal"))
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 (define_attr "write_conflict" "no,yes"
132   (if_then_else (eq_attr "type"
133                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
134                 (const_string "yes")
135                 (const_string "no")))
137 (define_attr "core_cycles" "single,multi"
138   (if_then_else (eq_attr "type"
139                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
140                 (const_string "single")
141                 (const_string "multi")))
143 ; The write buffer on some of the arm6 processors is hard to model exactly.
144 ; There is room in the buffer for up to two addresses and up to eight words
145 ; of memory, but the two needn't be split evenly.  When writing the two
146 ; addresses are fully pipelined.  However, a read from memory that is not
147 ; currently in the cache will block until the writes have completed.
148 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
149 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
150 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
151 ; cycle to add as well.
153 ;; (define_function_unit {name} {num-units} {n-users} {test}
154 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
155 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
156                                      (eq_attr "type" "fdivx")) 71 69)
158 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
159                                      (eq_attr "type" "fdivd")) 59 57)
161 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
162                                      (eq_attr "type" "fdivs")) 31 29)
164 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
165                                      (eq_attr "type" "fmul")) 9 7)
167 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
168                                      (eq_attr "type" "ffmul")) 6 4)
170 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
171                                      (eq_attr "type" "farith")) 4 2)
173 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
174                                      (eq_attr "type" "ffarith")) 2 2)
176 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
177                                      (eq_attr "type" "r_2_f")) 5 3)
179 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
180                                      (eq_attr "type" "f_2_r")) 1 2)
182 ;; The fpa10 doesn't really have a memory read unit, but it can start to
183 ;; speculatively execute the instruction in the pipeline, provided the data
184 ;; is already loaded, so pretend reads have a delay of 2 (and that the
185 ;; pipeline is infinite.
187 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
188                                          (eq_attr "type" "f_load")) 3 1)
190 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store1") 5 3)
191 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store2") 7 4)
192 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store3") 9 5)
193 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store4") 11 6)
194 (define_function_unit "write_buf" 1 2 (eq_attr "type" "r_mem_f") 5 3)
196 ;; The write_blockage unit models (partially), the fact that writes will stall
197 ;; until the write buffer empties.
199 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store1") 5 5
200         [(eq_attr "write_conflict" "yes")])
201 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store2") 7 7
202         [(eq_attr "write_conflict" "yes")])
203 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store3") 9 9
204         [(eq_attr "write_conflict" "yes")])
205 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store4") 11 11
206         [(eq_attr "write_conflict" "yes")])
207 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "r_mem_f") 5 5
208         [(eq_attr "write_conflict" "yes")])
209 (define_function_unit "write_blockage" 1 0 
210         (eq_attr "write_conflict" "yes") 1 1)
212 (define_function_unit "core" 1 1 (eq_attr "core_cycles" "single") 1 1)
214 (define_function_unit "core" 1 1 (eq_attr "type" "load") 2 2)
216 (define_function_unit "core" 1 1 (eq_attr "type" "mult") 16 16)
218 (define_function_unit "core" 1 1 (eq_attr "type" "store1") 2 2)
220 (define_function_unit "core" 1 1 (eq_attr "type" "store2") 3 3)
222 (define_function_unit "core" 1 1 (eq_attr "type" "store3") 4 4)
224 (define_function_unit "core" 1 1 (eq_attr "type" "store4") 5 5)
226 (define_function_unit "core" 1 1
227   (and (eq_attr "core_cycles" "multi")
228        (eq_attr "type" "!mult,load,store2,store3,store4")) 32 32)
231 ;; Note: For DImode insns, there is normally no reason why operands should
232 ;; not be in the same register, what we don't want is for something being
233 ;; written to partially overlap something that is an input.
235 ;; Addition insns.
237 (define_insn "adddi3"
238   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
239         (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
240                  (match_operand:DI 2 "s_register_operand" "r,0")))
241    (clobber (reg:CC 24))]
242   ""
243   "adds\\t%Q0, %Q1, %Q2\;adc\\t%R0, %R1, %R2"
244 [(set_attr "conds" "clob")
245  (set_attr "length" "8")])
247 (define_insn "*adddi_sesidi_di"
248   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
249         (plus:DI (sign_extend:DI
250                   (match_operand:SI 2 "s_register_operand" "r,r"))
251                  (match_operand:DI 1 "s_register_operand" "r,0")))
252    (clobber (reg:CC 24))]
253   ""
254   "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, %2, asr #31"
255 [(set_attr "conds" "clob")
256  (set_attr "length" "8")])
258 (define_insn "*adddi_zesidi_di"
259   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
260         (plus:DI (zero_extend:DI
261                   (match_operand:SI 2 "s_register_operand" "r,r"))
262                  (match_operand:DI 1 "s_register_operand" "r,0")))
263    (clobber (reg:CC 24))]
264   ""
265   "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, #0"
266 [(set_attr "conds" "clob")
267  (set_attr "length" "8")])
269 (define_expand "addsi3"
270   [(set (match_operand:SI 0 "s_register_operand" "")
271         (plus:SI (match_operand:SI 1 "s_register_operand" "")
272                  (match_operand:SI 2 "reg_or_int_operand" "")))]
273   ""
274   "
275   if (GET_CODE (operands[2]) == CONST_INT)
276     {
277       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
278                           operands[1],
279                           (reload_in_progress || reload_completed ? 0
280                            : preserve_subexpressions_p ()));
281       DONE;
282     }
285 (define_split
286   [(set (match_operand:SI 0 "s_register_operand" "")
287         (plus:SI (match_operand:SI 1 "s_register_operand" "")
288                  (match_operand:SI 2 "const_int_operand" "")))]
289   "! (const_ok_for_arm (INTVAL (operands[2]))
290       || const_ok_for_arm (-INTVAL (operands[2])))"
291   [(clobber (const_int 0))]
292   "
293   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
294                       operands[1], 0);
295   DONE;
298 (define_insn "*addsi3_insn"
299   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
300         (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
301                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
302   ""
303   "@
304    add%?\\t%0, %1, %2
305    sub%?\\t%0, %1, #%n2
306    #"
307 [(set_attr "length" "4,4,16")])
309 (define_insn "*addsi3_compare0"
310   [(set (reg:CC_NOOV 24)
311         (compare:CC_NOOV
312          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
313                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
314          (const_int 0)))
315    (set (match_operand:SI 0 "s_register_operand" "=r,r")
316         (plus:SI (match_dup 1) (match_dup 2)))]
317   ""
318   "@
319    add%?s\\t%0, %1, %2
320    sub%?s\\t%0, %1, #%n2"
321 [(set_attr "conds" "set")])
323 (define_insn "*addsi3_compare0_scratch"
324   [(set (reg:CC_NOOV 24)
325         (compare:CC_NOOV
326          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
327                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
328          (const_int 0)))]
329   ""
330   "@
331    cmn%?\\t%0, %1
332    cmp%?\\t%0, #%n1"
333 [(set_attr "conds" "set")])
335 ;; The next four insns work because they compare the result with one of
336 ;; the operands, and we know that the use of the condition code is
337 ;; either GEU or LTU, so we can use the carry flag from the addition
338 ;; instead of doing the compare a second time.
339 (define_insn "*addsi3_compare_op1"
340   [(set (reg:CC_C 24)
341         (compare:CC_C
342          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
343                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
344          (match_dup 1)))
345    (set (match_operand:SI 0 "s_register_operand" "=r,r")
346         (plus:SI (match_dup 1) (match_dup 2)))]
347   ""
348   "@
349    add%?s\\t%0, %1, %2
350    sub%?s\\t%0, %1, #%n2"
351 [(set_attr "conds" "set")])
353 (define_insn "*addsi3_compare_op2"
354   [(set (reg:CC_C 24)
355         (compare:CC_C
356          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
357                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
358          (match_dup 2)))
359    (set (match_operand:SI 0 "s_register_operand" "=r,r")
360         (plus:SI (match_dup 1) (match_dup 2)))]
361   ""
362   "@
363    add%?s\\t%0, %1, %2
364    sub%?s\\t%0, %1, #%n2"
365 [(set_attr "conds" "set")])
367 (define_insn "*compare_addsi2_op0"
368   [(set (reg:CC_C 24)
369         (compare:CC_C
370          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
371                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
372          (match_dup 0)))]
373   ""
374   "@
375    cmn%?\\t%0, %1
376    cmp%?\\t%0, #%n1"
377 [(set_attr "conds" "set")])
379 (define_insn "*compare_addsi2_op1"
380   [(set (reg:CC_C 24)
381         (compare:CC_C
382          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
383                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
384          (match_dup 1)))]
385   ""
386   "@
387    cmn%?\\t%0, %1
388    cmp%?\\t%0, #%n1"
389 [(set_attr "conds" "set")])
391 (define_insn "*addsi3_carryin"
392   [(set (match_operand:SI 0 "s_register_operand" "=r")
393         (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
394                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
395                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
396   ""
397   "adc%?\\t%0, %1, %2"
398 [(set_attr "conds" "use")])
400 (define_insn "*addsi3_carryin_alt1"
401   [(set (match_operand:SI 0 "s_register_operand" "=r")
402         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
403                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
404                  (ltu:SI (reg:CC_C 24) (const_int 0))))]
405   ""
406   "adc%?\\t%0, %1, %2"
407 [(set_attr "conds" "use")])
409 (define_insn "*addsi3_carryin_alt2"
410   [(set (match_operand:SI 0 "s_register_operand" "=r")
411         (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
412                           (match_operand:SI 1 "s_register_operand" "r"))
413                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
414   ""
415   "adc%?\\t%0, %1, %2"
416 [(set_attr "conds" "use")])
418 (define_insn "*addsi3_carryin_alt3"
419   [(set (match_operand:SI 0 "s_register_operand" "=r")
420         (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
421                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
422                  (match_operand:SI 1 "s_register_operand" "r")))]
423   ""
424   "adc%?\\t%0, %1, %2"
425 [(set_attr "conds" "use")])
427 (define_insn "incscc"
428   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
429         (plus:SI (match_operator:SI 2 "comparison_operator"
430                     [(reg 24) (const_int 0)])
431                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
432   ""
433   "@
434   add%d2\\t%0, %1, #1
435   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
436 [(set_attr "conds" "use")
437  (set_attr "length" "4,8")])
439 ; If a constant is too big to fit in a single instruction then the constant
440 ; will be pre-loaded into a register taking at least two insns, we might be
441 ; able to merge it with an add, but it depends on the exact value.
443 (define_split
444   [(set (match_operand:SI 0 "s_register_operand" "=r")
445         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
446                  (match_operand:SI 2 "const_int_operand" "n")))]
447   "!(const_ok_for_arm (INTVAL (operands[2]))
448      || const_ok_for_arm (-INTVAL (operands[2])))"
449   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
450    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
451   "
453   unsigned int val = (unsigned) INTVAL (operands[2]);
454   int i;
455   unsigned int temp;
457   /* this code is similar to the approach followed in movsi, but it must
458      generate exactly two insns */
460   for (i = 30; i >= 0; i -= 2)
461     {
462       if (val & (3 << i))
463         {
464           i -= 6;
465           if (i < 0) i = 0;
466           if (const_ok_for_arm (temp = (val & ~(255 << i))))
467             {
468               val &= 255 << i;
469               break;
470             }
471           /* we might be able to do this as (larger number - small number) */
472           temp = ((val >> i) & 255) + 1;
473           if (temp > 255 && i < 24)
474             {
475               i += 2;
476               temp = ((val >> i) & 255) + 1;
477             }
478           if (const_ok_for_arm ((temp << i) - val))
479             {
480               i = temp << i;
481               temp = (unsigned) - (int) (i - val);
482               val = i;
483               break;
484             }
485           FAIL;
486         }
487     }
488   /* if we got here, we have found a way of doing it in two instructions.
489      the two constants are in val and temp */
490   operands[2] = GEN_INT ((int)val);
491   operands[3] = GEN_INT ((int)temp);
495 (define_insn "addsf3"
496   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
497         (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
498                  (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
499   "TARGET_HARD_FLOAT"
500   "@
501    adf%?s\\t%0, %1, %2
502    suf%?s\\t%0, %1, #%N2"
503 [(set_attr "type" "farith")])
505 (define_insn "adddf3"
506   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
507         (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
508                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
509   "TARGET_HARD_FLOAT"
510   "@
511    adf%?d\\t%0, %1, %2
512    suf%?d\\t%0, %1, #%N2"
513 [(set_attr "type" "farith")])
515 (define_insn "*adddf_df_esfdf"
516   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
517         (plus:DF (float_extend:DF
518                   (match_operand:SF 1 "s_register_operand" "f,f"))
519                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
520   "TARGET_HARD_FLOAT"
521   "@
522    adf%?d\\t%0, %1, %2
523    suf%?d\\t%0, %1, #%N2"
524 [(set_attr "type" "farith")])
526 (define_insn "*adddf_df_esfdf"
527   [(set (match_operand:DF 0 "s_register_operand" "=f")
528         (plus:DF (match_operand:DF 1 "s_register_operand" "f")
529                  (float_extend:DF
530                   (match_operand:SF 2 "s_register_operand" "f"))))]
531   "TARGET_HARD_FLOAT"
532   "adf%?d\\t%0, %1, %2"
533 [(set_attr "type" "farith")])
535 (define_insn "*adddf_esfdf_esfdf"
536   [(set (match_operand:DF 0 "s_register_operand" "=f")
537         (plus:DF (float_extend:DF 
538                   (match_operand:SF 1 "s_register_operand" "f"))
539                  (float_extend:DF
540                   (match_operand:SF 2 "s_register_operand" "f"))))]
541   "TARGET_HARD_FLOAT"
542   "adf%?d\\t%0, %1, %2"
543 [(set_attr "type" "farith")])
545 (define_insn "addxf3"
546   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
547         (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
548                  (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
549   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
550   "@
551    adf%?e\\t%0, %1, %2
552    suf%?e\\t%0, %1, #%N2"
553 [(set_attr "type" "farith")])
555 (define_insn "subdi3"
556   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
557         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
558                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
559    (clobber (reg:CC 24))]
560   ""
561   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
562 [(set_attr "conds" "clob")
563  (set_attr "length" "8")])
565 (define_insn "*subdi_di_zesidi"
566   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
567         (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
568                   (zero_extend:DI
569                    (match_operand:SI 2 "s_register_operand" "r,r"))))
570    (clobber (reg:CC 24))]
571   ""
572   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
573 [(set_attr "conds" "clob")
574  (set_attr "length" "8")])
576 (define_insn "*subdi_di_sesidi"
577   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
578         (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
579                   (sign_extend:DI
580                    (match_operand:SI 2 "s_register_operand" "r,r"))))
581    (clobber (reg:CC 24))]
582   ""
583   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
584 [(set_attr "conds" "clob")
585  (set_attr "length" "8")])
587 (define_insn "*subdi_zesidi_di"
588   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
589         (minus:DI (zero_extend:DI
590                    (match_operand:SI 2 "s_register_operand" "r,r"))
591                   (match_operand:DI 1 "s_register_operand" "?r,0")))
592    (clobber (reg:CC 24))]
593   ""
594   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
595 [(set_attr "conds" "clob")
596  (set_attr "length" "8")])
598 (define_insn "*subdi_sesidi_di"
599   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
600         (minus:DI (sign_extend:DI
601                    (match_operand:SI 2 "s_register_operand" "r,r"))
602                   (match_operand:DI 1 "s_register_operand" "?r,0")))
603    (clobber (reg:CC 24))]
604   ""
605   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
606 [(set_attr "conds" "clob")
607  (set_attr "length" "8")])
609 (define_insn "*subdi_zesidi_zesidi"
610   [(set (match_operand:DI 0 "s_register_operand" "=r")
611         (minus:DI (zero_extend:DI
612                    (match_operand:SI 1 "s_register_operand" "r"))
613                   (zero_extend:DI
614                    (match_operand:SI 2 "s_register_operand" "r"))))
615    (clobber (reg:CC 24))]
616   ""
617   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
618 [(set_attr "conds" "clob")
619  (set_attr "length" "8")])
621 (define_expand "subsi3"
622   [(set (match_operand:SI 0 "s_register_operand" "")
623         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
624                   (match_operand:SI 2 "s_register_operand" "")))]
625   ""
626   "
627   if (GET_CODE (operands[1]) == CONST_INT)
628     {
629       arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
630                           operands[2],
631                           (reload_in_progress || reload_completed ? 0
632                            : preserve_subexpressions_p ()));
633       DONE;
634     }
637 (define_insn "*subsi3_insn"
638   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
639         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
640                   (match_operand:SI 2 "s_register_operand" "r,r")))]
641   ""
642   "@
643    rsb%?\\t%0, %2, %1
644    #"
645 [(set_attr "length" "4,16")])
647 (define_split
648   [(set (match_operand:SI 0 "s_register_operand" "")
649         (minus:SI (match_operand:SI 1 "const_int_operand" "")
650                   (match_operand:SI 2 "s_register_operand" "")))]
651   "! const_ok_for_arm (INTVAL (operands[1]))"
652   [(clobber (const_int 0))]
653   "
654   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
655                       operands[2], 0);
656   DONE;
659 (define_insn "*subsi3_compare0"
660   [(set (reg:CC_NOOV 24)
661         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
662                                  (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
663                          (const_int 0)))
664    (set (match_operand:SI 0 "s_register_operand" "=r,r")
665         (minus:SI (match_dup 1) (match_dup 2)))]
666   ""
667   "@
668    sub%?s\\t%0, %1, %2
669    rsb%?s\\t%0, %2, %1"
670 [(set_attr "conds" "set")])
672 (define_insn "decscc"
673   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
674         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
675                   (match_operator:SI 2 "comparison_operator"
676                    [(reg 24) (const_int 0)])))]
677   ""
678   "@
679   sub%d2\\t%0, %1, #1
680   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
681 [(set_attr "conds" "use")
682  (set_attr "length" "*,8")])
684 (define_insn "subsf3"
685   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
686         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
687                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
688   "TARGET_HARD_FLOAT"
689   "@
690    suf%?s\\t%0, %1, %2
691    rsf%?s\\t%0, %2, %1"
692 [(set_attr "type" "farith")])
694 (define_insn "subdf3"
695   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
696         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
697                   (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
698   "TARGET_HARD_FLOAT"
699   "@
700    suf%?d\\t%0, %1, %2
701    rsf%?d\\t%0, %2, %1"
702 [(set_attr "type" "farith")])
704 (define_insn "*subdf_esfdf_df"
705   [(set (match_operand:DF 0 "s_register_operand" "=f")
706         (minus:DF (float_extend:DF
707                    (match_operand:SF 1 "s_register_operand" "f"))
708                   (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
709   "TARGET_HARD_FLOAT"
710   "suf%?d\\t%0, %1, %2"
711 [(set_attr "type" "farith")])
713 (define_insn "*subdf_df_esfdf"
714   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
715         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
716                   (float_extend:DF
717                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
718   "TARGET_HARD_FLOAT"
719   "@
720    suf%?d\\t%0, %1, %2
721    rsf%?d\\t%0, %2, %1"
722 [(set_attr "type" "farith")])
724 (define_insn "*subdf_esfdf_esfdf"
725   [(set (match_operand:DF 0 "s_register_operand" "=f")
726         (minus:DF (float_extend:DF
727                    (match_operand:SF 1 "s_register_operand" "f"))
728                   (float_extend:DF
729                    (match_operand:SF 2 "s_register_operand" "f"))))]
730   "TARGET_HARD_FLOAT"
731   "suf%?d\\t%0, %1, %2"
732 [(set_attr "type" "farith")])
734 (define_insn "subxf3"
735   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
736         (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
737                   (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
738   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
739   "@
740    suf%?e\\t%0, %1, %2
741    rsf%?e\\t%0, %2, %1"
742 [(set_attr "type" "farith")])
744 ;; Multiplication insns
746 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
747 (define_insn "mulsi3"
748   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
749         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
750                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
751   ""
752   "mul%?\\t%0, %2, %1"
753 [(set_attr "type" "mult")])
755 (define_insn "*mulsi3_compare0"
756   [(set (reg:CC_NOOV 24)
757         (compare:CC_NOOV (mult:SI
758                           (match_operand:SI 2 "s_register_operand" "r,r")
759                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
760                          (const_int 0)))
761    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
762         (mult:SI (match_dup 2) (match_dup 1)))]
763   ""
764   "mul%?s\\t%0, %2, %1"
765 [(set_attr "conds" "set")
766  (set_attr "type" "mult")])
768 (define_insn "*mulsi_compare0_scratch"
769   [(set (reg:CC_NOOV 24)
770         (compare:CC_NOOV (mult:SI
771                           (match_operand:SI 2 "s_register_operand" "r,r")
772                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
773                          (const_int 0)))
774    (clobber (match_scratch:SI 0 "=&r,&r"))]
775   ""
776   "mul%?s\\t%0, %2, %1"
777 [(set_attr "conds" "set")
778  (set_attr "type" "mult")])
780 ;; Unnamed templates to match MLA instruction.
782 (define_insn "*mulsi3addsi"
783   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
784         (plus:SI
785           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
786                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
787           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
788   ""
789   "mla%?\\t%0, %2, %1, %3"
790 [(set_attr "type" "mult")])
792 (define_insn "*mulsi3addsi_compare0"
793   [(set (reg:CC_NOOV 24)
794         (compare:CC_NOOV (plus:SI
795                           (mult:SI
796                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
797                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
798                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
799                          (const_int 0)))
800    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
801         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
802                  (match_dup 3)))]
803   ""
804   "mla%?s\\t%0, %2, %1, %3"
805 [(set_attr "conds" "set")
806  (set_attr "type" "mult")])
808 (define_insn "*mulsi3addsi_compare0_scratch"
809   [(set (reg:CC_NOOV 24)
810         (compare:CC_NOOV (plus:SI
811                           (mult:SI
812                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
813                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
814                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
815                          (const_int 0)))
816    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
817   ""
818   "mla%?s\\t%0, %2, %1, %3"
819 [(set_attr "conds" "set")
820  (set_attr "type" "mult")])
822 (define_insn "mulsidi3"
823   [(set (match_operand:DI 0 "s_register_operand" "=&r")
824       (mult:DI (sign_extend:DI
825                 (match_operand:SI 1 "s_register_operand" "%r"))
826                (sign_extend:DI
827                (match_operand:SI 2 "s_register_operand" "r"))))]
828   "arm_fast_multiply"
829   "smull%?\\t%Q0, %R0, %1, %2"
830 [(set_attr "type" "mult")])
832 (define_insn "umulsidi3"
833   [(set (match_operand:DI 0 "s_register_operand" "=&r")
834       (mult:DI (zero_extend:DI
835                 (match_operand:SI 1 "s_register_operand" "%r"))
836                (zero_extend:DI
837                 (match_operand:SI 2 "s_register_operand" "r"))))]
838   "arm_fast_multiply"
839   "umull%?\\t%Q0, %R0, %1, %2"
840 [(set_attr "type" "mult")])
842 (define_insn "mulsf3"
843   [(set (match_operand:SF 0 "s_register_operand" "=f")
844         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
845                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
846   "TARGET_HARD_FLOAT"
847   "fml%?s\\t%0, %1, %2"
848 [(set_attr "type" "ffmul")])
850 (define_insn "muldf3"
851   [(set (match_operand:DF 0 "s_register_operand" "=f")
852         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
853                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
854   "TARGET_HARD_FLOAT"
855   "muf%?d\\t%0, %1, %2"
856 [(set_attr "type" "fmul")])
858 (define_insn "*muldf_esfdf_df"
859   [(set (match_operand:DF 0 "s_register_operand" "=f")
860         (mult:DF (float_extend:DF
861                   (match_operand:SF 1 "s_register_operand" "f"))
862                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
863   "TARGET_HARD_FLOAT"
864   "muf%?d\\t%0, %1, %2"
865 [(set_attr "type" "fmul")])
867 (define_insn "*muldf_df_esfdf"
868   [(set (match_operand:DF 0 "s_register_operand" "=f")
869         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
870                  (float_extend:DF
871                   (match_operand:SF 2 "s_register_operand" "f"))))]
872   "TARGET_HARD_FLOAT"
873   "muf%?d\\t%0, %1, %2"
874 [(set_attr "type" "fmul")])
876 (define_insn "*muldf_esfdf_esfdf"
877   [(set (match_operand:DF 0 "s_register_operand" "=f")
878         (mult:DF (float_extend:DF
879                   (match_operand:SF 1 "s_register_operand" "f"))
880                  (float_extend:DF
881                   (match_operand:SF 2 "s_register_operand" "f"))))]
882   "TARGET_HARD_FLOAT"
883   "muf%?d\\t%0, %1, %2"
884 [(set_attr "type" "fmul")])
886 (define_insn "mulxf3"
887   [(set (match_operand:XF 0 "s_register_operand" "=f")
888         (mult:XF (match_operand:XF 1 "s_register_operand" "f")
889                  (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
890   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
891   "muf%?e\\t%0, %1, %2"
892 [(set_attr "type" "fmul")])
894 ;; Division insns
896 (define_insn "divsf3"
897   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
898         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
899                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
900   "TARGET_HARD_FLOAT"
901   "@
902    fdv%?s\\t%0, %1, %2
903    frd%?s\\t%0, %2, %1"
904 [(set_attr "type" "fdivs")])
906 (define_insn "divdf3"
907   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
908         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
909                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
910   "TARGET_HARD_FLOAT"
911   "@
912    dvf%?d\\t%0, %1, %2
913    rdf%?d\\t%0, %2, %1"
914 [(set_attr "type" "fdivd")])
916 (define_insn "*divdf_esfdf_df"
917   [(set (match_operand:DF 0 "s_register_operand" "=f")
918         (div:DF (float_extend:DF
919                  (match_operand:SF 1 "s_register_operand" "f"))
920                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
921   "TARGET_HARD_FLOAT"
922   "dvf%?d\\t%0, %1, %2"
923 [(set_attr "type" "fdivd")])
925 (define_insn "*divdf_df_esfdf"
926   [(set (match_operand:DF 0 "s_register_operand" "=f")
927         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
928                 (float_extend:DF
929                  (match_operand:SF 2 "s_register_operand" "f"))))]
930   "TARGET_HARD_FLOAT"
931   "rdf%?d\\t%0, %2, %1"
932 [(set_attr "type" "fdivd")])
934 (define_insn "*divdf_esfdf_esfdf"
935   [(set (match_operand:DF 0 "s_register_operand" "=f")
936         (div:DF (float_extend:DF
937                  (match_operand:SF 1 "s_register_operand" "f"))
938                 (float_extend:DF
939                  (match_operand:SF 2 "s_register_operand" "f"))))]
940   "TARGET_HARD_FLOAT"
941   "dvf%?d\\t%0, %1, %2"
942 [(set_attr "type" "fdivd")])
944 (define_insn "divxf3"
945   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
946         (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
947                 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
948   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
949   "@
950    dvf%?e\\t%0, %1, %2
951    rdf%?e\\t%0, %2, %1"
952 [(set_attr "type" "fdivx")])
954 ;; Modulo insns
956 (define_insn "modsf3"
957   [(set (match_operand:SF 0 "s_register_operand" "=f")
958         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
959                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
960   "TARGET_HARD_FLOAT"
961   "rmf%?s\\t%0, %1, %2"
962 [(set_attr "type" "fdivs")])
964 (define_insn "moddf3"
965   [(set (match_operand:DF 0 "s_register_operand" "=f")
966         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
967                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
968   "TARGET_HARD_FLOAT"
969   "rmf%?d\\t%0, %1, %2"
970 [(set_attr "type" "fdivd")])
972 (define_insn "*moddf_esfdf_df"
973   [(set (match_operand:DF 0 "s_register_operand" "=f")
974         (mod:DF (float_extend:DF
975                  (match_operand:SF 1 "s_register_operand" "f"))
976                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
977   "TARGET_HARD_FLOAT"
978   "rmf%?d\\t%0, %1, %2"
979 [(set_attr "type" "fdivd")])
981 (define_insn "*moddf_df_esfdf"
982   [(set (match_operand:DF 0 "s_register_operand" "=f")
983         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
984                 (float_extend:DF
985                  (match_operand:SF 2 "s_register_operand" "f"))))]
986   "TARGET_HARD_FLOAT"
987   "rmf%?d\\t%0, %1, %2"
988 [(set_attr "type" "fdivd")])
990 (define_insn "*moddf_esfdf_esfdf"
991   [(set (match_operand:DF 0 "s_register_operand" "=f")
992         (mod:DF (float_extend:DF
993                  (match_operand:SF 1 "s_register_operand" "f"))
994                 (float_extend:DF
995                  (match_operand:SF 2 "s_register_operand" "f"))))]
996   "TARGET_HARD_FLOAT"
997   "rmf%?d\\t%0, %1, %2"
998 [(set_attr "type" "fdivd")])
1000 (define_insn "modxf3"
1001   [(set (match_operand:XF 0 "s_register_operand" "=f")
1002         (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1003                 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1004   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1005   "rmf%?e\\t%0, %1, %2"
1006 [(set_attr "type" "fdivx")])
1008 ;; Boolean and,ior,xor insns
1010 (define_insn "anddi3"
1011   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1012         (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1013                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1014   ""
1015   "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2"
1016 [(set_attr "length" "8")])
1018 (define_insn "*anddi_zesidi_di"
1019   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1020         (and:DI (zero_extend:DI
1021                  (match_operand:SI 2 "s_register_operand" "r,r"))
1022                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1023   ""
1024   "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0"
1025 [(set_attr "length" "8")])
1027 (define_insn "*anddi_sesdi_di"
1028   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1029         (and:DI (sign_extend:DI
1030                  (match_operand:SI 2 "s_register_operand" "r,r"))
1031                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1032   ""
1033   "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31"
1034 [(set_attr "length" "8")])
1036 (define_expand "andsi3"
1037   [(set (match_operand:SI 0 "s_register_operand" "")
1038         (and:SI (match_operand:SI 1 "s_register_operand" "")
1039                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1040   ""
1041   "
1042   if (GET_CODE (operands[2]) == CONST_INT)
1043     {
1044       arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1045                           operands[1],
1046                           (reload_in_progress || reload_completed
1047                            ? 0 : preserve_subexpressions_p ()));
1048       DONE;
1049     }
1052 (define_insn "*andsi3_insn"
1053   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1054         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1055                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1056   ""
1057   "@
1058    and%?\\t%0, %1, %2
1059    bic%?\\t%0, %1, #%B2
1060    #"
1061 [(set_attr "length" "4,4,16")])
1063 (define_split
1064   [(set (match_operand:SI 0 "s_register_operand" "")
1065         (and:SI (match_operand:SI 1 "s_register_operand" "")
1066                 (match_operand:SI 2 "const_int_operand" "")))]
1067   "! (const_ok_for_arm (INTVAL (operands[2]))
1068       || const_ok_for_arm (~ INTVAL (operands[2])))"
1069   [(clobber (const_int 0))]
1070   "
1071   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1072                        operands[1], 0);
1073   DONE;
1076 (define_insn "*andsi3_compare0"
1077   [(set (reg:CC_NOOV 24)
1078         (compare:CC_NOOV
1079          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1080                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1081          (const_int 0)))
1082    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1083         (and:SI (match_dup 1) (match_dup 2)))]
1084   ""
1085   "@
1086    and%?s\\t%0, %1, %2
1087    bic%?s\\t%0, %1, #%B2"
1088 [(set_attr "conds" "set")])
1090 (define_insn "*andsi3_compare0_scratch"
1091   [(set (reg:CC_NOOV 24)
1092         (compare:CC_NOOV
1093          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1094                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1095          (const_int 0)))
1096    (clobber (match_scratch:SI 3 "=X,r"))]
1097   ""
1098   "@
1099    tst%?\\t%0, %1
1100    bic%?s\\t%3, %0, #%B1"
1101 [(set_attr "conds" "set")])
1103 (define_insn "*zeroextractsi_compare0_scratch"
1104   [(set (reg:CC_NOOV 24)
1105         (compare:CC_NOOV (zero_extract:SI
1106                           (match_operand:SI 0 "s_register_operand" "r")
1107                           (match_operand 1 "const_int_operand" "n")
1108                           (match_operand 2 "const_int_operand" "n"))
1109                          (const_int 0)))]
1110   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1111    && INTVAL (operands[1]) > 0 
1112    && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1113    && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1114   "*
1116   unsigned int mask = 0;
1117   int cnt = INTVAL (operands[1]);
1118   
1119   while (cnt--)
1120     mask = (mask << 1) | 1;
1121   operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1122   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1123   return \"\";
1126 [(set_attr "conds" "set")])
1128 (define_insn "*zeroextractqi_compare0_scratch"
1129   [(set (reg:CC_NOOV 24)
1130         (compare:CC_NOOV (zero_extract:SI
1131                           (match_operand:QI 0 "memory_operand" "m")
1132                           (match_operand 1 "const_int_operand" "n")
1133                           (match_operand 2 "const_int_operand" "n"))
1134                          (const_int 0)))
1135    (clobber (match_scratch:QI 3 "=r"))]
1136   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 8
1137    && INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8"
1138   "*
1140   unsigned int mask = 0;
1141   int cnt = INTVAL (operands[1]);
1142   
1143   while (cnt--)
1144     mask = (mask << 1) | 1;
1145   operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1146   output_asm_insn (\"ldr%?b\\t%3, %0\", operands);
1147   output_asm_insn (\"tst%?\\t%3, %1\", operands);
1148   return \"\";
1151 [(set_attr "conds" "set")
1152  (set_attr "length" "8")])
1154 ;; constants for op 2 will never be given to these patterns.
1155 (define_insn "*anddi_notdi_di"
1156   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1157         (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1158                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1159   ""
1160   "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2"
1161 [(set_attr "length" "8")])
1162   
1163 (define_insn "*anddi_notzesidi_di"
1164   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1165         (and:DI (not:DI (zero_extend:DI
1166                          (match_operand:SI 2 "s_register_operand" "r,r")))
1167                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1168   ""
1169   "@
1170    bic%?\\t%Q0, %Q1, %2
1171    bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1172 [(set_attr "length" "4,8")])
1173   
1174 (define_insn "*anddi_notsesidi_di"
1175   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1176         (and:DI (not:DI (sign_extend:DI
1177                          (match_operand:SI 2 "s_register_operand" "r,r")))
1178                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1179   ""
1180   "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
1181 [(set_attr "length" "8")])
1182   
1183 (define_insn "*andsi_notsi_si"
1184   [(set (match_operand:SI 0 "s_register_operand" "=r")
1185         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1186                 (match_operand:SI 1 "s_register_operand" "r")))]
1187   ""
1188   "bic%?\\t%0, %1, %2")
1190 (define_insn "*andsi_notsi_si_compare0"
1191   [(set (reg:CC_NOOV 24)
1192         (compare:CC_NOOV
1193          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1194                  (match_operand:SI 1 "s_register_operand" "r"))
1195          (const_int 0)))
1196    (set (match_operand:SI 0 "s_register_operand" "=r")
1197         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1198   ""
1199   "bic%?s\\t%0, %1, %2"
1200 [(set_attr "conds" "set")])
1202 (define_insn "*andsi_notsi_si_compare0_scratch"
1203   [(set (reg:CC_NOOV 24)
1204         (compare:CC_NOOV
1205          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1206                  (match_operand:SI 1 "s_register_operand" "r"))
1207          (const_int 0)))
1208    (clobber (match_scratch:SI 0 "=r"))]
1209   ""
1210   "bic%?s\\t%0, %1, %2"
1211 [(set_attr "conds" "set")])
1213 (define_insn "iordi3"
1214   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1215         (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1216                 (match_operand:DI 2 "s_register_operand" "r")))]
1217   ""
1218   "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2"
1219 [(set_attr "length" "8")])
1221 (define_insn "*iordi_zesidi_di"
1222   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1223         (ior:DI (zero_extend:DI
1224                  (match_operand:SI 2 "s_register_operand" "r,r"))
1225                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1226   ""
1227   "@
1228    orr%?\\t%Q0, %Q1, %2
1229    orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1230 [(set_attr "length" "4,8")])
1232 (define_insn "*iordi_sesidi_di"
1233   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1234         (ior:DI (sign_extend:DI
1235                  (match_operand:SI 2 "s_register_operand" "r,r"))
1236                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1237   ""
1238   "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1239 [(set_attr "length" "8")])
1241 (define_expand "iorsi3"
1242   [(set (match_operand:SI 0 "s_register_operand" "")
1243         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1244                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1245   ""
1246   "
1247   if (GET_CODE (operands[2]) == CONST_INT)
1248     {
1249       arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1250                           operands[1],
1251                           (reload_in_progress || reload_completed
1252                            ? 0 : preserve_subexpressions_p ()));
1253       DONE;
1254     }
1257 (define_insn "*iorsi3_insn"
1258   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1259         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1260                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1261   ""
1262   "@
1263    orr%?\\t%0, %1, %2
1264    #"
1265 [(set_attr "length" "4,16")])
1267 (define_split
1268   [(set (match_operand:SI 0 "s_register_operand" "")
1269         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1270                 (match_operand:SI 2 "const_int_operand" "")))]
1271   "! const_ok_for_arm (INTVAL (operands[2]))"
1272   [(clobber (const_int 0))]
1273   "
1274   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1275                       operands[1], 0);
1276   DONE;
1278   
1279 (define_insn "*iorsi3_compare0"
1280   [(set (reg:CC_NOOV 24)
1281         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1282                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1283                          (const_int 0)))
1284    (set (match_operand:SI 0 "s_register_operand" "=r")
1285         (ior:SI (match_dup 1) (match_dup 2)))]
1286   ""
1287   "orr%?s\\t%0, %1, %2"
1288 [(set_attr "conds" "set")])
1290 (define_insn "*iorsi3_compare0_scratch"
1291   [(set (reg:CC_NOOV 24)
1292         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1293                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1294                          (const_int 0)))
1295    (clobber (match_scratch:SI 0 "=r"))]
1296   ""
1297   "orr%?s\\t%0, %1, %2"
1298 [(set_attr "conds" "set")])
1300 (define_insn "xordi3"
1301   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1302         (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1303                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1304   ""
1305   "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2"
1306 [(set_attr "length" "8")])
1308 (define_insn "*xordi_zesidi_di"
1309   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1310         (xor:DI (zero_extend:DI
1311                  (match_operand:SI 2 "s_register_operand" "r,r"))
1312                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1313   ""
1314   "@
1315    eor%?\\t%Q0, %Q1, %2
1316    eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1317 [(set_attr "length" "4,8")])
1319 (define_insn "*xordi_sesidi_di"
1320   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1321         (xor:DI (sign_extend:DI
1322                  (match_operand:SI 2 "s_register_operand" "r,r"))
1323                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1324   ""
1325   "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1326 [(set_attr "length" "8")])
1328 (define_insn "xorsi3"
1329   [(set (match_operand:SI 0 "s_register_operand" "=r")
1330         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1331                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1332   ""
1333   "eor%?\\t%0, %1, %2")
1335 (define_insn "*xorsi3_compare0"
1336   [(set (reg:CC_NOOV 24)
1337         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1338                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1339                          (const_int 0)))
1340    (set (match_operand:SI 0 "s_register_operand" "=r")
1341         (xor:SI (match_dup 1) (match_dup 2)))]
1342   ""
1343   "eor%?s\\t%0, %1, %2"
1344 [(set_attr "conds" "set")])
1346 (define_insn "*xorsi3_compare0_scratch"
1347   [(set (reg:CC_NOOV 24)
1348         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1349                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
1350                          (const_int 0)))]
1351   ""
1352   "teq%?\\t%0, %1"
1353 [(set_attr "conds" "set")])
1355 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
1356 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1357 ;; insns
1359 (define_split
1360   [(set (match_operand:SI 0 "s_register_operand" "=r")
1361         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1362                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1363                 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1364    (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1365   ""
1366   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1367                               (not:SI (match_dup 3))))
1368    (set (match_dup 0) (not:SI (match_dup 4)))]
1369   ""
1372 (define_insn "*andsi_iorsi3_notsi"
1373   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1374         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1375                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1376                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1377   ""
1378   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1379 [(set_attr "length" "8")])
1383 ;; Minimum and maximum insns
1385 (define_insn "smaxsi3"
1386   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1387         (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1388                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1389    (clobber (reg:CC 24))]
1390   ""
1391   "@
1392    cmp\\t%1, %2\;movlt\\t%0, %2
1393    cmp\\t%1, %2\;movge\\t%0, %1
1394    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1395 [(set_attr "conds" "clob")
1396  (set_attr "length" "8,8,12")])
1398 (define_insn "sminsi3"
1399   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1400         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1401                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1402    (clobber (reg:CC 24))]
1403   ""
1404   "@
1405    cmp\\t%1, %2\;movge\\t%0, %2
1406    cmp\\t%1, %2\;movlt\\t%0, %1
1407    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1408 [(set_attr "conds" "clob")
1409  (set_attr "length" "8,8,12")])
1411 (define_insn "umaxsi3"
1412   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1413         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1414                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1415    (clobber (reg:CC 24))]
1416   ""
1417   "@
1418    cmp\\t%1, %2\;movcc\\t%0, %2
1419    cmp\\t%1, %2\;movcs\\t%0, %1
1420    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1421 [(set_attr "conds" "clob")
1422  (set_attr "length" "8,8,12")])
1424 (define_insn "uminsi3"
1425   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1426         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1427                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1428    (clobber (reg:CC 24))]
1429   ""
1430   "@
1431    cmp\\t%1, %2\;movcs\\t%0, %2
1432    cmp\\t%1, %2\;movcc\\t%0, %1
1433    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1434 [(set_attr "conds" "clob")
1435  (set_attr "length" "8,8,12")])
1437 (define_insn "*store_minmansi"
1438   [(set (match_operand:SI 0 "memory_operand" "=m")
1439         (match_operator:SI 3 "minmax_operator"
1440          [(match_operand:SI 1 "s_register_operand" "r")
1441           (match_operand:SI 2 "s_register_operand" "r")]))
1442    (clobber (reg:CC 24))]
1443   ""
1444   "*
1445   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1446                          operands[2]);
1447   output_asm_insn (\"cmp\\t%1, %2\", operands);
1448   output_asm_insn (\"str%d3\\t%1, %0\", operands);
1449   output_asm_insn (\"str%D3\\t%2, %0\", operands);
1450   return \"\";
1452 [(set_attr "conds" "clob")
1453  (set_attr "length" "12")
1454  (set_attr "type" "store1")])
1456 (define_insn "*minmax_arithsi"
1457   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1458         (match_operator:SI 4 "shiftable_operator"
1459          [(match_operator:SI 5 "minmax_operator"
1460            [(match_operand:SI 2 "s_register_operand" "r,r")
1461             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1462           (match_operand:SI 1 "s_register_operand" "0,?r")]))
1463    (clobber (reg:CC 24))]
1464   ""
1465   "*
1467   enum rtx_code code = GET_CODE (operands[4]);
1469   operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1470                          operands[3]);
1471   output_asm_insn (\"cmp\\t%2, %3\", operands);
1472   output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1473   if (which_alternative != 0 || operands[3] != const0_rtx
1474       || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1475     output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1476   return \"\";
1479 [(set_attr "conds" "clob")
1480  (set_attr "length" "12")])
1483 ;; Shift and rotation insns
1485 (define_expand "ashlsi3"
1486   [(set (match_operand:SI 0 "s_register_operand" "")
1487         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
1488                    (match_operand:SI 2 "arm_rhs_operand" "")))]
1489   ""
1490   "
1491   if (GET_CODE (operands[2]) == CONST_INT
1492       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1493     {
1494       emit_insn (gen_movsi (operands[0], const0_rtx));
1495       DONE;
1496     }
1499 (define_expand "ashrsi3"
1500   [(set (match_operand:SI 0 "s_register_operand" "")
1501         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1502                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1503   ""
1504   "
1505   if (GET_CODE (operands[2]) == CONST_INT
1506       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1507     operands[2] = GEN_INT (31);
1510 (define_expand "lshrsi3"
1511   [(set (match_operand:SI 0 "s_register_operand" "")
1512         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1513                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1514   ""
1515   "
1516   if (GET_CODE (operands[2]) == CONST_INT
1517       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1518     {
1519       emit_insn (gen_movsi (operands[0], const0_rtx));
1520       DONE;
1521     }
1524 (define_expand "rotlsi3"
1525   [(set (match_operand:SI 0 "s_register_operand" "")
1526         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1527                      (match_operand:SI 2 "reg_or_int_operand" "")))]
1528   ""
1529   "
1530   if (GET_CODE (operands[2]) == CONST_INT)
1531     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1532   else
1533     {
1534       rtx reg = gen_reg_rtx (SImode);
1535       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1536       operands[2] = reg;
1537     }
1540 (define_expand "rotrsi3"
1541   [(set (match_operand:SI 0 "s_register_operand" "")
1542         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1543                      (match_operand:SI 2 "arm_rhs_operand" "")))]
1544   ""
1545   "
1546   if (GET_CODE (operands[2]) == CONST_INT
1547       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1548     operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1551 (define_insn "*shiftsi3"
1552   [(set (match_operand:SI 0 "s_register_operand" "=r")
1553         (match_operator:SI 3 "shift_operator"
1554          [(match_operand:SI 1 "s_register_operand" "r")
1555           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1556   ""
1557   "mov%?\\t%0, %1%S3")
1559 (define_insn "*shiftsi3_compare0"
1560   [(set (reg:CC_NOOV 24)
1561         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1562                           [(match_operand:SI 1 "s_register_operand" "r")
1563                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1564                          (const_int 0)))
1565    (set (match_operand:SI 0 "s_register_operand" "=r")
1566         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1567   ""
1568   "mov%?s\\t%0, %1%S3"
1569 [(set_attr "conds" "set")])
1571 (define_insn "*shiftsi3_compare0_scratch"
1572   [(set (reg:CC_NOOV 24)
1573         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1574                           [(match_operand:SI 1 "s_register_operand" "r")
1575                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
1576                          (const_int 0)))
1577    (clobber (match_scratch:SI 0 "=r"))]
1578   ""
1579   "mov%?s\\t%0, %1%S3"
1580 [(set_attr "conds" "set")])
1582 (define_insn "*notsi_shiftsi"
1583   [(set (match_operand:SI 0 "s_register_operand" "=r")
1584         (not:SI (match_operator:SI 3 "shift_operator"
1585                  [(match_operand:SI 1 "s_register_operand" "r")
1586                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1587   ""
1588   "mvn%?\\t%0, %1%S3")
1590 (define_insn "*notsi_shiftsi_compare0"
1591   [(set (reg:CC_NOOV 24)
1592         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1593                           [(match_operand:SI 1 "s_register_operand" "r")
1594                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1595                          (const_int 0)))
1596    (set (match_operand:SI 0 "s_register_operand" "=r")
1597         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1598   ""
1599   "mvn%?s\\t%0, %1%S3"
1600 [(set_attr "conds" "set")])
1602 (define_insn "*not_shiftsi_compare0_scratch"
1603   [(set (reg:CC_NOOV 24)
1604         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1605                           [(match_operand:SI 1 "s_register_operand" "r")
1606                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1607                          (const_int 0)))
1608    (clobber (match_scratch:SI 0 "=r"))]
1609   ""
1610   "mvn%?s\\t%0, %1%S3"
1611 [(set_attr "conds" "set")])
1614 ;; Unary arithmetic insns
1616 (define_insn "negdi2"
1617   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1618         (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1619   ""
1620   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
1621 [(set_attr "conds" "clob")
1622  (set_attr "length" "8")])
1624 (define_insn "negsi2"
1625   [(set (match_operand:SI 0 "s_register_operand" "=r")
1626         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1627   ""
1628   "rsb%?\\t%0, %1, #0")
1630 (define_insn "negsf2"
1631   [(set (match_operand:SF 0 "s_register_operand" "=f")
1632         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1633   "TARGET_HARD_FLOAT"
1634   "mnf%?s\\t%0, %1"
1635 [(set_attr "type" "ffarith")])
1637 (define_insn "negdf2"
1638   [(set (match_operand:DF 0 "s_register_operand" "=f")
1639         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1640   "TARGET_HARD_FLOAT"
1641   "mnf%?d\\t%0, %1"
1642 [(set_attr "type" "ffarith")])
1644 (define_insn "*negdf_esfdf"
1645   [(set (match_operand:DF 0 "s_register_operand" "=f")
1646         (neg:DF (float_extend:DF
1647                  (match_operand:SF 1 "s_register_operand" "f"))))]
1648   "TARGET_HARD_FLOAT"
1649   "mnf%?d\\t%0, %1"
1650 [(set_attr "type" "ffarith")])
1652 (define_insn "negxf2"
1653   [(set (match_operand:XF 0 "s_register_operand" "=f")
1654         (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1655   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1656   "mnf%?e\\t%0, %1"
1657 [(set_attr "type" "ffarith")])
1659 ;; abssi2 doesn't really clobber the condition codes if a different register
1660 ;; is being set.  To keep things simple, assume during rtl manipulations that
1661 ;; it does, but tell the final scan operator the truth.  Similarly for
1662 ;; (neg (abs...))
1664 (define_insn "abssi2"
1665   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1666         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1667    (clobber (reg 24))]
1668   ""
1669   "@
1670    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1671    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1672 [(set_attr "conds" "clob,*")
1673  (set_attr "length" "8")])
1675 (define_insn "*neg_abssi2"
1676   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1677         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1678    (clobber (reg 24))]
1679   ""
1680   "@
1681    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1682    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1683 [(set_attr "conds" "clob,*")
1684  (set_attr "length" "8")])
1686 (define_insn "abssf2"
1687   [(set (match_operand:SF 0 "s_register_operand" "=f")
1688          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1689   "TARGET_HARD_FLOAT"
1690   "abs%?s\\t%0, %1"
1691 [(set_attr "type" "ffarith")])
1693 (define_insn "absdf2"
1694   [(set (match_operand:DF 0 "s_register_operand" "=f")
1695         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1696   "TARGET_HARD_FLOAT"
1697   "abs%?d\\t%0, %1"
1698 [(set_attr "type" "ffarith")])
1700 (define_insn "*absdf_esfdf"
1701   [(set (match_operand:DF 0 "s_register_operand" "=f")
1702         (abs:DF (float_extend:DF
1703                  (match_operand:SF 1 "s_register_operand" "f"))))]
1704   "TARGET_HARD_FLOAT"
1705   "abs%?d\\t%0, %1"
1706 [(set_attr "type" "ffarith")])
1708 (define_insn "absxf2"
1709   [(set (match_operand:XF 0 "s_register_operand" "=f")
1710         (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1711   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1712   "abs%?e\\t%0, %1"
1713 [(set_attr "type" "ffarith")])
1715 (define_insn "sqrtsf2"
1716   [(set (match_operand:SF 0 "s_register_operand" "=f")
1717         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1718   "TARGET_HARD_FLOAT"
1719   "sqt%?s\\t%0, %1"
1720 [(set_attr "type" "float_em")])
1722 (define_insn "sqrtdf2"
1723   [(set (match_operand:DF 0 "s_register_operand" "=f")
1724         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1725   "TARGET_HARD_FLOAT"
1726   "sqt%?d\\t%0, %1"
1727 [(set_attr "type" "float_em")])
1729 (define_insn "*sqrtdf_esfdf"
1730   [(set (match_operand:DF 0 "s_register_operand" "=f")
1731         (sqrt:DF (float_extend:DF
1732                   (match_operand:SF 1 "s_register_operand" "f"))))]
1733   "TARGET_HARD_FLOAT"
1734   "sqt%?d\\t%0, %1"
1735 [(set_attr "type" "float_em")])
1737 (define_insn "sqrtxf2"
1738   [(set (match_operand:XF 0 "s_register_operand" "=f")
1739         (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1740   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1741   "sqt%?e\\t%0, %1"
1742 [(set_attr "type" "float_em")])
1744 (define_insn "sinsf2"
1745   [(set (match_operand:SF 0 "s_register_operand" "=f")
1746         (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1747   "TARGET_HARD_FLOAT"
1748   "sin%?s\\t%0, %1"
1749 [(set_attr "type" "float_em")])
1751 (define_insn "sindf2"
1752   [(set (match_operand:DF 0 "s_register_operand" "=f")
1753         (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1754   "TARGET_HARD_FLOAT"
1755   "sin%?d\\t%0, %1"
1756 [(set_attr "type" "float_em")])
1758 (define_insn "*sindf_esfdf"
1759   [(set (match_operand:DF 0 "s_register_operand" "=f")
1760         (unspec:DF [(float_extend:DF
1761                      (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1762   "TARGET_HARD_FLOAT"
1763   "sin%?d\\t%0, %1"
1764 [(set_attr "type" "float_em")])
1766 (define_insn "sinxf2"
1767   [(set (match_operand:XF 0 "s_register_operand" "=f")
1768         (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1769   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1770   "sin%?e\\t%0, %1"
1771 [(set_attr "type" "float_em")])
1773 (define_insn "cossf2"
1774   [(set (match_operand:SF 0 "s_register_operand" "=f")
1775         (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
1776   "TARGET_HARD_FLOAT"
1777   "cos%?s\\t%0, %1"
1778 [(set_attr "type" "float_em")])
1780 (define_insn "cosdf2"
1781   [(set (match_operand:DF 0 "s_register_operand" "=f")
1782         (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
1783   "TARGET_HARD_FLOAT"
1784   "cos%?d\\t%0, %1"
1785 [(set_attr "type" "float_em")])
1787 (define_insn "*cosdf_esfdf"
1788   [(set (match_operand:DF 0 "s_register_operand" "=f")
1789         (unspec:DF [(float_extend:DF
1790                      (match_operand:SF 1 "s_register_operand" "f"))] 1))]
1791   "TARGET_HARD_FLOAT"
1792   "cos%?d\\t%0, %1"
1793 [(set_attr "type" "float_em")])
1795 (define_insn "cosxf2"
1796   [(set (match_operand:XF 0 "s_register_operand" "=f")
1797         (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
1798   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1799   "cos%?e\\t%0, %1"
1800 [(set_attr "type" "float_em")])
1802 (define_insn "one_cmpldi2"
1803   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1804         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1805   ""
1806   "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1"
1807 [(set_attr "length" "8")])
1809 (define_insn "one_cmplsi2"
1810   [(set (match_operand:SI 0 "s_register_operand" "=r")
1811         (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
1812   ""
1813   "mvn%?\\t%0, %1")
1815 (define_insn "*notsi_compare0"
1816   [(set (reg:CC_NOOV 24)
1817         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1818                          (const_int 0)))
1819    (set (match_operand:SI 0 "s_register_operand" "=r")
1820         (not:SI (match_dup 1)))]
1821   ""
1822   "mvn%?s\\t%0, %1"
1823 [(set_attr "conds" "set")])
1825 (define_insn "*notsi_compare0_scratch"
1826   [(set (reg:CC_NOOV 24)
1827         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1828                          (const_int 0)))
1829    (clobber (match_scratch:SI 0 "=r"))]
1830   ""
1831   "mvn%?s\\t%0, %1"
1832 [(set_attr "conds" "set")])
1834 ;; Fixed <--> Floating conversion insns
1836 (define_insn "floatsisf2"
1837   [(set (match_operand:SF 0 "s_register_operand" "=f")
1838         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
1839   "TARGET_HARD_FLOAT"
1840   "flt%?s\\t%0, %1"
1841 [(set_attr "type" "r_2_f")])
1843 (define_insn "floatsidf2"
1844   [(set (match_operand:DF 0 "s_register_operand" "=f")
1845         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
1846   "TARGET_HARD_FLOAT"
1847   "flt%?d\\t%0, %1"
1848 [(set_attr "type" "r_2_f")])
1850 (define_insn "floatsixf2"
1851   [(set (match_operand:XF 0 "s_register_operand" "=f")
1852         (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
1853   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1854   "flt%?e\\t%0, %1"
1855 [(set_attr "type" "r_2_f")])
1857 (define_insn "fix_truncsfsi2"
1858   [(set (match_operand:SI 0 "s_register_operand" "=r")
1859         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
1860   "TARGET_HARD_FLOAT"
1861   "fix%?z\\t%0, %1"
1862 [(set_attr "type" "f_2_r")])
1864 (define_insn "fix_truncdfsi2"
1865   [(set (match_operand:SI 0 "s_register_operand" "=r")
1866         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
1867   "TARGET_HARD_FLOAT"
1868   "fix%?z\\t%0, %1"
1869 [(set_attr "type" "f_2_r")])
1871 (define_insn "fix_truncxfsi2"
1872   [(set (match_operand:SI 0 "s_register_operand" "=r")
1873         (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
1874   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1875   "fix%?z\\t%0, %1"
1876 [(set_attr "type" "f_2_r")])
1878 ;; Truncation insns
1880 (define_insn "truncdfsf2"
1881   [(set (match_operand:SF 0 "s_register_operand" "=f")
1882         (float_truncate:SF
1883          (match_operand:DF 1 "s_register_operand" "f")))]
1884   "TARGET_HARD_FLOAT"
1885   "mvf%?s\\t%0, %1"
1886 [(set_attr "type" "ffarith")])
1888 (define_insn "truncxfsf2"
1889   [(set (match_operand:SF 0 "s_register_operand" "=f")
1890         (float_truncate:SF
1891          (match_operand:XF 1 "s_register_operand" "f")))]
1892   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1893   "mvf%?s\\t%0, %1"
1894 [(set_attr "type" "ffarith")])
1896 (define_insn "truncxfdf2"
1897   [(set (match_operand:DF 0 "s_register_operand" "=f")
1898         (float_truncate:DF
1899          (match_operand:XF 1 "s_register_operand" "f")))]
1900   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1901   "mvf%?d\\t%0, %1"
1902 [(set_attr "type" "ffarith")])
1904 ;; Zero and sign extension instructions.
1906 (define_insn "zero_extendsidi2"
1907   [(set (match_operand:DI 0 "s_register_operand" "=r")
1908         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
1909   ""
1910   "*
1911   if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
1912     output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
1913   return \"mov%?\\t%R0, #0\";
1915 [(set_attr "length" "8")])
1917 (define_insn "zero_extendqidi2"
1918   [(set (match_operand:DI 0 "s_register_operand" "=r,r")
1919         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1920   ""
1921   "@
1922    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
1923    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
1924 [(set_attr "length" "8")
1925  (set_attr "type" "*,load")])
1927 (define_insn "extendsidi2"
1928   [(set (match_operand:DI 0 "s_register_operand" "=r")
1929         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
1930   ""
1931   "*
1932   if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
1933     output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
1934   return \"mov%?\\t%R0, %Q0, asr #31\";
1936 [(set_attr "length" "8")])
1938 (define_expand "zero_extendhisi2"
1939   [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
1940                                  (const_int 16)))
1941    (set (match_operand:SI 0 "s_register_operand" "")
1942         (lshiftrt:SI (match_dup 2) (const_int 16)))]
1943   ""
1944   "
1946   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
1947     {
1948       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1949                           gen_rtx (ZERO_EXTEND, SImode, operands[1])));
1950       DONE;
1951     }
1952   if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
1953     {
1954       emit_insn (gen_movhi_bytes (operands[0], operands[1]));
1955       DONE;
1956     }
1957   if (! s_register_operand (operands[1], HImode))
1958     operands[1] = copy_to_mode_reg (HImode, operands[1]);
1959   operands[1] = gen_lowpart (SImode, operands[1]);
1960   operands[2] = gen_reg_rtx (SImode); 
1963 (define_insn "*zero_extendhisi_insn"
1964   [(set (match_operand:SI 0 "s_register_operand" "=r")
1965         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1966   "arm_arch4"
1967   "ldr%?h\\t%0, %1"
1968 [(set_attr "type" "load")])
1970 (define_split
1971   [(set (match_operand:SI 0 "s_register_operand" "")
1972         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
1973    (clobber (match_operand:SI 2 "s_register_operand" ""))]
1974   "! arm_arch4"
1975   [(set (match_dup 2) (match_dup 1))
1976    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
1977   "
1979   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
1980     FAIL;
1983 (define_split
1984   [(set (match_operand:SI 0 "s_register_operand" "")
1985         (match_operator:SI 3 "shiftable_operator"
1986          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
1987           (match_operand:SI 4 "s_register_operand" "")]))
1988    (clobber (match_operand:SI 2 "s_register_operand" ""))]
1989   "! arm_arch4"
1990   [(set (match_dup 2) (match_dup 1))
1991    (set (match_dup 0)
1992         (match_op_dup 3
1993          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
1994   "
1996   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
1997     FAIL;
2000 (define_expand "zero_extendqisi2"
2001   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2002         (zero_extend:SI
2003          (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2004   ""
2005   "
2006   if (GET_CODE (operands[1]) != MEM)
2007     {
2008       emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
2009                              GEN_INT (255)));
2010       DONE;
2011     }
2014 (define_insn "*load_extendqisi"
2015   [(set (match_operand:SI 0 "s_register_operand" "=r")
2016         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2017   ""
2018   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
2019 [(set_attr "type" "load")])
2021 (define_split
2022   [(set (match_operand:SI 0 "s_register_operand" "")
2023         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
2024    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2025   "GET_CODE (operands[1]) != MEM"
2026   [(set (match_dup 2) (match_dup 1))
2027    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
2028   "")
2030 (define_insn "*compareqi_eq0"
2031   [(set (reg:CC_Z 24)
2032         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
2033                          (const_int 0)))]
2034   ""
2035   "tst\\t%0, #255"
2036 [(set_attr "conds" "set")])
2038 (define_expand "extendhisi2"
2039   [(set (match_dup 2)
2040         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2041                    (const_int 16)))
2042    (set (match_operand:SI 0 "s_register_operand" "")
2043         (ashiftrt:SI (match_dup 2)
2044                      (const_int 16)))]
2045   ""
2046   "
2048   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2049     {
2050       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2051                  gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2052       DONE;
2053     }
2055   if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2056     {
2057       emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
2058       DONE;
2059     }
2060   if (! s_register_operand (operands[1], HImode))
2061     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2062   operands[1] = gen_lowpart (SImode, operands[1]);
2063   operands[2] = gen_reg_rtx (SImode);
2066 (define_expand "extendhisi2_mem"
2067   [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" ""))))
2068    (set (match_dup 3)
2069         (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
2070    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
2071    (set (match_operand:SI 0 "" "")
2072         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
2073   ""
2074   "
2075   operands[0] = gen_lowpart (SImode, operands[0]);
2076   operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2077   operands[2] = gen_reg_rtx (SImode);
2078   operands[3] = gen_reg_rtx (SImode);
2079   operands[6] = gen_reg_rtx (SImode);
2081   if (BYTES_BIG_ENDIAN)
2082     {
2083       operands[4] = operands[2];
2084       operands[5] = operands[3];
2085     }
2086   else
2087     {
2088       operands[4] = operands[3];
2089       operands[5] = operands[2];
2090     }
2093 (define_insn "*extendhisi_insn"
2094   [(set (match_operand:SI 0 "s_register_operand" "=r")
2095         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2096   "arm_arch4"
2097   "ldr%?sh\\t%0, %1"
2098 [(set_attr "type" "load")])
2100 (define_split
2101   [(set (match_operand:SI 0 "s_register_operand" "")
2102         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2103    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2104   "! arm_arch4"
2105   [(set (match_dup 2) (match_dup 1))
2106    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2107   "
2109   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2110     FAIL;
2113 (define_split
2114   [(set (match_operand:SI 0 "s_register_operand" "")
2115         (match_operator:SI 3 "shiftable_operator"
2116          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2117           (match_operand:SI 4 "s_register_operand" "")]))
2118    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2119   "! arm_arch4"
2120   [(set (match_dup 2) (match_dup 1))
2121    (set (match_dup 0)
2122         (match_op_dup 3
2123          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2124   "
2126   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2127     FAIL;
2130 (define_expand "extendqihi2"
2131   [(set (match_dup 2)
2132         (ashift:SI (match_operand:QI 1 "general_operand" "")
2133                    (const_int 24)))
2134    (set (match_operand:HI 0 "s_register_operand" "")
2135         (ashiftrt:SI (match_dup 2)
2136                      (const_int 24)))]
2137   ""
2138   "
2140   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2141     {
2142       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2143                           gen_rtx (SIGN_EXTEND, HImode, operands[1])));
2144       DONE;
2145     }
2146   if (! s_register_operand (operands[1], QImode))
2147     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2148   operands[0] = gen_lowpart (SImode, operands[0]);
2149   operands[1] = gen_lowpart (SImode, operands[1]);
2150   operands[2] = gen_reg_rtx (SImode);
2153 (define_insn "*extendqihi_insn"
2154   [(set (match_operand:HI 0 "s_register_operand" "=r")
2155         (sign_extend:HI (match_operand:QI 1 "memory_operand" "o<>")))]
2156   "arm_arch4"
2157   "ldr%?sb\\t%0, %1"
2158 [(set_attr "type" "load")])
2160 (define_expand "extendqisi2"
2161   [(set (match_dup 2)
2162         (ashift:SI (match_operand:QI 1 "s_register_operand" "")
2163                    (const_int 24)))
2164    (set (match_operand:SI 0 "s_register_operand" "")
2165         (ashiftrt:SI (match_dup 2)
2166                      (const_int 24)))]
2167   ""
2168   "
2170   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2171     {
2172       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2173                           gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2174       DONE;
2175     }
2176   if (! s_register_operand (operands[1], QImode))
2177     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2178   operands[1] = gen_lowpart (SImode, operands[1]);
2179   operands[2] = gen_reg_rtx (SImode);
2182 (define_insn "*extendqisi_insn"
2183   [(set (match_operand:SI 0 "s_register_operand" "=r")
2184         (sign_extend:SI (match_operand:QI 1 "memory_operand" "o<>")))]
2185   "arm_arch4"
2186   "ldr%?sb\\t%0, %1"
2187 [(set_attr "type" "load")])
2189 (define_insn "extendsfdf2"
2190   [(set (match_operand:DF 0 "s_register_operand" "=f")
2191         (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2192   "TARGET_HARD_FLOAT"
2193   "mvf%?d\\t%0, %1"
2194 [(set_attr "type" "ffarith")])
2196 (define_insn "extendsfxf2"
2197   [(set (match_operand:XF 0 "s_register_operand" "=f")
2198         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2199   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2200   "mvf%?e\\t%0, %1"
2201 [(set_attr "type" "ffarith")])
2203 (define_insn "extenddfxf2"
2204   [(set (match_operand:XF 0 "s_register_operand" "=f")
2205         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2206   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2207   "mvf%?e\\t%0, %1"
2208 [(set_attr "type" "ffarith")])
2211 ;; Move insns (including loads and stores)
2213 ;; XXX Just some ideas about movti.
2214 ;; I don't think these are a good idea on the arm, there just aren't enough
2215 ;; registers
2216 ;;(define_expand "loadti"
2217 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
2218 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
2219 ;;  "" "")
2221 ;;(define_expand "storeti"
2222 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2223 ;;      (match_operand:TI 1 "s_register_operand" ""))]
2224 ;;  "" "")
2226 ;;(define_expand "movti"
2227 ;;  [(set (match_operand:TI 0 "general_operand" "")
2228 ;;      (match_operand:TI 1 "general_operand" ""))]
2229 ;;  ""
2230 ;;  "
2232 ;;  rtx insn;
2234 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2235 ;;    operands[1] = copy_to_reg (operands[1]);
2236 ;;  if (GET_CODE (operands[0]) == MEM)
2237 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2238 ;;  else if (GET_CODE (operands[1]) == MEM)
2239 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2240 ;;  else
2241 ;;    FAIL;
2243 ;;  emit_insn (insn);
2244 ;;  DONE;
2245 ;;}")
2247 ;; Recognise garbage generated above.
2249 ;;(define_insn ""
2250 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2251 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2252 ;;  ""
2253 ;;  "*
2254 ;;  {
2255 ;;    register mem = (which_alternative < 3);
2256 ;;    register char *template;
2258 ;;    operands[mem] = XEXP (operands[mem], 0);
2259 ;;    switch (which_alternative)
2260 ;;      {
2261 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2262 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
2263 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
2264 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
2265 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
2266 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
2267 ;;      }
2268 ;;    output_asm_insn (template, operands);
2269 ;;    return \"\";
2270 ;;  }")
2273 (define_insn "movdi"
2274   [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2275         (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2276   ""
2277   "*
2278   return (output_move_double (operands));
2280 [(set_attr "length" "8,8,8")
2281  (set_attr "type" "*,load,store2")])
2283 (define_expand "movsi"
2284   [(set (match_operand:SI 0 "general_operand" "")
2285         (match_operand:SI 1 "general_operand" ""))]
2286   ""
2287   "
2288   /* Everything except mem = const or mem = mem can be done easily */
2289   if (GET_CODE (operands[0]) == MEM)
2290     operands[1] = force_reg (SImode, operands[1]);
2291   if (GET_CODE (operands[1]) == CONST_INT
2292       && !(const_ok_for_arm (INTVAL (operands[1]))
2293            || const_ok_for_arm (~INTVAL (operands[1]))))
2294     {
2295       arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2296                           NULL_RTX,
2297                           (reload_in_progress || reload_completed ? 0
2298                            : preserve_subexpressions_p ()));
2299       DONE;
2300     }
2303 (define_insn "*movsi_insn"
2304   [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2305         (match_operand:SI 1 "general_operand"  "rI,K,mi,r"))]
2306   "register_operand (operands[0], SImode)
2307    || register_operand (operands[1], SImode)"
2308   "@
2309    mov%?\\t%0, %1
2310    mvn%?\\t%0, #%B1
2311    ldr%?\\t%0, %1
2312    str%?\\t%1, %0"
2313 [(set_attr "type" "*,*,load,store1")])
2315 (define_split
2316   [(set (match_operand:SI 0 "s_register_operand" "")
2317         (match_operand:SI 1 "const_int_operand" ""))]
2318   "! (const_ok_for_arm (INTVAL (operands[1]))
2319       || const_ok_for_arm (~INTVAL (operands[1])))"
2320   [(clobber (const_int 0))]
2321   "
2322   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2323                       NULL_RTX, 0);
2324   DONE;
2327 (define_expand "movaddr"
2328   [(set (match_operand:SI 0 "s_register_operand" "")
2329         (match_operand:DI 1 "address_operand" ""))]
2330   ""
2331   "")
2333 (define_insn "*movaddr_insn"
2334   [(set (match_operand:SI 0 "s_register_operand" "=r")
2335         (match_operand:DI 1 "address_operand" "p"))]
2336   "reload_completed
2337    && (GET_CODE (operands[1]) == LABEL_REF
2338        || (GET_CODE (operands[1]) == CONST
2339            && GET_CODE (XEXP (operands[1], 0)) == PLUS
2340            && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2341            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2342   "adr%?\\t%0, %a1")
2344 ;; If copying one reg to another we can set the condition codes according to
2345 ;; its value.  Such a move is common after a return from subroutine and the
2346 ;; result is being tested against zero.
2348 (define_insn "*movsi_compare0"
2349   [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
2350                                 (const_int 0)))
2351    (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2352   ""
2353   "@
2354    cmp%?\\t%0, #0
2355    sub%?s\\t%0, %1, #0"
2356 [(set_attr "conds" "set")])
2358 ;; Subroutine to store a half word from a register into memory.
2359 ;; Operand 0 is the source register (HImode)
2360 ;; Operand 1 is the destination address in a register (SImode)
2362 ;; In both this routine and the next, we must be careful not to spill
2363 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2364 ;; can generate unrecognizable rtl.
2366 (define_expand "storehi"
2367   [;; store the low byte
2368    (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3))
2369    ;; extract the high byte
2370    (set (match_dup 2)
2371         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2372    ;; store the high byte
2373    (set (mem:QI (match_dup 4))
2374         (subreg:QI (match_dup 2) 0))]   ;explicit subreg safe
2375   ""
2376   "
2378   enum rtx_code code = GET_CODE (operands[1]);
2380   if ((code == PLUS || code == MINUS)
2381       && (GET_CODE (XEXP (operands[1], 1)) == REG
2382           || GET_CODE (XEXP (operands[1], 0)) != REG))
2383     operands[1] = force_reg (SImode, operands[1]);
2384   operands[4] = plus_constant (operands[1], 1);
2385   operands[3] = gen_lowpart (QImode, operands[0]);
2386   operands[0] = gen_lowpart (SImode, operands[0]);
2387   operands[2] = gen_reg_rtx (SImode); 
2391 (define_expand "storehi_bigend"
2392   [(set (mem:QI (match_dup 4)) (match_dup 3))
2393    (set (match_dup 2)
2394         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2395    (set (mem:QI (match_operand 1 "" ""))
2396         (subreg:QI (match_dup 2) 0))]
2397   ""
2398   "
2400   enum rtx_code code = GET_CODE (operands[1]);
2401   if ((code == PLUS || code == MINUS)
2402       && (GET_CODE (XEXP (operands[1], 1)) == REG
2403           || GET_CODE (XEXP (operands[1], 0)) != REG))
2404     operands[1] = force_reg (SImode, operands[1]);
2406   operands[4] = plus_constant (operands[1], 1);
2407   operands[3] = gen_lowpart (QImode, operands[0]);
2408   operands[0] = gen_lowpart (SImode, operands[0]);
2409   operands[2] = gen_reg_rtx (SImode);
2413 ;; Subroutine to store a half word integer constant into memory.
2414 (define_expand "storeinthi"
2415   [(set (mem:QI (match_operand:SI 0 "" ""))
2416         (subreg:QI (match_operand 1 "" "") 0))
2417    (set (mem:QI (match_dup 3)) (subreg:QI (match_dup 2) 0))]
2418   ""
2419   "
2421   HOST_WIDE_INT value = INTVAL (operands[1]);
2422   enum rtx_code code = GET_CODE (operands[0]);
2424   if ((code == PLUS || code == MINUS)
2425       && (GET_CODE (XEXP (operands[0], 1)) == REG
2426           || GET_CODE (XEXP (operands[0], 0)) != REG))
2427   operands[0] = force_reg (SImode, operands[0]);
2429   operands[1] = gen_reg_rtx (SImode);
2430   if (BYTES_BIG_ENDIAN)
2431     {
2432       emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2433       if ((value & 255) == ((value >> 8) & 255))
2434         operands[2] = operands[1];
2435       else
2436         {
2437           operands[2] = gen_reg_rtx (SImode);
2438           emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2439         }
2440     }
2441   else
2442     {
2443       emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2444       if ((value & 255) == ((value >> 8) & 255))
2445         operands[2] = operands[1];
2446       else
2447         {
2448           operands[2] = gen_reg_rtx (SImode);
2449           emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2450         }
2451     }
2453   operands[3] = plus_constant (operands[0], 1);
2457 (define_expand "storehi_single_op"
2458   [(set (match_operand:HI 0 "memory_operand" "")
2459         (match_operand:HI 1 "general_operand" ""))]
2460   "arm_arch4"
2461   "
2462   if (! s_register_operand (operands[1], HImode))
2463     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2466 (define_expand "movhi"
2467   [(set (match_operand:HI 0 "general_operand" "")
2468         (match_operand:HI 1 "general_operand" ""))]
2469   ""
2470   "
2472   rtx insn;
2474   if (! (reload_in_progress || reload_completed))
2475     {
2476       if (GET_CODE (operands[0]) == MEM)
2477         {
2478           if (arm_arch4)
2479             {
2480               emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2481               DONE;
2482             }
2483           if (GET_CODE (operands[1]) == CONST_INT)
2484             emit_insn (gen_storeinthi (XEXP (operands[0], 0), operands[1]));
2485           else
2486             {
2487               if (GET_CODE (operands[1]) == MEM)
2488                 operands[1] = force_reg (HImode, operands[1]);
2489               if (BYTES_BIG_ENDIAN)
2490                 emit_insn (gen_storehi_bigend (operands[1],
2491                                                XEXP (operands[0], 0)));
2492               else
2493                 emit_insn (gen_storehi (operands[1], XEXP (operands[0], 0)));
2494             }
2495           DONE;
2496         }
2497       /* Sign extend a constant, and keep it in an SImode reg.  */
2498       else if (GET_CODE (operands[1]) == CONST_INT)
2499         {
2500           rtx reg = gen_reg_rtx (SImode);
2501           HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2503           /* If the constant is already valid, leave it alone.  */
2504           if (! const_ok_for_arm (val))
2505             {
2506               /* If setting all the top bits will make the constant 
2507                  loadable in a single instruction, then set them.  
2508                  Otherwise, sign extend the number.  */
2510               if (const_ok_for_arm (~ (val | ~0xffff)))
2511                 val |= ~0xffff;
2512               else if (val & 0x8000)
2513                 val |= ~0xffff;
2514             }
2516           emit_insn (gen_movsi (reg, GEN_INT (val)));
2517           operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
2518         }
2519       else if (! arm_arch4)
2520         {
2521           if (GET_CODE (operands[1]) == MEM)
2522             {
2523               if (TARGET_SHORT_BY_BYTES)
2524                 {
2525                   rtx base;
2526                   rtx offset = const0_rtx;
2527                   rtx reg = gen_reg_rtx (SImode);
2529                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2530                        || (GET_CODE (base) == PLUS
2531                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2532                            && GET_CODE (base = XEXP (base, 0)) == REG))
2533                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2534                     {
2535                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~2;
2537                       emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode,
2538                                            plus_constant (base, new_offset))));
2539                       if (((INTVAL (offset) & 2) != 0)
2540                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
2541                         {
2542                           rtx reg2 = gen_reg_rtx (SImode);
2544                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
2545                           reg = reg2;
2546                         }
2547                     }
2548                   else
2549                     emit_insn (gen_movhi_bytes (reg, operands[1]));
2551                   operands[1] = gen_lowpart (HImode, reg);
2552                 }
2553               else if (BYTES_BIG_ENDIAN)
2554                 {
2555                   rtx base;
2556                   rtx offset = const0_rtx;
2558                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2559                        || (GET_CODE (base) == PLUS
2560                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2561                            && GET_CODE (base = XEXP (base, 0)) == REG))
2562                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2563                     {
2564                       rtx reg = gen_reg_rtx (SImode);
2565                       rtx new_mem;
2567                       if ((INTVAL (offset) & 2) == 2)
2568                         {
2569                           HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
2570                           new_mem = gen_rtx (MEM, SImode,
2571                                              plus_constant (base, new_offset));
2573                           emit_insn (gen_movsi (reg, new_mem));
2574                         }
2575                       else
2576                         {
2577                           new_mem = gen_rtx (MEM, SImode,
2578                                              XEXP (operands[1], 0));
2579                           emit_insn (gen_rotated_loadsi (reg, new_mem));
2580                         }
2582                       operands[1] = gen_lowpart (HImode, reg);
2583                     }
2584                   else
2585                     {
2586                       emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2587                       DONE;
2588                     }
2589                 }
2590             }
2591         }
2592     }
2593   /* Handle loading a large integer during reload */
2594   else if (GET_CODE (operands[1]) == CONST_INT
2595            && ! const_ok_for_arm (INTVAL (operands[1]))
2596            && ! const_ok_for_arm (~INTVAL (operands[1])))
2597     {
2598       /* Writing a constant to memory needs a scratch, which should
2599          be handled with SECONDARY_RELOADs.  */
2600       if (GET_CODE (operands[0]) != REG)
2601         abort ();
2603       operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
2604       emit_insn (gen_movsi (operands[0], operands[1]));
2605       DONE;
2606     }
2610 (define_insn "rotated_loadsi"
2611   [(set (match_operand:SI 0 "s_register_operand" "=r")
2612         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
2613                    (const_int 16)))]
2614   "! TARGET_SHORT_BY_BYTES"
2615   "*
2617   rtx ops[2];
2619   ops[0] = operands[0];
2620   ops[1] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 2));
2621   output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
2622   return \"\";
2624 [(set_attr "type" "load")])
2626 (define_expand "movhi_bytes"
2627   [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" ""))))
2628    (set (match_dup 3)
2629         (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
2630    (set (match_operand:SI 0 "" "")
2631          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
2632   ""
2633   "
2634   operands[0] = gen_lowpart (SImode, operands[0]);
2635   operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2636   operands[2] = gen_reg_rtx (SImode);
2637   operands[3] = gen_reg_rtx (SImode);
2639   if (BYTES_BIG_ENDIAN)
2640     {
2641       operands[4] = operands[2];
2642       operands[5] = operands[3];
2643     }
2644   else
2645     {
2646       operands[4] = operands[3];
2647       operands[5] = operands[2];
2648     }
2651 (define_expand "movhi_bigend"
2652   [(set (match_dup 2)
2653         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
2654                    (const_int 16)))
2655    (set (match_dup 3)
2656         (ashiftrt:SI (match_dup 2) (const_int 16)))
2657    (set (match_operand:HI 0 "s_register_operand" "")
2658         (subreg:HI (match_dup 3) 0))]
2659   ""
2660   "
2661   operands[2] = gen_reg_rtx (SImode);
2662   operands[3] = gen_reg_rtx (SImode);
2665 ;; Pattern to recognise insn generated default case above
2667 (define_insn "*movhi_insn_arch4"
2668   [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
2669         (match_operand:HI 1 "general_operand"  "rI,K,m,r"))]
2670   "arm_arch4
2671    && (GET_CODE (operands[1]) != CONST_INT
2672        || const_ok_for_arm (INTVAL (operands[1]))
2673        || const_ok_for_arm (~INTVAL (operands[1])))"
2674   "@
2675    mov%?\\t%0, %1\\t%@ movhi
2676    mvn%?\\t%0, #%B1\\t%@ movhi
2677    ldr%?h\\t%0, %1\\t%@ movhi
2678    str%?h\\t%1, %0\\t%@ movhi"
2679 [(set_attr "type" "*,*,load,store1")])
2681 (define_insn "*movhi_insn_littleend"
2682   [(set (match_operand:HI 0 "general_operand" "=r,r,r")
2683         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2684   "! arm_arch4
2685    && ! BYTES_BIG_ENDIAN
2686    && ! TARGET_SHORT_BY_BYTES
2687    && (GET_CODE (operands[1]) != CONST_INT
2688        || const_ok_for_arm (INTVAL (operands[1]))
2689        || const_ok_for_arm (~INTVAL (operands[1])))"
2690   "@
2691    mov%?\\t%0, %1\\t%@ movhi
2692    mvn%?\\t%0, #%B1\\t%@ movhi
2693    ldr%?\\t%0, %1\\t%@ movhi"
2694 [(set_attr "type" "*,*,load")])
2696 (define_insn "*movhi_insn_bigend"
2697   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
2698         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
2699   "! arm_arch4
2700    && BYTES_BIG_ENDIAN
2701    && ! TARGET_SHORT_BY_BYTES
2702    && (GET_CODE (operands[1]) != CONST_INT
2703        || const_ok_for_arm (INTVAL (operands[1]))
2704        || const_ok_for_arm (~INTVAL (operands[1])))"
2705   "@
2706    mov%?\\t%0, %1\\t%@ movhi
2707    mvn%?\\t%0, #%B1\\t%@ movhi
2708    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
2709 [(set_attr "type" "*,*,load")
2710  (set_attr "length" "4,4,8")])
2712 (define_insn "*loadhi_si_bigend"
2713   [(set (match_operand:SI 0 "s_register_operand" "=r")
2714         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
2715                    (const_int 16)))]
2716   "BYTES_BIG_ENDIAN
2717    && ! TARGET_SHORT_BY_BYTES"
2718   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
2719 [(set_attr "type" "load")])
2721 (define_insn "*movhi_bytes"
2722   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
2723         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
2724   "TARGET_SHORT_BY_BYTES"
2725   "@
2726    mov%?\\t%0, %1\\t%@ movhi
2727    mvn%?\\t%0, #%B1\\t%@ movhi")
2730 (define_expand "reload_outhi"
2731   [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
2732               (match_operand:HI 1 "s_register_operand" "r")
2733               (match_operand:SI 2 "s_register_operand" "=&r")])]
2734   ""
2735   "
2736   arm_reload_out_hi (operands);
2737   DONE;
2740 (define_expand "reload_inhi"
2741   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
2742               (match_operand:HI 1 "reload_memory_operand" "o")
2743               (match_operand:SI 2 "s_register_operand" "=&r")])]
2744   "TARGET_SHORT_BY_BYTES"
2745   "
2746   arm_reload_in_hi (operands);
2747   DONE;
2750 (define_expand "movqi"
2751   [(set (match_operand:QI 0 "general_operand" "")
2752         (match_operand:QI 1 "general_operand" ""))]
2753   ""
2754   "
2755   /* Everything except mem = const or mem = mem can be done easily */
2757   if (!(reload_in_progress || reload_completed))
2758     {
2759       if (GET_CODE (operands[1]) == CONST_INT)
2760         {
2761           rtx reg = gen_reg_rtx (SImode);
2763           emit_insn (gen_movsi (reg, operands[1]));
2764           operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
2765         }
2766       if (GET_CODE (operands[0]) == MEM)
2767         operands[1] = force_reg (QImode, operands[1]);
2768     }
2772 (define_insn "*movqi_insn"
2773   [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
2774         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
2775   "register_operand (operands[0], QImode)
2776    || register_operand (operands[1], QImode)"
2777   "@
2778    mov%?\\t%0, %1
2779    mvn%?\\t%0, #%B1
2780    ldr%?b\\t%0, %1
2781    str%?b\\t%1, %0"
2782 [(set_attr "type" "*,*,load,store1")])
2784 (define_expand "movsf"
2785   [(set (match_operand:SF 0 "general_operand" "")
2786         (match_operand:SF 1 "general_operand" ""))]
2787   ""
2788   "
2789   if (GET_CODE (operands[0]) == MEM)
2790     operands[1] = force_reg (SFmode, operands[1]);
2793 (define_insn "*movsf_hard_insn"
2794   [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
2795         (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
2796   "TARGET_HARD_FLOAT
2797    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
2798   "@
2799    mvf%?s\\t%0, %1
2800    mnf%?s\\t%0, #%N1
2801    ldf%?s\\t%0, %1
2802    stf%?s\\t%1, %0
2803    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
2804    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
2805    mov%?\\t%0, %1
2806    ldr%?\\t%0, %1\\t%@ float
2807    str%?\\t%1, %0\\t%@ float"
2808 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
2809  (set_attr "type"
2810          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
2812 ;; Exactly the same as above, except that all `f' cases are deleted.
2813 ;; This is necessary to prevent reload from ever trying to use a `f' reg
2814 ;; when -msoft-float.
2816 (define_insn "*movsf_soft_insn"
2817   [(set (match_operand:SF 0 "general_operand" "=r,r,m")
2818         (match_operand:SF 1 "general_operand" "r,mE,r"))]
2819   "TARGET_SOFT_FLOAT
2820    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
2821   "@
2822    mov%?\\t%0, %1
2823    ldr%?\\t%0, %1\\t%@ float
2824    str%?\\t%1, %0\\t%@ float"
2825 [(set_attr "length" "4,4,4")
2826  (set_attr "type" "*,load,store1")])
2828 (define_expand "movdf"
2829   [(set (match_operand:DF 0 "general_operand" "")
2830         (match_operand:DF 1 "general_operand" ""))]
2831   ""
2832   "
2833   if (GET_CODE (operands[0]) == MEM)
2834     operands[1] = force_reg (DFmode, operands[1]);
2837 ;; Reloading a df mode value stored in integer regs to memory can require a
2838 ;; scratch reg.
2839 (define_expand "reload_outdf"
2840   [(match_operand:DF 0 "reload_memory_operand" "=o")
2841    (match_operand:DF 1 "s_register_operand" "r")
2842    (match_operand:SI 2 "s_register_operand" "=&r")]
2843   ""
2844   "
2846   enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
2848   if (code == REG)
2849     operands[2] = XEXP (operands[0], 0);
2850   else if (code == POST_INC || code == PRE_DEC)
2851     {
2852       operands[0] = gen_rtx (SUBREG, DImode, operands[0], 0);
2853       operands[1] = gen_rtx (SUBREG, DImode, operands[1], 0);
2854       emit_insn (gen_movdi (operands[0], operands[1]));
2855       DONE;
2856     }
2857   else if (code == PRE_INC)
2858     {
2859       rtx reg = XEXP (XEXP (operands[0], 0), 0);
2860       emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
2861       operands[2] = reg;
2862     }
2863   else if (code == POST_DEC)
2864     operands[2] = XEXP (XEXP (operands[0], 0), 0);
2865   else
2866     emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
2867                            XEXP (XEXP (operands[0], 0), 1)));
2869   emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DFmode, operands[2]),
2870                       operands[1]));
2872   if (code == POST_DEC)
2873     emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
2875   DONE;
2879 (define_insn "*movdf_hard_insn"
2880   [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
2881         (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
2882   "TARGET_HARD_FLOAT
2883    && (GET_CODE (operands[0]) != MEM
2884        || register_operand (operands[1], DFmode))"
2885   "*
2887   rtx ops[3];
2889   switch (which_alternative)
2890     {
2891     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
2892     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
2893     case 2: case 3: case 4: return output_move_double (operands);
2894     case 5: return \"mvf%?d\\t%0, %1\";
2895     case 6: return \"mnf%?d\\t%0, #%N1\";
2896     case 7: return \"ldf%?d\\t%0, %1\";
2897     case 8: return \"stf%?d\\t%1, %0\";
2898     case 9: return output_mov_double_fpu_from_arm (operands);
2899     case 10: return output_mov_double_arm_from_fpu (operands);
2900     }
2903 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
2904  (set_attr "type"
2905 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
2907 ;; Software floating point version.  This is essentially the same as movdi.
2908 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
2909 ;; an `f' reg.
2911 (define_insn "*movdf_soft_insn"
2912   [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
2913         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
2914   "TARGET_SOFT_FLOAT"
2915   "* return output_move_double (operands);"
2916 [(set_attr "length" "8,8,8")
2917  (set_attr "type" "*,load,store2")])
2919 (define_expand "movxf"
2920   [(set (match_operand:XF 0 "general_operand" "")
2921         (match_operand:XF 1 "general_operand" ""))]
2922   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2923   "")
2925 ;; Even when the XFmode patterns aren't enabled, we enable this after
2926 ;; reloading so that we can push floating point registers in the prologue.
2928 (define_insn "*movxf_hard_insn"
2929   [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
2930         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
2931   "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
2932   "*
2933   switch (which_alternative)
2934     {
2935     case 0: return \"mvf%?e\\t%0, %1\";
2936     case 1: return \"mnf%?e\\t%0, #%N1\";
2937     case 2: return \"ldf%?e\\t%0, %1\";
2938     case 3: return \"stf%?e\\t%1, %0\";
2939     case 4: return output_mov_long_double_fpu_from_arm (operands);
2940     case 5: return output_mov_long_double_arm_from_fpu (operands);
2941     case 6: return output_mov_long_double_arm_from_arm (operands);
2942     }
2944 [(set_attr "length" "4,4,4,4,8,8,12")
2945  (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
2948 ;; load- and store-multiple insns
2949 ;; The arm can load/store any set of registers, provided that they are in
2950 ;; ascending order; but that is beyond GCC so stick with what it knows.
2952 (define_expand "load_multiple"
2953   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2954                           (match_operand:SI 1 "" ""))
2955                      (use (match_operand:SI 2 "" ""))])]
2956   ""
2957   "
2958   /* Support only fixed point registers */
2959   if (GET_CODE (operands[2]) != CONST_INT
2960       || INTVAL (operands[2]) > 14
2961       || INTVAL (operands[2]) < 2
2962       || GET_CODE (operands[1]) != MEM
2963       || GET_CODE (operands[0]) != REG
2964       || REGNO (operands[0]) > 14
2965       || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
2966     FAIL;
2968   operands[3]
2969             = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
2970                                      force_reg (SImode, XEXP (operands[1], 0)),
2971                                      TRUE, FALSE);
2974 ;; Load multiple with write-back
2976 (define_insn "*ldmsi_postinc"
2977   [(match_parallel 0 "load_multiple_operation"
2978     [(set (match_operand:SI 1 "s_register_operand" "+r")
2979           (plus:SI (match_dup 1)
2980                    (match_operand:SI 2 "const_int_operand" "n")))
2981      (set (match_operand:SI 3 "s_register_operand" "=r")
2982           (mem:SI (match_dup 1)))])]
2983   "(INTVAL (operands[2])  == 4 * (XVECLEN (operands[0], 0) - 2))"
2984   "*
2986   rtx ops[3];
2987   int count = XVECLEN (operands[0], 0);
2989   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2990   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
2991   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
2993   output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
2994   return \"\";
2997 [(set_attr "type" "load")])
2999 ;; Ordinary load multiple
3001 (define_insn "*ldmsi"
3002   [(match_parallel 0 "load_multiple_operation"
3003     [(set (match_operand:SI 1 "s_register_operand" "=r")
3004           (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3005   ""
3006   "*
3008   rtx ops[3];
3009   int count = XVECLEN (operands[0], 0);
3011   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3012   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3013   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3015   output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3016   return \"\";
3019 [(set_attr "type" "load")])
3021 (define_expand "store_multiple"
3022   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3023                           (match_operand:SI 1 "" ""))
3024                      (use (match_operand:SI 2 "" ""))])]
3025   ""
3026   "
3027   /* Support only fixed point registers */
3028   if (GET_CODE (operands[2]) != CONST_INT
3029       || INTVAL (operands[2]) > 14
3030       || INTVAL (operands[2]) < 2
3031       || GET_CODE (operands[1]) != REG
3032       || GET_CODE (operands[0]) != MEM
3033       || REGNO (operands[1]) > 14
3034       || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3035     FAIL;
3037   operands[3]
3038            = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3039                                      force_reg (SImode, XEXP (operands[0], 0)),
3040                                      TRUE, FALSE);
3043 ;; Store multiple with write-back
3045 (define_insn "*stmsi_postinc"
3046   [(match_parallel 0 "store_multiple_operation"
3047     [(set (match_operand:SI 1 "s_register_operand" "+r")
3048           (plus:SI (match_dup 1)
3049                    (match_operand:SI 2 "const_int_operand" "n")))
3050      (set (mem:SI (match_dup 1))
3051           (match_operand:SI 3 "s_register_operand" "r"))])]
3052   "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3053   "*
3055   rtx ops[3];
3056   int count = XVECLEN (operands[0], 0);
3058   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3059   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3060   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3062   output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3063   return \"\";
3066 [(set (attr "type")
3067       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3068                 (const_string "store2")
3069              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3070                 (const_string "store3")]
3071           (const_string "store4")))])
3073 ;; Ordinary store multiple
3075 (define_insn "*stmsi"
3076   [(match_parallel 0 "store_multiple_operation"
3077     [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3078           (match_operand:SI 1 "s_register_operand" "r"))])]
3079   ""
3080   "*
3082   rtx ops[3];
3083   int count = XVECLEN (operands[0], 0);
3085   ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3086   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3087   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3089   output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3090   return \"\";
3093 [(set (attr "type")
3094       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3095                 (const_string "store2")
3096              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3097                 (const_string "store3")]
3098           (const_string "store4")))])
3100 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
3101 ;; We could let this apply for blocks of less than this, but it clobbers so
3102 ;; many registers that there is then probably a better way.
3104 (define_expand "movstrqi"
3105   [(match_operand:BLK 0 "general_operand" "")
3106    (match_operand:BLK 1 "general_operand" "")
3107    (match_operand:SI 2 "const_int_operand" "")
3108    (match_operand:SI 3 "const_int_operand" "")]
3109   ""
3110   "
3111   if (arm_gen_movstrqi (operands))
3112     DONE;
3113   FAIL;
3117 ;; Comparison and test insns
3119 (define_expand "cmpsi"
3120   [(match_operand:SI 0 "s_register_operand" "")
3121    (match_operand:SI 1 "arm_add_operand" "")]
3122   ""
3123   "
3125   arm_compare_op0 = operands[0];
3126   arm_compare_op1 = operands[1];
3127   arm_compare_fp = 0;
3128   DONE;
3132 (define_expand "cmpsf"
3133   [(match_operand:SF 0 "s_register_operand" "")
3134    (match_operand:SF 1 "fpu_rhs_operand" "")]
3135   "TARGET_HARD_FLOAT"
3136   "
3138   arm_compare_op0 = operands[0];
3139   arm_compare_op1 = operands[1];
3140   arm_compare_fp = 1;
3141   DONE;
3145 (define_expand "cmpdf"
3146   [(match_operand:DF 0 "s_register_operand" "")
3147    (match_operand:DF 1 "fpu_rhs_operand" "")]
3148   "TARGET_HARD_FLOAT"
3149   "
3151   arm_compare_op0 = operands[0];
3152   arm_compare_op1 = operands[1];
3153   arm_compare_fp = 1;
3154   DONE;
3158 (define_expand "cmpxf"
3159   [(match_operand:XF 0 "s_register_operand" "")
3160    (match_operand:XF 1 "fpu_rhs_operand" "")]
3161   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3162   "
3164   arm_compare_op0 = operands[0];
3165   arm_compare_op1 = operands[1];
3166   arm_compare_fp = 1;
3167   DONE;
3171 (define_insn "*cmpsi_insn"
3172   [(set (reg:CC 24)
3173         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3174                     (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3175   ""
3176   "@
3177    cmp%?\\t%0, %1
3178    cmn%?\\t%0, #%n1"
3179 [(set_attr "conds" "set")])
3181 (define_insn "*cmpsi_shiftsi"
3182   [(set (reg:CC 24)
3183         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3184                     (match_operator:SI 3 "shift_operator"
3185                      [(match_operand:SI 1 "s_register_operand" "r")
3186                       (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3187   ""
3188   "cmp%?\\t%0, %1%S3"
3189 [(set_attr "conds" "set")])
3191 (define_insn "*cmpsi_shiftsi_swp"
3192   [(set (reg:CC_SWP 24)
3193         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3194                          [(match_operand:SI 1 "s_register_operand" "r")
3195                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
3196                         (match_operand:SI 0 "s_register_operand" "r")))]
3197   ""
3198   "cmp%?\\t%0, %1%S3"
3199 [(set_attr "conds" "set")])
3201 (define_insn "*cmpsi_neg_shiftsi"
3202   [(set (reg:CC 24)
3203         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3204                     (neg:SI (match_operator:SI 3 "shift_operator"
3205                              [(match_operand:SI 1 "s_register_operand" "r")
3206                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3207   ""
3208   "cmn%?\\t%0, %1%S3"
3209 [(set_attr "conds" "set")])
3211 (define_insn "*cmpsf_insn"
3212   [(set (reg:CCFP 24)
3213         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3214                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3215   "TARGET_HARD_FLOAT"
3216   "@
3217    cmf%?\\t%0, %1
3218    cnf%?\\t%0, #%N1"
3219 [(set_attr "conds" "set")
3220  (set_attr "type" "f_2_r")])
3222 (define_insn "*cmpdf_insn"
3223   [(set (reg:CCFP 24)
3224         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3225                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3226   "TARGET_HARD_FLOAT"
3227   "@
3228    cmf%?\\t%0, %1
3229    cnf%?\\t%0, #%N1"
3230 [(set_attr "conds" "set")
3231  (set_attr "type" "f_2_r")])
3233 (define_insn "*cmpesfdf_df"
3234   [(set (reg:CCFP 24)
3235         (compare:CCFP (float_extend:DF
3236                        (match_operand:SF 0 "s_register_operand" "f,f"))
3237                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3238   "TARGET_HARD_FLOAT"
3239   "@
3240    cmf%?\\t%0, %1
3241    cnf%?\\t%0, #%N1"
3242 [(set_attr "conds" "set")
3243  (set_attr "type" "f_2_r")])
3245 (define_insn "*cmpdf_esfdf"
3246   [(set (reg:CCFP 24)
3247         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3248                       (float_extend:DF
3249                        (match_operand:SF 1 "s_register_operand" "f"))))]
3250   "TARGET_HARD_FLOAT"
3251   "cmf%?\\t%0, %1"
3252 [(set_attr "conds" "set")
3253  (set_attr "type" "f_2_r")])
3255 (define_insn "*cmpxf_insn"
3256   [(set (reg:CCFP 24)
3257         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3258                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3259   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3260   "@
3261    cmf%?\\t%0, %1
3262    cnf%?\\t%0, #%N1"
3263 [(set_attr "conds" "set")
3264  (set_attr "type" "f_2_r")])
3266 (define_insn "*cmpsf_trap"
3267   [(set (reg:CCFPE 24)
3268         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3269                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3270   "TARGET_HARD_FLOAT"
3271   "@
3272    cmf%?e\\t%0, %1
3273    cnf%?e\\t%0, #%N1"
3274 [(set_attr "conds" "set")
3275  (set_attr "type" "f_2_r")])
3277 (define_insn "*cmpdf_trap"
3278   [(set (reg:CCFPE 24)
3279         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3280                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3281   "TARGET_HARD_FLOAT"
3282   "@
3283    cmf%?e\\t%0, %1
3284    cnf%?e\\t%0, #%N1"
3285 [(set_attr "conds" "set")
3286  (set_attr "type" "f_2_r")])
3288 (define_insn "*cmp_esfdf_df_trap"
3289   [(set (reg:CCFPE 24)
3290         (compare:CCFPE (float_extend:DF
3291                         (match_operand:SF 0 "s_register_operand" "f,f"))
3292                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3293   "TARGET_HARD_FLOAT"
3294   "@
3295    cmf%?e\\t%0, %1
3296    cnf%?e\\t%0, #%N1"
3297 [(set_attr "conds" "set")
3298  (set_attr "type" "f_2_r")])
3300 (define_insn "*cmp_df_esfdf_trap"
3301   [(set (reg:CCFPE 24)
3302         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3303                        (float_extend:DF
3304                         (match_operand:SF 1 "s_register_operand" "f"))))]
3305   "TARGET_HARD_FLOAT"
3306   "cmf%?e\\t%0, %1"
3307 [(set_attr "conds" "set")
3308  (set_attr "type" "f_2_r")])
3310 (define_insn "*cmpxf_trap"
3311   [(set (reg:CCFPE 24)
3312         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3313                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3314   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3315   "@
3316    cmf%?e\\t%0, %1
3317    cnf%?e\\t%0, #%N1"
3318 [(set_attr "conds" "set")
3319  (set_attr "type" "f_2_r")])
3321 ; This insn allows redundant compares to be removed by cse, nothing should
3322 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3323 ; is deleted later on. The match_dup will match the mode here, so that
3324 ; mode changes of the condition codes aren't lost by this even though we don't
3325 ; specify what they are.
3327 (define_insn "*delted_compare"
3328   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3329   ""
3330   "\\t%@ deleted compare"
3331 [(set_attr "conds" "set")
3332  (set_attr "length" "0")])
3335 ;; Conditional branch insns
3337 (define_expand "beq"
3338   [(set (pc)
3339         (if_then_else (eq (match_dup 1) (const_int 0))
3340                       (label_ref (match_operand 0 "" ""))
3341                       (pc)))]
3342   ""
3343   "
3345   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3346                                  arm_compare_fp);
3350 (define_expand "bne"
3351   [(set (pc)
3352         (if_then_else (ne (match_dup 1) (const_int 0))
3353                       (label_ref (match_operand 0 "" ""))
3354                       (pc)))]
3355   ""
3356   "
3358   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3359                                  arm_compare_fp);
3363 (define_expand "bgt"
3364   [(set (pc)
3365         (if_then_else (gt (match_dup 1) (const_int 0))
3366                       (label_ref (match_operand 0 "" ""))
3367                       (pc)))]
3368   ""
3369   "
3371   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3372                                  arm_compare_fp);
3376 (define_expand "ble"
3377   [(set (pc)
3378         (if_then_else (le (match_dup 1) (const_int 0))
3379                       (label_ref (match_operand 0 "" ""))
3380                       (pc)))]
3381   ""
3382   "
3384   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3385                                  arm_compare_fp);
3389 (define_expand "bge"
3390   [(set (pc)
3391         (if_then_else (ge (match_dup 1) (const_int 0))
3392                       (label_ref (match_operand 0 "" ""))
3393                       (pc)))]
3394   ""
3395   "
3397   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3398                                  arm_compare_fp);
3402 (define_expand "blt"
3403   [(set (pc)
3404         (if_then_else (lt (match_dup 1) (const_int 0))
3405                       (label_ref (match_operand 0 "" ""))
3406                       (pc)))]
3407   ""
3408   "
3410   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3411                                  arm_compare_fp);
3415 (define_expand "bgtu"
3416   [(set (pc)
3417         (if_then_else (gtu (match_dup 1) (const_int 0))
3418                       (label_ref (match_operand 0 "" ""))
3419                       (pc)))]
3420   ""
3421   "
3423   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3424                                  arm_compare_fp);
3428 (define_expand "bleu"
3429   [(set (pc)
3430         (if_then_else (leu (match_dup 1) (const_int 0))
3431                       (label_ref (match_operand 0 "" ""))
3432                       (pc)))]
3433   ""
3434   "
3436   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3437                                  arm_compare_fp);
3441 (define_expand "bgeu"
3442   [(set (pc)
3443         (if_then_else (geu (match_dup 1) (const_int 0))
3444                       (label_ref (match_operand 0 "" ""))
3445                       (pc)))]
3446   ""
3447   "
3449   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3450                                  arm_compare_fp);
3454 (define_expand "bltu"
3455   [(set (pc)
3456         (if_then_else (ltu (match_dup 1) (const_int 0))
3457                       (label_ref (match_operand 0 "" ""))
3458                       (pc)))]
3459   ""
3460   "
3462   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3463                                  arm_compare_fp);
3467 ;; patterns to match conditional branch insns
3469 (define_insn "*condbranch"
3470   [(set (pc)
3471         (if_then_else (match_operator 1 "comparison_operator"
3472                                         [(reg 24) (const_int 0)])
3473                       (label_ref (match_operand 0 "" ""))
3474                       (pc)))]
3475   ""
3476   "*
3478   extern int arm_ccfsm_state;
3480   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3481   {
3482     arm_ccfsm_state += 2;
3483     return \"\";
3484   }
3485   return \"b%d1\\t%l0\";
3487 [(set_attr "conds" "use")])
3489 (define_insn "*condbranch_reversed"
3490   [(set (pc)
3491         (if_then_else (match_operator 1 "comparison_operator"
3492                                         [(reg 24) (const_int 0)])
3493                       (pc)
3494                       (label_ref (match_operand 0 "" ""))))]
3495   ""
3496   "*
3498   extern int arm_ccfsm_state;
3500   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3501   {
3502     arm_ccfsm_state += 2;
3503     return \"\";
3504   }
3505   return \"b%D1\\t%l0\";
3507 [(set_attr "conds" "use")])
3510 ; scc insns
3512 (define_expand "seq"
3513   [(set (match_operand:SI 0 "s_register_operand" "=r")
3514         (eq:SI (match_dup 1) (const_int 0)))]
3515   ""
3516   "
3518   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3519                                  arm_compare_fp);
3523 (define_expand "sne"
3524   [(set (match_operand:SI 0 "s_register_operand" "=r")
3525         (ne:SI (match_dup 1) (const_int 0)))]
3526   ""
3527   "
3529   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3530                                  arm_compare_fp);
3534 (define_expand "sgt"
3535   [(set (match_operand:SI 0 "s_register_operand" "=r")
3536         (gt:SI (match_dup 1) (const_int 0)))]
3537   ""
3538   "
3540   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3541                                  arm_compare_fp);
3545 (define_expand "sle"
3546   [(set (match_operand:SI 0 "s_register_operand" "=r")
3547         (le:SI (match_dup 1) (const_int 0)))]
3548   ""
3549   "
3551   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3552                                  arm_compare_fp);
3556 (define_expand "sge"
3557   [(set (match_operand:SI 0 "s_register_operand" "=r")
3558         (ge:SI (match_dup 1) (const_int 0)))]
3559   ""
3560   "
3562   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3563                                  arm_compare_fp);
3567 (define_expand "slt"
3568   [(set (match_operand:SI 0 "s_register_operand" "=r")
3569         (lt:SI (match_dup 1) (const_int 0)))]
3570   ""
3571   "
3573   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3574                                  arm_compare_fp);
3578 (define_expand "sgtu"
3579   [(set (match_operand:SI 0 "s_register_operand" "=r")
3580         (gtu:SI (match_dup 1) (const_int 0)))]
3581   ""
3582   "
3584   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3585                                  arm_compare_fp);
3589 (define_expand "sleu"
3590   [(set (match_operand:SI 0 "s_register_operand" "=r")
3591         (leu:SI (match_dup 1) (const_int 0)))]
3592   ""
3593   "
3595   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3596                                  arm_compare_fp);
3600 (define_expand "sgeu"
3601   [(set (match_operand:SI 0 "s_register_operand" "=r")
3602         (geu:SI (match_dup 1) (const_int 0)))]
3603   ""
3604   "
3606   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3607                                  arm_compare_fp);
3611 (define_expand "sltu"
3612   [(set (match_operand:SI 0 "s_register_operand" "=r")
3613         (ltu:SI (match_dup 1) (const_int 0)))]
3614   ""
3615   "
3617   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3618                                  arm_compare_fp);
3622 (define_insn "*mov_scc"
3623   [(set (match_operand:SI 0 "s_register_operand" "=r")
3624         (match_operator:SI 1 "comparison_operator" [(reg 24) (const_int 0)]))]
3625   ""
3626   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
3627 [(set_attr "conds" "use")
3628  (set_attr "length" "8")])
3630 (define_insn "*mov_negscc"
3631   [(set (match_operand:SI 0 "s_register_operand" "=r")
3632         (neg:SI (match_operator:SI 1 "comparison_operator"
3633                  [(reg 24) (const_int 0)])))]
3634   ""
3635   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
3636 [(set_attr "conds" "use")
3637  (set_attr "length" "8")])
3639 (define_insn "*mov_notscc"
3640   [(set (match_operand:SI 0 "s_register_operand" "=r")
3641         (not:SI (match_operator:SI 1 "comparison_operator"
3642                  [(reg 24) (const_int 0)])))]
3643   ""
3644   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
3645 [(set_attr "conds" "use")
3646  (set_attr "length" "8")])
3649 ;; Conditional move insns
3651 (define_expand "movsicc"
3652   [(set (match_operand:SI 0 "register_operand" "")
3653         (if_then_else:SI (match_operand 1 "comparison_operator" "")
3654                          (match_operand:SI 2 "arm_not_operand" "")
3655                          (match_operand:SI 3 "register_operand" "")))]
3656   ""
3657   "
3659   enum rtx_code code = GET_CODE (operands[1]);
3660   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3661                                arm_compare_fp);
3663   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3666 (define_expand "movsfcc"
3667   [(set (match_operand:SF 0 "register_operand" "")
3668         (if_then_else:SF (match_operand 1 "comparison_operator" "")
3669                          (match_operand:SF 2 "nonmemory_operand" "")
3670                          (match_operand:SF 3 "register_operand" "")))]
3671   ""
3672   "
3674   enum rtx_code code = GET_CODE (operands[1]);
3675   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3676                                arm_compare_fp);
3678   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3681 (define_expand "movdfcc"
3682   [(set (match_operand:DF 0 "register_operand" "")
3683         (if_then_else:DF (match_operand 1 "comparison_operator" "")
3684                          (match_operand:DF 2 "nonmemory_operand" "")
3685                          (match_operand:DF 3 "register_operand" "")))]
3686   "TARGET_HARD_FLOAT"
3687   "
3689   enum rtx_code code = GET_CODE (operands[1]);
3690   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3691                                arm_compare_fp);
3693   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3696 (define_insn "*movsicc_insn"
3697   [(set (match_operand:SI 0 "register_operand" "=r,r")
3698         (if_then_else:SI (match_operator 1 "comparison_operator" 
3699                           [(reg 24) (const_int 0)])
3700                          (match_operand:SI 2 "arm_not_operand" "rI,K")
3701                          (match_operand:SI 3 "register_operand" "0,0")))]
3702   ""
3703   "@
3704    mov%d1\\t%0, %2
3705    mvn%d1\\t%0, #%B2"
3706   [(set_attr "type" "*,*")
3707    (set_attr "conds" "use,use")])
3709 (define_insn "*movsfcc_hard_insn"
3710   [(set (match_operand:SF 0 "register_operand" "=f")
3711         (if_then_else:SF (match_operator 1 "comparison_operator" 
3712                           [(reg 24) (const_int 0)])
3713                          (match_operand:SF 2 "register_operand" "f")
3714                          (match_operand:SF 3 "register_operand" "0")))]
3715   "TARGET_HARD_FLOAT"
3716   "mvf%d1s\\t%0, %2"
3717   [(set_attr "type" "ffarith")
3718    (set_attr "conds" "use")])
3720 (define_insn "*movsfcc_soft_insn"
3721   [(set (match_operand:SF 0 "register_operand" "=r")
3722         (if_then_else:SF (match_operator 1 "comparison_operator"
3723                           [(reg 24) (const_int 0)])
3724                          (match_operand:SF 2 "register_operand" "r")
3725                          (match_operand:SF 3 "register_operand" "0")))]
3726   "TARGET_SOFT_FLOAT"
3727   "mov%d1\\t%0, %2"
3728   [(set_attr "type" "*")
3729    (set_attr "conds" "use")])
3731 (define_insn "*movdfcc_insn"
3732   [(set (match_operand:DF 0 "register_operand" "=f")
3733         (if_then_else:DF (match_operator 1 "comparison_operator"
3734                           [(reg 24) (const_int 0)])
3735                          (match_operand:DF 2 "register_operand" "f")
3736                          (match_operand:DF 3 "register_operand" "0")))]
3737   "TARGET_HARD_FLOAT"
3738   "mvf%d1d\\t%0, %2"
3739   [(set_attr "type" "ffarith")
3740    (set_attr "conds" "use")])
3742 ;; Jump and linkage insns
3744 (define_insn "jump"
3745   [(set (pc)
3746         (label_ref (match_operand 0 "" "")))]
3747   ""
3748   "*
3750   extern int arm_ccfsm_state;
3752   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3753   {
3754     arm_ccfsm_state += 2;
3755     return \"\";
3756   }
3757   return \"b%?\\t%l0\";
3760 (define_expand "call"
3761   [(parallel [(call (match_operand 0 "memory_operand" "")
3762                     (match_operand 1 "general_operand" ""))
3763               (clobber (reg:SI 14))])]
3764   ""
3765   "")
3767 (define_insn "*call_reg"
3768   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
3769          (match_operand 1 "" "g"))
3770    (clobber (reg:SI 14))]
3771   ""
3772   "*
3773   return output_call (operands);
3775 ;; length is worst case, normally it is only two
3776 [(set_attr "length" "12")
3777  (set_attr "type" "call")])
3779 (define_insn "*call_mem"
3780   [(call (mem:SI (match_operand 0 "memory_operand" "m"))
3781          (match_operand 1 "general_operand" "g"))
3782    (clobber (reg:SI 14))]
3783   ""
3784   "*
3785   return output_call_mem (operands);
3787 [(set_attr "length" "12")
3788  (set_attr "type" "call")])
3790 (define_expand "call_value"
3791   [(parallel [(set (match_operand 0 "" "=rf")
3792                    (call (match_operand 1 "memory_operand" "m")
3793                          (match_operand 2 "general_operand" "g")))
3794               (clobber (reg:SI 14))])]
3795   ""
3796   "")
3798 (define_insn "*call_value_reg"
3799   [(set (match_operand 0 "" "=rf")
3800         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
3801               (match_operand 2 "general_operand" "g")))
3802    (clobber (reg:SI 14))]
3803   ""
3804   "*
3805   return output_call (&operands[1]);
3807 [(set_attr "length" "12")
3808  (set_attr "type" "call")])
3810 (define_insn "*call_value_mem"
3811   [(set (match_operand 0 "" "=rf")
3812         (call (mem:SI (match_operand 1 "memory_operand" "m"))
3813         (match_operand 2 "general_operand" "g")))
3814    (clobber (reg:SI 14))]
3815   "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
3816   "*
3817   return output_call_mem (&operands[1]);
3819 [(set_attr "length" "12")
3820  (set_attr "type" "call")])
3822 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
3823 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
3825 (define_insn "*call_symbol"
3826   [(call (mem:SI (match_operand:SI 0 "" "X"))
3827          (match_operand:SI 1 "general_operand" "g"))
3828    (clobber (reg:SI 14))]
3829   "GET_CODE (operands[0]) == SYMBOL_REF"
3830   "bl%?\\t%a0"
3831 [(set_attr "type" "call")])
3833 (define_insn "*call_value_symbol"
3834   [(set (match_operand 0 "s_register_operand" "=rf")
3835         (call (mem:SI (match_operand:SI 1 "" "X"))
3836         (match_operand:SI 2 "general_operand" "g")))
3837    (clobber (reg:SI 14))]
3838   "GET_CODE(operands[1]) == SYMBOL_REF"
3839   "bl%?\\t%a1"
3840 [(set_attr "type" "call")])
3842 ;; Often the return insn will be the same as loading from memory, so set attr
3843 (define_insn "return"
3844   [(return)]
3845   "USE_RETURN_INSN"
3846   "*
3848   extern int arm_ccfsm_state;
3850   if (arm_ccfsm_state == 2)
3851   {
3852     arm_ccfsm_state += 2;
3853     return \"\";
3854   }
3855   return output_return_instruction (NULL, TRUE, FALSE);
3857 [(set_attr "type" "load")])
3859 (define_insn "*cond_return"
3860   [(set (pc)
3861         (if_then_else (match_operator 0 "comparison_operator"
3862                        [(reg 24) (const_int 0)])
3863                       (return)
3864                       (pc)))]
3865   "USE_RETURN_INSN"
3866   "*
3868   extern int arm_ccfsm_state;
3870   if (arm_ccfsm_state == 2)
3871   {
3872     arm_ccfsm_state += 2;
3873     return \"\";
3874   }
3875   return output_return_instruction (operands[0], TRUE, FALSE);
3877 [(set_attr "conds" "use")
3878  (set_attr "type" "load")])
3880 (define_insn "*cond_return_inverted"
3881   [(set (pc)
3882         (if_then_else (match_operator 0 "comparison_operator"
3883                        [(reg 24) (const_int 0)])
3884                       (pc)
3885                       (return)))]
3886   "USE_RETURN_INSN"
3887   "*
3889   extern int arm_ccfsm_state;
3891   if (arm_ccfsm_state == 2)
3892   {
3893     arm_ccfsm_state += 2;
3894     return \"\";
3895   }
3896   return output_return_instruction (operands[0], TRUE, TRUE);
3898 [(set_attr "conds" "use")
3899  (set_attr "type" "load")])
3901 ;; Call subroutine returning any type.
3903 (define_expand "untyped_call"
3904   [(parallel [(call (match_operand 0 "" "")
3905                     (const_int 0))
3906               (match_operand 1 "" "")
3907               (match_operand 2 "" "")])]
3908   ""
3909   "
3911   int i;
3913   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
3915   for (i = 0; i < XVECLEN (operands[2], 0); i++)
3916     {
3917       rtx set = XVECEXP (operands[2], 0, i);
3918       emit_move_insn (SET_DEST (set), SET_SRC (set));
3919     }
3921   /* The optimizer does not know that the call sets the function value
3922      registers we stored in the result block.  We avoid problems by
3923      claiming that all hard registers are used and clobbered at this
3924      point.  */
3925   emit_insn (gen_blockage ());
3927   DONE;
3930 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
3931 ;; all of memory.  This blocks insns from being moved across this point.
3933 (define_insn "blockage"
3934   [(unspec_volatile [(const_int 0)] 0)]
3935   ""
3936   ""
3937 [(set_attr "length" "0")
3938  (set_attr "type" "block")])
3940 (define_expand "casesi"
3941   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
3942    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
3943    (match_operand:SI 2 "const_int_operand" "")  ; total range
3944    (match_operand:SI 3 "" "")                   ; table label
3945    (match_operand:SI 4 "" "")]                  ; Out of range label
3946   ""
3947   "
3949   rtx reg;
3950   if (operands[1] != const0_rtx)
3951     {
3952       reg = gen_reg_rtx (SImode);
3953       emit_insn (gen_addsi3 (reg, operands[0],
3954                              GEN_INT (-INTVAL (operands[1]))));
3955       operands[0] = reg;
3956     }
3958   if (! const_ok_for_arm (INTVAL (operands[2])))
3959     operands[2] = force_reg (SImode, operands[2]);
3961   emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
3962                                        operands[4]));
3963   DONE;
3966 (define_insn "casesi_internal"
3967   [(set (pc)
3968         (if_then_else
3969          (leu (match_operand:SI 0 "s_register_operand" "r")
3970               (match_operand:SI 1 "arm_rhs_operand" "rI"))
3971          (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
3972                           (label_ref (match_operand 2 "" ""))))
3973          (label_ref (match_operand 3 "" ""))))]
3974   ""
3975   "*
3976   if (flag_pic)
3977     return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
3978   return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
3980 [(set_attr "conds" "clob")
3981  (set_attr "length" "12")])
3983 (define_insn "indirect_jump"
3984   [(set (pc)
3985         (match_operand:SI 0 "s_register_operand" "r"))]
3986   ""
3987   "mov%?\\t%|pc, %0\\t%@ indirect jump")
3989 (define_insn "*load_indirect_jump"
3990   [(set (pc)
3991         (match_operand:SI 0 "memory_operand" "m"))]
3992   ""
3993   "ldr%?\\t%|pc, %0\\t%@ indirect jump"
3994 [(set_attr "type" "load")])
3996 ;; Misc insns
3998 (define_insn "nop"
3999   [(const_int 0)]
4000   ""
4001   "mov%?\\tr0, r0\\t%@ nop")
4003 ;; Patterns to allow combination of arithmetic, cond code and shifts
4005 (define_insn "*arith_shiftsi"
4006   [(set (match_operand:SI 0 "s_register_operand" "=r")
4007         (match_operator:SI 1 "shiftable_operator"
4008           [(match_operator:SI 3 "shift_operator"
4009              [(match_operand:SI 4 "s_register_operand" "r")
4010               (match_operand:SI 5 "reg_or_int_operand" "rI")])
4011            (match_operand:SI 2 "s_register_operand" "r")]))]
4012   ""
4013   "%i1%?\\t%0, %2, %4%S3")
4015 (define_insn "*arith_shiftsi_compare0"
4016   [(set (reg:CC_NOOV 24)
4017         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4018                           [(match_operator:SI 3 "shift_operator"
4019                             [(match_operand:SI 4 "s_register_operand" "r")
4020                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4021                            (match_operand:SI 2 "s_register_operand" "r")])
4022                          (const_int 0)))
4023    (set (match_operand:SI 0 "s_register_operand" "=r")
4024         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4025                          (match_dup 2)]))]
4026   ""
4027   "%i1%?s\\t%0, %2, %4%S3"
4028 [(set_attr "conds" "set")])
4030 (define_insn "*arith_shiftsi_compare0_scratch"
4031   [(set (reg:CC_NOOV 24)
4032         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4033                           [(match_operator:SI 3 "shift_operator"
4034                             [(match_operand:SI 4 "s_register_operand" "r")
4035                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4036                            (match_operand:SI 2 "s_register_operand" "r")])
4037                          (const_int 0)))
4038    (clobber (match_scratch:SI 0 "=r"))]
4039   ""
4040   "%i1%?s\\t%0, %2, %4%S3"
4041 [(set_attr "conds" "set")])
4043 (define_insn "*sub_shiftsi"
4044   [(set (match_operand:SI 0 "s_register_operand" "=r")
4045         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4046                   (match_operator:SI 2 "shift_operator"
4047                    [(match_operand:SI 3 "s_register_operand" "r")
4048                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4049   ""
4050   "sub%?\\t%0, %1, %3%S2")
4052 (define_insn "*sub_shiftsi_compare0"
4053   [(set (reg:CC_NOOV 24)
4054         (compare:CC_NOOV
4055          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4056                    (match_operator:SI 2 "shift_operator"
4057                     [(match_operand:SI 3 "s_register_operand" "r")
4058                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4059          (const_int 0)))
4060    (set (match_operand:SI 0 "s_register_operand" "=r")
4061         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4062                                                  (match_dup 4)])))]
4063   ""
4064   "sub%?s\\t%0, %1, %3%S2"
4065 [(set_attr "conds" "set")])
4067 (define_insn "*sub_shiftsi_compare0_scratch"
4068   [(set (reg:CC_NOOV 24)
4069         (compare:CC_NOOV
4070          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4071                    (match_operator:SI 2 "shift_operator"
4072                     [(match_operand:SI 3 "s_register_operand" "r")
4073                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4074          (const_int 0)))
4075    (clobber (match_scratch:SI 0 "=r"))]
4076   ""
4077   "sub%?s\\t%0, %1, %3%S2"
4078 [(set_attr "conds" "set")])
4080 ;; These variants of the above insns can occur if the first operand is the
4081 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
4082 ;; seem to be a way around it.  Most of the predicates have to be null
4083 ;; because the format can be generated part way through reload, so
4084 ;; if we don't match it as soon as it becomes available, reload doesn't know
4085 ;; how to reload pseudos that haven't got hard registers; the constraints will
4086 ;; sort everything out.
4088 (define_insn "*reload_mulsi3"
4089   [(set (match_operand:SI 0 "" "=&r")
4090         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4091                            [(match_operand:SI 3 "" "r")
4092                             (match_operand:SI 4 "" "rM")])
4093                           (match_operand:SI 2 "" "r"))
4094                  (match_operand:SI 1 "const_int_operand" "n")))]
4095   "reload_in_progress"
4096   "*
4097   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4098   operands[2] = operands[1];
4099   operands[1] = operands[0];
4100   return output_add_immediate (operands);
4102 ; we have no idea how long the add_immediate is, it could be up to 4.
4103 [(set_attr "length" "20")])
4105 (define_insn "*relaod_mulsi_compare0"
4106   [(set (reg:CC_NOOV 24)
4107         (compare:CC_NOOV (plus:SI
4108                           (plus:SI 
4109                            (match_operator:SI 5 "shift_operator"
4110                             [(match_operand:SI 3 "" "r")
4111                              (match_operand:SI 4 "" "rM")])
4112                            (match_operand:SI 1 "" "r"))
4113                           (match_operand:SI 2 "const_int_operand" "n"))
4114                          (const_int 0)))
4115    (set (match_operand:SI 0 "" "=&r")
4116         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4117                           (match_dup 1))
4118                  (match_dup 2)))]
4119   "reload_in_progress"
4120   "*
4121   output_add_immediate (operands);
4122   return \"add%?s\\t%0, %0, %3%S5\";
4124 [(set_attr "conds" "set")
4125  (set_attr "length" "20")])
4127 (define_insn "*reload_mulsi_compare0_scratch"
4128   [(set (reg:CC_NOOV 24)
4129         (compare:CC_NOOV (plus:SI
4130                           (plus:SI 
4131                            (match_operator:SI 5 "shift_operator"
4132                             [(match_operand:SI 3 "" "r")
4133                              (match_operand:SI 4 "" "rM")])
4134                            (match_operand:SI 1 "" "r"))
4135                           (match_operand:SI 2 "const_int_operand" "n"))
4136                          (const_int 0)))
4137    (clobber (match_scratch:SI 0 "=&r"))]
4138   "reload_in_progress"
4139   "*
4140   output_add_immediate (operands);
4141   return \"add%?s\\t%0, %0, %3%S5\";
4143 [(set_attr "conds" "set")
4144  (set_attr "length" "20")])
4146 ;; These are similar, but are needed when the mla pattern contains the
4147 ;; eliminated register as operand 3.
4149 (define_insn "*reload_muladdsi"
4150   [(set (match_operand:SI 0 "" "=&r,&r")
4151         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4152                                    (match_operand:SI 2 "" "r,r"))
4153                           (match_operand:SI 3 "" "r,r"))
4154                  (match_operand:SI 4 "const_int_operand" "n,n")))]
4155   "reload_in_progress"
4156   "*
4157   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4158   operands[2] = operands[4];
4159   operands[1] = operands[0];
4160   return output_add_immediate (operands);
4162 [(set_attr "length" "20")
4163  (set_attr "type" "mult")])
4165 (define_insn "*reload_muladdsi_compare0"
4166   [(set (reg:CC_NOOV 24)
4167         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4168                                             (match_operand:SI 3 "" "r")
4169                                             (match_operand:SI 4 "" "r"))
4170                                            (match_operand:SI 1 "" "r"))
4171                                   (match_operand:SI 2 "const_int_operand" "n"))
4172                          (const_int 0)))
4173    (set (match_operand:SI 0 "" "=&r")
4174         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4175                  (match_dup 2)))]
4176   "reload_in_progress"
4177   "*
4178   output_add_immediate (operands);
4179   output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4180   return \"\";
4182 [(set_attr "length" "20")
4183  (set_attr "conds" "set")
4184  (set_attr "type" "mult")])
4186 (define_insn "*reload_muladdsi_compare0_scratch"
4187   [(set (reg:CC_NOOV 24)
4188         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4189                                             (match_operand:SI 3 "" "r")
4190                                             (match_operand:SI 4 "" "r"))
4191                                            (match_operand:SI 1 "" "r"))
4192                                   (match_operand:SI 2 "const_int_operand" "n"))
4193                          (const_int 0)))
4194    (clobber (match_scratch:SI 0 "=&r"))]
4195   "reload_in_progress"
4196   "*
4197   output_add_immediate (operands);
4198   return \"mla%?s\\t%0, %3, %4, %0\";
4200 [(set_attr "length" "20")
4201  (set_attr "conds" "set")
4202  (set_attr "type" "mult")])
4206 (define_insn "*and_scc"
4207   [(set (match_operand:SI 0 "s_register_operand" "=r")
4208         (and:SI (match_operator 1 "comparison_operator"
4209                  [(match_operand 3 "cc_register" "") (const_int 0)])
4210                 (match_operand:SI 2 "s_register_operand" "r")))]
4211   ""
4212   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
4213 [(set_attr "conds" "use")
4214  (set_attr "length" "8")])
4216 (define_insn "*ior_scc"
4217   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4218         (ior:SI (match_operator 2 "comparison_operator"
4219                  [(reg 24) (const_int 0)])
4220                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
4221   ""
4222   "@
4223    orr%d2\\t%0, %1, #1
4224    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
4225 [(set_attr "conds" "use")
4226  (set_attr "length" "4,8")])
4228 (define_insn "*compare_scc"
4229   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4230         (match_operator 1 "comparison_operator"
4231          [(match_operand:SI 2 "s_register_operand" "r,r")
4232           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4233    (clobber (reg 24))]
4234   ""
4235   "*
4236   if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4237     return \"mov\\t%0, %2, lsr #31\";
4239   if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4240     return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4242   if (GET_CODE (operands[1]) == NE)
4243     {
4244       if (which_alternative == 1)
4245         return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4246       return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4247     }
4248   if (which_alternative == 1)
4249     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4250   else
4251     output_asm_insn (\"cmp\\t%2, %3\", operands);
4252   return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4254 [(set_attr "conds" "clob")
4255  (set_attr "length" "12")])
4257 (define_insn "*cond_move"
4258   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4259         (if_then_else:SI (match_operator 3 "equality_operator"
4260                           [(match_operator 4 "comparison_operator"
4261                             [(reg 24) (const_int 0)])
4262                            (const_int 0)])
4263                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4264                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4265   ""
4266   "*
4267   if (GET_CODE (operands[3]) == NE)
4268     {
4269       if (which_alternative != 1)
4270         output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4271       if (which_alternative != 0)
4272         output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4273       return \"\";
4274     }
4275   if (which_alternative != 0)
4276     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4277   if (which_alternative != 1)
4278     output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4279   return \"\";
4281 [(set_attr "conds" "use")
4282  (set_attr "length" "4,4,8")])
4284 (define_insn "*cond_arith"
4285   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4286         (match_operator:SI 5 "shiftable_operator" 
4287          [(match_operator:SI 4 "comparison_operator"
4288            [(match_operand:SI 2 "s_register_operand" "r,r")
4289             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4290           (match_operand:SI 1 "s_register_operand" "0,?r")]))
4291    (clobber (reg 24))]
4292   ""
4293   "*
4294   if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4295     return \"%i5\\t%0, %1, %2, lsr #31\";
4297   output_asm_insn (\"cmp\\t%2, %3\", operands);
4298   if (GET_CODE (operands[5]) == AND)
4299     output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4300   else if (GET_CODE (operands[5]) == MINUS)
4301     output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4302   else if (which_alternative != 0)
4303     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4304   return \"%i5%d4\\t%0, %1, #1\";
4306 [(set_attr "conds" "clob")
4307  (set_attr "length" "12")])
4309 (define_insn "*cond_sub"
4310   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4311         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4312                   (match_operator:SI 4 "comparison_operator"
4313                    [(match_operand:SI 2 "s_register_operand" "r,r")
4314                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4315    (clobber (reg 24))]
4316   ""
4317   "*
4318   output_asm_insn (\"cmp\\t%2, %3\", operands);
4319   if (which_alternative != 0)
4320     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4321   return \"sub%d4\\t%0, %1, #1\";
4323 [(set_attr "conds" "clob")
4324  (set_attr "length" "8,12")])
4326 (define_insn "*cmp_ite0"
4327   [(set (match_operand 6 "dominant_cc_register" "")
4328         (compare
4329          (if_then_else:SI
4330           (match_operator 4 "comparison_operator"
4331            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4332             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4333           (match_operator:SI 5 "comparison_operator"
4334            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4335             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4336           (const_int 0))
4337          (const_int 0)))]
4338   ""
4339   "*
4341   char* opcodes[4][2] =
4342   {
4343     {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
4344     {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
4345     {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
4346     {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
4347      \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
4348   };
4349   int swap =
4350     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
4352   return opcodes[which_alternative][swap];
4355 [(set_attr "conds" "set")
4356  (set_attr "length" "8")])
4358 (define_insn "*cmp_ite1"
4359   [(set (match_operand 6 "dominant_cc_register" "")
4360         (compare
4361          (if_then_else:SI
4362           (match_operator 4 "comparison_operator"
4363            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4364             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4365           (match_operator:SI 5 "comparison_operator"
4366            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4367             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4368           (const_int 1))
4369          (const_int 0)))]
4370   ""
4371   "*
4373   char* opcodes[4][2] =
4374   {
4375     {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
4376     {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
4377     {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
4378     {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
4379      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
4380   };
4381   int swap =
4382     comparison_dominates_p (GET_CODE (operands[5]),
4383                             reverse_condition (GET_CODE (operands[4])));
4385   return opcodes[which_alternative][swap];
4388 [(set_attr "conds" "set")
4389  (set_attr "length" "8")])
4391 (define_insn "*negscc"
4392   [(set (match_operand:SI 0 "s_register_operand" "=r")
4393         (neg:SI (match_operator 3 "comparison_operator"
4394                  [(match_operand:SI 1 "s_register_operand" "r")
4395                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4396    (clobber (reg 24))]
4397   ""
4398   "*
4399   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4400     return \"mov\\t%0, %1, asr #31\";
4402   if (GET_CODE (operands[3]) == NE)
4403     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4405   if (GET_CODE (operands[3]) == GT)
4406     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4408   output_asm_insn (\"cmp\\t%1, %2\", operands);
4409   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4410   return \"mvn%d3\\t%0, #0\";
4412 [(set_attr "conds" "clob")
4413  (set_attr "length" "12")])
4415 (define_insn "movcond"
4416   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4417         (if_then_else:SI
4418          (match_operator 5 "comparison_operator"
4419           [(match_operand:SI 3 "s_register_operand" "r,r,r")
4420            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4421          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4422          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4423    (clobber (reg 24))]
4424   ""
4425   "*
4426   if (GET_CODE (operands[5]) == LT
4427       && (operands[4] == const0_rtx))
4428     {
4429       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4430         {
4431           if (operands[2] == const0_rtx)
4432             return \"and\\t%0, %1, %3, asr #31\";
4433           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4434         }
4435       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4436         {
4437           if (operands[1] == const0_rtx)
4438             return \"bic\\t%0, %2, %3, asr #31\";
4439           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4440         }
4441       /* The only case that falls through to here is when both ops 1 & 2
4442          are constants */
4443     }
4445   if (GET_CODE (operands[5]) == GE
4446       && (operands[4] == const0_rtx))
4447     {
4448       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4449         {
4450           if (operands[2] == const0_rtx)
4451             return \"bic\\t%0, %1, %3, asr #31\";
4452           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4453         }
4454       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4455         {
4456           if (operands[1] == const0_rtx)
4457             return \"and\\t%0, %2, %3, asr #31\";
4458           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4459         }
4460       /* The only case that falls through to here is when both ops 1 & 2
4461          are constants */
4462     }
4463   if (GET_CODE (operands[4]) == CONST_INT
4464       && !const_ok_for_arm (INTVAL (operands[4])))
4465     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4466   else
4467     output_asm_insn (\"cmp\\t%3, %4\", operands);
4468   if (which_alternative != 0)
4469     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4470   if (which_alternative != 1)
4471     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4472   return \"\";
4474 [(set_attr "conds" "clob")
4475  (set_attr "length" "8,8,12")])
4477 (define_insn "*ifcompare_arith_arith"
4478   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4479         (if_then_else:SI (match_operator 9 "comparison_operator"
4480                           [(match_operand:SI 5 "s_register_operand" "r,r")
4481                            (match_operand:SI 6 "arm_add_operand" "rI,L")])
4482                          (match_operator:SI 8 "shiftable_operator"
4483                           [(match_operand:SI 1 "s_register_operand" "r,r")
4484                            (match_operand:SI 2 "arm_rhs_operand" "rI,rI")])
4485                          (match_operator:SI 7 "shiftable_operator"
4486                           [(match_operand:SI 3 "s_register_operand" "r,r")
4487                            (match_operand:SI 4 "arm_rhs_operand" "rI,rI")])))
4488    (clobber (reg 24))]
4489   ""
4490   "@
4491    cmp\\t%5, %6\;%I8%d9\\t%0, %1, %2\;%I7%D9\\t%0, %3, %4
4492    cmn\\t%5, #%n6\;%I8%d9\\t%0, %1, %2\;%I7%D9\\t%0, %3, %4"
4493 [(set_attr "conds" "clob")
4494  (set_attr "length" "12")])
4496 (define_insn "*ifcompare_arith_move"
4497   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4498         (if_then_else:SI (match_operator 6 "comparison_operator"
4499                           [(match_operand:SI 2 "s_register_operand" "r,r")
4500                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
4501                          (match_operator:SI 7 "shiftable_operator"
4502                           [(match_operand:SI 4 "s_register_operand" "r,r")
4503                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
4504                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4505    (clobber (reg 24))]
4506   ""
4507   "*
4508   /* If we have an operation where (op x 0) is the identity operation and
4509      the conditional operator is LT or GE and we are comparing against zero and
4510      everything is in registers then we can do this in two instructions */
4511   if (operands[3] == const0_rtx
4512       && GET_CODE (operands[7]) != AND
4513       && GET_CODE (operands[5]) == REG
4514       && GET_CODE (operands[1]) == REG 
4515       && REGNO (operands[1]) == REGNO (operands[4])
4516       && REGNO (operands[4]) != REGNO (operands[0]))
4517     {
4518       if (GET_CODE (operands[6]) == LT)
4519         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4520       else if (GET_CODE (operands[6]) == GE)
4521         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4522     }
4523   if (GET_CODE (operands[3]) == CONST_INT
4524       && !const_ok_for_arm (INTVAL (operands[3])))
4525     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4526   else
4527     output_asm_insn (\"cmp\\t%2, %3\", operands);
4528   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
4529   if (which_alternative != 0)
4530     {
4531       if (GET_CODE (operands[1]) == MEM)
4532         return \"ldr%D6\\t%0, %1\";
4533       else
4534         return \"mov%D6\\t%0, %1\";
4535     }
4536   return \"\";
4538 [(set_attr "conds" "clob")
4539  (set_attr "length" "8,12")])
4541 (define_insn "*ifcompare_move_arith"
4542   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4543         (if_then_else:SI (match_operator 6 "comparison_operator"
4544                           [(match_operand:SI 4 "s_register_operand" "r,r")
4545                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4546                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4547                          (match_operator:SI 7 "shiftable_operator"
4548                           [(match_operand:SI 2 "s_register_operand" "r,r")
4549                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4550    (clobber (reg 24))]
4551   ""
4552   "*
4553   /* If we have an operation where (op x 0) is the identity operation and
4554      the conditional operator is LT or GE and we are comparing against zero and
4555      everything is in registers then we can do this in two instructions */
4556   if (operands[5] == const0_rtx
4557       && GET_CODE (operands[7]) != AND
4558       && GET_CODE (operands[3]) == REG
4559       && GET_CODE (operands[1]) == REG 
4560       && REGNO (operands[1]) == REGNO (operands[2])
4561       && REGNO (operands[2]) != REGNO (operands[0]))
4562     {
4563       if (GET_CODE (operands[6]) == GE)
4564         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4565       else if (GET_CODE (operands[6]) == LT)
4566         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4567     }
4569   if (GET_CODE (operands[5]) == CONST_INT
4570       && !const_ok_for_arm (INTVAL (operands[5])))
4571     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4572   else
4573     output_asm_insn (\"cmp\\t%4, %5\", operands);
4575   if (which_alternative != 0)
4576     {
4577       if (GET_CODE (operands[1]) == MEM)
4578         output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4579       else
4580         output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4581     }
4582   return \"%I7%D6\\t%0, %2, %3\";
4584 [(set_attr "conds" "clob")
4585  (set_attr "length" "8,12")])
4587 (define_insn "*ifcompare_plus_move"
4588   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4589         (if_then_else:SI (match_operator 6 "comparison_operator"
4590                           [(match_operand:SI 4 "s_register_operand" "r,r")
4591                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4592                          (plus:SI
4593                           (match_operand:SI 2 "s_register_operand" "r,r")
4594                           (match_operand:SI 3 "arm_add_operand" "rL,rL"))
4595                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4596    (clobber (reg 24))]
4597   ""
4598   "*
4600   if (GET_CODE (operands[5]) == CONST_INT
4601       && !const_ok_for_arm (INTVAL (operands[5])))
4602     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4603   else
4604     output_asm_insn (\"cmp\\t%4, %5\", operands);
4605   if (GET_CODE (operands[3]) == CONST_INT
4606       && !const_ok_for_arm (INTVAL (operands[3])))
4607     output_asm_insn (\"sub%d6\\t%0, %2, #%n3\", operands);
4608   else
4609     output_asm_insn (\"add%d6\\t%0, %2, %3\", operands);
4610   if (which_alternative != 0)
4611     {
4612       if (GET_CODE (operands[1]) == MEM)
4613         output_asm_insn (\"ldr%D6\\t%0, %1\", operands);
4614       else
4615         output_asm_insn (\"mov%D6\\t%0, %1\", operands);
4616     }
4617   return \"\";
4620 [(set_attr "conds" "clob")
4621  (set_attr "length" "8,12")])
4623 (define_insn "*ifcompare_move_plus"
4624   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4625         (if_then_else:SI (match_operator 6 "comparison_operator"
4626                           [(match_operand:SI 4 "s_register_operand" "r,r")
4627                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4628                          (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4629                          (plus:SI
4630                           (match_operand:SI 2 "s_register_operand" "r,r")
4631                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4632    (clobber (reg 24))]
4633   ""
4634   "*
4636   if (GET_CODE (operands[5]) == CONST_INT
4637       && !const_ok_for_arm (INTVAL (operands[5])))
4638     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4639   else
4640     output_asm_insn (\"cmp\\t%4, %5\", operands);
4641   if (GET_CODE (operands[3]) == CONST_INT
4642       && !const_ok_for_arm (INTVAL (operands[3])))
4643     output_asm_insn (\"sub%D6\\t%0, %2, #%n3\", operands);
4644   else
4645     output_asm_insn (\"add%D6\\t%0, %2, %3\", operands);
4646   if (which_alternative != 0)
4647     {
4648       if (GET_CODE (operands[6]) == MEM)
4649         output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4650       else
4651         output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4652     }
4653   return \"\";
4656 [(set_attr "conds" "clob")
4657  (set_attr "length" "8,12")])
4659 (define_insn "*ifcompare_move_not"
4660   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4661         (if_then_else:SI (match_operator 5 "comparison_operator"
4662                           [(match_operand:SI 3 "s_register_operand" "r,r")
4663                            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
4664                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4665                          (not:SI
4666                           (match_operand:SI 2 "s_register_operand" "r,r"))))
4667    (clobber (reg 24))]
4668   ""
4669   "#"
4670 [(set_attr "conds" "clob")
4671  (set_attr "length" "8,12")])
4673 (define_insn "*ifcompare_not_move"
4674   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4675         (if_then_else:SI 
4676          (match_operator 5 "comparison_operator"
4677           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4678            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4679          (not:SI
4680           (match_operand:SI 2 "s_register_operand" "r,r,r,r"))
4681          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4682    (clobber (reg 24))]
4683   ""
4684   "@
4685    cmp\\t%3, %4\;mvn%d5\\t%0, %2
4686    cmn\\t%3, #%n4\;mvn%d5\\t%0, %2
4687    cmp\\t%3, %4\;mov%D5\\t%0, %1\;mvn%d5\\t%0, %2
4688    cmn\\t%3, #%n4\;mov%D5\\t%0, %1\;mvn%d5\\t%0, %2"
4689 [(set_attr "conds" "clob")
4690  (set_attr "length" "8,8,12,12")])
4692 (define_insn "*ifcompare_shift_move"
4693   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4694         (if_then_else:SI
4695          (match_operator 6 "comparison_operator"
4696           [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
4697            (match_operand:SI 5 "arm_add_operand" "rI,L,rI,L")])
4698          (match_operator:SI 7 "shift_operator"
4699           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4700            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM,rM")])
4701          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4702    (clobber (reg 24))]
4703   ""
4704   "@
4705    cmp\\t%4, %5\;mov%d6\\t%0, %2%S7
4706    cmn\\t%4, #%n5\;mov%d6\\t%0, %2%S7
4707    cmp\\t%4, %5\;mov%D6\\t%0, %1\;mov%d6\\t%0, %2%S7
4708    cmn\\t%4, #%n5\;mov%D6\\t%0, %1\;mov%d6\\t%0, %2%S7"
4709 [(set_attr "conds" "clob")
4710  (set_attr "length" "8,8,12,12")])
4712 (define_insn "ifcompare_move_shift"
4713   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4714         (if_then_else:SI
4715          (match_operator 6 "comparison_operator"
4716           [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
4717            (match_operand:SI 5 "arm_add_operand" "rI,L,rI,L")])
4718          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4719          (match_operator:SI 7 "shift_operator"
4720           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4721            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM,rM")])))
4722    (clobber (reg 24))]
4723   ""
4724   "@
4725    cmp\\t%4, %5\;mov%D6\\t%0, %2%S7
4726    cmn\\t%4, #%n5\;mov%D6\\t%0, %2%S7
4727    cmp\\t%4, %5\;mov%d6\\t%0, %1\;mov%D6\\t%0, %2%S7
4728    cmn\\t%4, #%n5\;mov%d6\\t%0, %1\;mov%D6\\t%0, %2%S7"
4729 [(set_attr "conds" "clob")
4730  (set_attr "length" "8,8,12,12")])
4732 (define_insn "*ifcompare_shift_shift"
4733   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4734         (if_then_else:SI
4735          (match_operator 7 "comparison_operator"
4736           [(match_operand:SI 5 "s_register_operand" "r,r")
4737            (match_operand:SI 6 "arm_add_operand" "rI,L")])
4738          (match_operator:SI 8 "shift_operator"
4739           [(match_operand:SI 1 "s_register_operand" "r,r")
4740            (match_operand:SI 2 "arm_rhs_operand" "rM,rM")])
4741          (match_operator:SI 9 "shift_operator"
4742           [(match_operand:SI 3 "s_register_operand" "r,r")
4743            (match_operand:SI 4 "arm_rhs_operand" "rI,rI")])))
4744    (clobber (reg 24))]
4745   ""
4746   "@
4747    cmp\\t%5, %6\;mov%d7\\t%0, %1%S8\;mov%D7\\t%0, %3%S9
4748    cmn\\t%5, #%n6\;mov%d7\\t%0, %1%S8\;mov%D7\\t%0, %3%S9"
4749 [(set_attr "conds" "clob")
4750  (set_attr "length" "12")])
4752 (define_insn "*ifcompare_not_arith"
4753   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4754         (if_then_else:SI
4755          (match_operator 6 "comparison_operator"
4756           [(match_operand:SI 4 "s_register_operand" "r,r")
4757            (match_operand:SI 5 "arm_add_operand" "rI,L")])
4758          (not:SI (match_operand:SI 1 "s_register_operand" "r,r"))
4759          (match_operator:SI 7 "shiftable_operator"
4760           [(match_operand:SI 2 "s_register_operand" "r,r")
4761            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4762    (clobber (reg 24))]
4763   ""
4764   "@
4765    cmp\\t%4, %5\;mvn%d6\\t%0, %1\;%I7%D6\\t%0, %2, %3
4766    cmn\\t%4, #%n5\;mvn%d6\\t%0, %1\;%I7%D6\\t%0, %2, %3"
4767 [(set_attr "conds" "clob")
4768  (set_attr "length" "12")])
4770 (define_insn "*if_compare_arith_not"
4771   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4772         (if_then_else:SI
4773          (match_operator 6 "comparison_operator"
4774           [(match_operand:SI 4 "s_register_operand" "r,r")
4775            (match_operand:SI 5 "arm_add_operand" "rI,L")])
4776          (match_operator:SI 7 "shiftable_operator"
4777           [(match_operand:SI 2 "s_register_operand" "r,r")
4778            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4779          (not:SI (match_operand:SI 1 "s_register_operand" "r,r"))))
4780    (clobber (reg 24))]
4781   ""
4782   "@
4783    cmp\\t%4, %5\;mvn%D6\\t%0, %1\;%I7%d6\\t%0, %2, %3
4784    cmn\\t%4, #%n5\;mvn%D6\\t%0, %1\;%I7%d6\\t%0, %2, %3"
4785 [(set_attr "conds" "clob")
4786  (set_attr "length" "12")])
4788 (define_insn "*ifcompare_neg_move"
4789   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4790         (if_then_else:SI
4791          (match_operator 5 "comparison_operator"
4792           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4793            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4794          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r"))
4795          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4796    (clobber (reg:CC 24))]
4797   ""
4798   "@
4799    cmp\\t%3, %4\;rsb%d5\\t%0, %2, #0
4800    cmn\\t%3, #%n4\;rsb%d5\\t%0, %2, #0
4801    cmp\\t%3, %4\;mov%D5\\t%0, %1\;rsb%d5\\t%0, %2, #0
4802    cmn\\t%3, #%n4\;mov%D5\\t%0, %1\;rsb%d5\\t%0, %2, #0"
4803 [(set_attr "conds" "clob")
4804  (set_attr "length" "8,8,12,12")])
4806 (define_insn "*ifcompare_move_neg"
4807   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4808         (if_then_else:SI
4809          (match_operator 5 "comparison_operator"
4810           [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4811            (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4812          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4813          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r"))))
4814    (clobber (reg:CC 24))]
4815   ""
4816   "@
4817    cmp\\t%3, %4\;rsb%D5\\t%0, %2, #0
4818    cmn\\t%3, #%n4\;rsb%D5\\t%0, %2, #0
4819    cmp\\t%3, %4\;mov%d5\\t%0, %1\;rsb%D5\\t%0, %2, #0
4820    cmn\\t%3, #%n4\;mov%d5\\t%0, %1\;rsb%D5\\t%0, %2, #0"
4821 [(set_attr "conds" "clob")
4822  (set_attr "length" "8,8,12,12")])
4824 (define_insn "*arith_adjacentmem"
4825   [(set (match_operand:SI 0 "s_register_operand" "=r")
4826         (match_operator:SI 1 "shiftable_operator"
4827          [(match_operand:SI 2 "memory_operand" "m")
4828           (match_operand:SI 3 "memory_operand" "m")]))
4829    (clobber (match_scratch:SI 4 "=r"))]
4830   "adjacent_mem_locations (operands[2], operands[3])"
4831   "*
4833   rtx ldm[3];
4834   rtx arith[4];
4835   int val1 = 0, val2 = 0;
4837   if (REGNO (operands[0]) > REGNO (operands[4]))
4838     {
4839       ldm[1] = operands[4];
4840       ldm[2] = operands[0];
4841     }
4842   else
4843     {
4844       ldm[1] = operands[0];
4845       ldm[2] = operands[4];
4846     }
4847   if (GET_CODE (XEXP (operands[2], 0)) != REG)
4848     val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
4849   if (GET_CODE (XEXP (operands[3], 0)) != REG)
4850     val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
4851   arith[0] = operands[0];
4852   arith[3] = operands[1];
4853   if (val1 < val2)
4854     {
4855       arith[1] = ldm[1];
4856       arith[2] = ldm[2];
4857     }
4858   else
4859     {
4860       arith[1] = ldm[2];
4861       arith[2] = ldm[1];
4862     }
4863   if (val1 && val2)
4864     {
4865       rtx ops[3];
4866       ldm[0] = ops[0] = operands[4];
4867       ops[1] = XEXP (XEXP (operands[2], 0), 0);
4868       ops[2] = XEXP (XEXP (operands[2], 0), 1);
4869       output_add_immediate (ops);
4870       if (val1 < val2)
4871         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4872       else
4873         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4874     }
4875   else if (val1)
4876     {
4877       ldm[0] = XEXP (operands[3], 0);
4878       if (val1 < val2)
4879         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4880       else
4881         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4882     }
4883   else
4884     {
4885       ldm[0] = XEXP (operands[2], 0);
4886       if (val1 < val2)
4887         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4888       else
4889         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4890     }
4891   output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
4892   return \"\";
4895 [(set_attr "length" "12")
4896  (set_attr "type" "load")])
4898 ;; the arm can support extended pre-inc instructions
4900 ;; In all these cases, we use operands 0 and 1 for the register being
4901 ;; incremented because those are the operands that local-alloc will
4902 ;; tie and these are the pair most likely to be tieable (and the ones
4903 ;; that will benefit the most).
4905 ;; We reject the frame pointer if it occurs anywhere in these patterns since
4906 ;; elimination will cause too many headaches.
4908 (define_insn "*strqi_preinc"
4909   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4910                          (match_operand:SI 2 "index_operand" "rJ")))
4911         (match_operand:QI 3 "s_register_operand" "r"))
4912    (set (match_operand:SI 0 "s_register_operand" "=r")
4913         (plus:SI (match_dup 1) (match_dup 2)))]
4914   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4915    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4916    && (GET_CODE (operands[2]) != REG
4917        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4918   "str%?b\\t%3, [%0, %2]!"
4919 [(set_attr "type" "store1")])
4921 (define_insn "*strqi_predec"
4922   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4923                           (match_operand:SI 2 "s_register_operand" "r")))
4924         (match_operand:QI 3 "s_register_operand" "r"))
4925    (set (match_operand:SI 0 "s_register_operand" "=r")
4926         (minus:SI (match_dup 1) (match_dup 2)))]
4927   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4928    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4929    && (GET_CODE (operands[2]) != REG
4930        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4931   "str%?b\\t%3, [%0, -%2]!"
4932 [(set_attr "type" "store1")])
4934 (define_insn "*loadqi_preinc"
4935   [(set (match_operand:QI 3 "s_register_operand" "=r")
4936         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4937                          (match_operand:SI 2 "index_operand" "rJ"))))
4938    (set (match_operand:SI 0 "s_register_operand" "=r")
4939         (plus:SI (match_dup 1) (match_dup 2)))]
4940   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4941    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4942    && (GET_CODE (operands[2]) != REG
4943        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4944   "ldr%?b\\t%3, [%0, %2]!"
4945 [(set_attr "type" "load")])
4947 (define_insn "*loadqi_predec"
4948   [(set (match_operand:QI 3 "s_register_operand" "=r")
4949         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4950                           (match_operand:SI 2 "s_register_operand" "r"))))
4951    (set (match_operand:SI 0 "s_register_operand" "=r")
4952         (minus:SI (match_dup 1) (match_dup 2)))]
4953   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4954    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4955    && (GET_CODE (operands[2]) != REG
4956        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4957   "ldr%?b\\t%3, [%0, -%2]!"
4958 [(set_attr "type" "load")])
4960 (define_insn "*loadqisi_preinc"
4961   [(set (match_operand:SI 3 "s_register_operand" "=r")
4962         (zero_extend:SI
4963          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4964                           (match_operand:SI 2 "index_operand" "rJ")))))
4965    (set (match_operand:SI 0 "s_register_operand" "=r")
4966         (plus:SI (match_dup 1) (match_dup 2)))]
4967   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4968    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4969    && (GET_CODE (operands[2]) != REG
4970        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4971   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
4972 [(set_attr "type" "load")])
4974 (define_insn "*loadqisi_predec"
4975   [(set (match_operand:SI 3 "s_register_operand" "=r")
4976         (zero_extend:SI
4977          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4978                            (match_operand:SI 2 "s_register_operand" "r")))))
4979    (set (match_operand:SI 0 "s_register_operand" "=r")
4980         (minus:SI (match_dup 1) (match_dup 2)))]
4981   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4982    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4983    && (GET_CODE (operands[2]) != REG
4984        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4985   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
4986 [(set_attr "type" "load")])
4988 (define_insn "*strsi_preinc"
4989   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4990                          (match_operand:SI 2 "index_operand" "rJ")))
4991         (match_operand:SI 3 "s_register_operand" "r"))
4992    (set (match_operand:SI 0 "s_register_operand" "=r")
4993         (plus:SI (match_dup 1) (match_dup 2)))]
4994   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4995    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4996    && (GET_CODE (operands[2]) != REG
4997        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4998   "str%?\\t%3, [%0, %2]!"
4999 [(set_attr "type" "store1")])
5001 (define_insn "*strqi_predec"
5002   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5003                           (match_operand:SI 2 "s_register_operand" "r")))
5004         (match_operand:SI 3 "s_register_operand" "r"))
5005    (set (match_operand:SI 0 "s_register_operand" "=r")
5006         (minus:SI (match_dup 1) (match_dup 2)))]
5007   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5008    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5009    && (GET_CODE (operands[2]) != REG
5010        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5011   "str%?\\t%3, [%0, -%2]!"
5012 [(set_attr "type" "store1")])
5014 (define_insn "*loadsi_preinc"
5015   [(set (match_operand:SI 3 "s_register_operand" "=r")
5016         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5017                          (match_operand:SI 2 "index_operand" "rJ"))))
5018    (set (match_operand:SI 0 "s_register_operand" "=r")
5019         (plus:SI (match_dup 1) (match_dup 2)))]
5020   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5021    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5022    && (GET_CODE (operands[2]) != REG
5023        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5024   "ldr%?\\t%3, [%0, %2]!"
5025 [(set_attr "type" "load")])
5027 (define_insn "*loadsi_predec"
5028   [(set (match_operand:SI 3 "s_register_operand" "=r")
5029         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5030                           (match_operand:SI 2 "s_register_operand" "r"))))
5031    (set (match_operand:SI 0 "s_register_operand" "=r")
5032         (minus:SI (match_dup 1) (match_dup 2)))]
5033   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5034    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5035    && (GET_CODE (operands[2]) != REG
5036        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5037   "ldr%?\\t%3, [%0, -%2]!"
5038 [(set_attr "type" "load")])
5040 (define_insn "*loadhi_preinc"
5041   [(set (match_operand:HI 3 "s_register_operand" "=r")
5042         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5043                          (match_operand:SI 2 "index_operand" "rJ"))))
5044    (set (match_operand:SI 0 "s_register_operand" "=r")
5045         (plus:SI (match_dup 1) (match_dup 2)))]
5046   "(! BYTES_BIG_ENDIAN)
5047    && ! TARGET_SHORT_BY_BYTES
5048    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5049    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5050    && (GET_CODE (operands[2]) != REG
5051        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5052   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5053 [(set_attr "type" "load")])
5055 (define_insn "*loadhi_predec"
5056   [(set (match_operand:HI 3 "s_register_operand" "=r")
5057         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5058                           (match_operand:SI 2 "s_register_operand" "r"))))
5059    (set (match_operand:SI 0 "s_register_operand" "=r")
5060         (minus:SI (match_dup 1) (match_dup 2)))]
5061   "(!BYTES_BIG_ENDIAN)
5062    && ! TARGET_SHORT_BY_BYTES
5063    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5064    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5065    && (GET_CODE (operands[2]) != REG
5066        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5067   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5068 [(set_attr "type" "load")])
5070 (define_insn "*strqi_shiftpreinc"
5071   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5072                           [(match_operand:SI 3 "s_register_operand" "r")
5073                            (match_operand:SI 4 "const_shift_operand" "n")])
5074                          (match_operand:SI 1 "s_register_operand" "0")))
5075         (match_operand:QI 5 "s_register_operand" "r"))
5076    (set (match_operand:SI 0 "s_register_operand" "=r")
5077         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5078                  (match_dup 1)))]
5079   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5080    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5081    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5082   "str%?b\\t%5, [%0, %3%S2]!"
5083 [(set_attr "type" "store1")])
5085 (define_insn "*strqi_shiftpredec"
5086   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5087                           (match_operator:SI 2 "shift_operator"
5088                            [(match_operand:SI 3 "s_register_operand" "r")
5089                             (match_operand:SI 4 "const_shift_operand" "n")])))
5090         (match_operand:QI 5 "s_register_operand" "r"))
5091    (set (match_operand:SI 0 "s_register_operand" "=r")
5092         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5093                                                  (match_dup 4)])))]
5094   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5095    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5096    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5097   "str%?b\\t%5, [%0, -%3%S2]!"
5098 [(set_attr "type" "store1")])
5100 (define_insn "*loadqi_shiftpreinc"
5101   [(set (match_operand:QI 5 "s_register_operand" "=r")
5102         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5103                           [(match_operand:SI 3 "s_register_operand" "r")
5104                            (match_operand:SI 4 "const_shift_operand" "n")])
5105                          (match_operand:SI 1 "s_register_operand" "0"))))
5106    (set (match_operand:SI 0 "s_register_operand" "=r")
5107         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5108                  (match_dup 1)))]
5109   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5110    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5111    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5112   "ldr%?b\\t%5, [%0, %3%S2]!"
5113 [(set_attr "type" "load")])
5115 (define_insn "*loadqi_shiftpredec"
5116   [(set (match_operand:QI 5 "s_register_operand" "=r")
5117         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5118                           (match_operator:SI 2 "shift_operator"
5119                            [(match_operand:SI 3 "s_register_operand" "r")
5120                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5121    (set (match_operand:SI 0 "s_register_operand" "=r")
5122         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5123                                                  (match_dup 4)])))]
5124   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5125    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5126    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5127   "ldr%?b\\t%5, [%0, -%3%S2]!"
5128 [(set_attr "type" "load")])
5130 (define_insn "*strsi_shiftpreinc"
5131   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5132                           [(match_operand:SI 3 "s_register_operand" "r")
5133                            (match_operand:SI 4 "const_shift_operand" "n")])
5134                          (match_operand:SI 1 "s_register_operand" "0")))
5135         (match_operand:SI 5 "s_register_operand" "r"))
5136    (set (match_operand:SI 0 "s_register_operand" "=r")
5137         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5138                  (match_dup 1)))]
5139   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5140    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5141    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5142   "str%?\\t%5, [%0, %3%S2]!"
5143 [(set_attr "type" "store1")])
5145 (define_insn "*strsi_shiftpredec"
5146   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5147                           (match_operator:SI 2 "shift_operator"
5148                            [(match_operand:SI 3 "s_register_operand" "r")
5149                             (match_operand:SI 4 "const_shift_operand" "n")])))
5150         (match_operand:SI 5 "s_register_operand" "r"))
5151    (set (match_operand:SI 0 "s_register_operand" "=r")
5152         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5153                                                  (match_dup 4)])))]
5154   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5155    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5156    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5157   "str%?\\t%5, [%0, -%3%S2]!"
5158 [(set_attr "type" "store1")])
5160 (define_insn "*loadqi_shiftpreinc"
5161   [(set (match_operand:SI 5 "s_register_operand" "=r")
5162         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5163                           [(match_operand:SI 3 "s_register_operand" "r")
5164                            (match_operand:SI 4 "const_shift_operand" "n")])
5165                          (match_operand:SI 1 "s_register_operand" "0"))))
5166    (set (match_operand:SI 0 "s_register_operand" "=r")
5167         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5168                  (match_dup 1)))]
5169   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5170    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5171    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5172   "ldr%?\\t%5, [%0, %3%S2]!"
5173 [(set_attr "type" "load")])
5175 (define_insn "*loadqi_shiftpredec"
5176   [(set (match_operand:SI 5 "s_register_operand" "=r")
5177         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5178                           (match_operator:SI 2 "shift_operator"
5179                            [(match_operand:SI 3 "s_register_operand" "r")
5180                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5181    (set (match_operand:SI 0 "s_register_operand" "=r")
5182         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5183                                                  (match_dup 4)])))]
5184   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5185    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5186    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5187   "ldr%?\\t%5, [%0, -%3%S2]!"
5188 [(set_attr "type" "load")])
5190 (define_insn "*loadhi_shiftpreinc"
5191   [(set (match_operand:HI 5 "s_register_operand" "=r")
5192         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5193                           [(match_operand:SI 3 "s_register_operand" "r")
5194                            (match_operand:SI 4 "const_shift_operand" "n")])
5195                          (match_operand:SI 1 "s_register_operand" "0"))))
5196    (set (match_operand:SI 0 "s_register_operand" "=r")
5197         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5198                  (match_dup 1)))]
5199   "(! BYTES_BIG_ENDIAN)
5200    && ! TARGET_SHORT_BY_BYTES
5201    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5202    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5203    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5204   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5205 [(set_attr "type" "load")])
5207 (define_insn "*loadhi_shiftpredec"
5208   [(set (match_operand:HI 5 "s_register_operand" "=r")
5209         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5210                           (match_operator:SI 2 "shift_operator"
5211                            [(match_operand:SI 3 "s_register_operand" "r")
5212                             (match_operand:SI 4 "const_shift_operand" "n")]))))
5213    (set (match_operand:SI 0 "s_register_operand" "=r")
5214         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5215                                                  (match_dup 4)])))]
5216   "(! BYTES_BIG_ENDIAN)
5217    && ! TARGET_SHORT_BY_BYTES
5218    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5219    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5220    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5221   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5222 [(set_attr "type" "load")])
5224 ; It can also support extended post-inc expressions, but combine doesn't
5225 ; try these....
5226 ; It doesn't seem worth adding peepholes for anything but the most common
5227 ; cases since, unlike combine, the increment must immediately follow the load
5228 ; for this pattern to match.
5229 ; When loading we must watch to see that the base register isn't trampled by
5230 ; the load.  In such cases this isn't a post-inc expression.
5232 (define_peephole
5233   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5234         (match_operand:QI 2 "s_register_operand" "r"))
5235    (set (match_dup 0)
5236         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5237   ""
5238   "str%?b\\t%2, [%0], %1")
5240 (define_peephole
5241   [(set (match_operand:QI 0 "s_register_operand" "=r")
5242         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5243    (set (match_dup 1)
5244         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5245   "REGNO(operands[0]) != REGNO(operands[1])
5246    && (GET_CODE (operands[2]) != REG
5247        || REGNO(operands[0]) != REGNO (operands[2]))"
5248   "ldr%?b\\t%0, [%1], %2")
5250 (define_peephole
5251   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5252         (match_operand:SI 2 "s_register_operand" "r"))
5253    (set (match_dup 0)
5254         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5255   ""
5256   "str%?\\t%2, [%0], %1")
5258 (define_peephole
5259   [(set (match_operand:HI 0 "s_register_operand" "=r")
5260         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5261    (set (match_dup 1)
5262         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5263   "(! BYTES_BIG_ENDIAN)
5264    && ! TARGET_SHORT_BY_BYTES
5265    && REGNO(operands[0]) != REGNO(operands[1])
5266    && (GET_CODE (operands[2]) != REG
5267        || REGNO(operands[0]) != REGNO (operands[2]))"
5268   "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5270 (define_peephole
5271   [(set (match_operand:SI 0 "s_register_operand" "=r")
5272         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5273    (set (match_dup 1)
5274         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5275   "REGNO(operands[0]) != REGNO(operands[1])
5276    && (GET_CODE (operands[2]) != REG
5277        || REGNO(operands[0]) != REGNO (operands[2]))"
5278   "ldr%?\\t%0, [%1], %2")
5280 (define_peephole
5281   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5282                          (match_operand:SI 1 "index_operand" "rJ")))
5283         (match_operand:QI 2 "s_register_operand" "r"))
5284    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5285   ""
5286   "str%?b\\t%2, [%0, %1]!")
5288 (define_peephole
5289   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5290                           [(match_operand:SI 0 "s_register_operand" "r")
5291                            (match_operand:SI 1 "const_int_operand" "n")])
5292                          (match_operand:SI 2 "s_register_operand" "+r")))
5293         (match_operand:QI 3 "s_register_operand" "r"))
5294    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5295                                (match_dup 2)))]
5296   ""
5297   "str%?b\\t%3, [%2, %0%S4]!")
5299 ; This pattern is never tried by combine, so do it as a peephole
5301 (define_peephole
5302   [(set (match_operand:SI 0 "s_register_operand" "=r")
5303         (match_operand:SI 1 "s_register_operand" "r"))
5304    (set (reg:CC 24)
5305         (compare:CC (match_dup 1) (const_int 0)))]
5306   ""
5307   "sub%?s\\t%0, %1, #0"
5308 [(set_attr "conds" "set")])
5310 ; Peepholes to spot possible load- and store-multiples, if the ordering is
5311 ; reversed, check that the memory references aren't volatile.
5313 (define_peephole
5314   [(set (match_operand:SI 0 "s_register_operand" "=r")
5315         (match_operand:SI 4 "memory_operand" "m"))
5316    (set (match_operand:SI 1 "s_register_operand" "=r")
5317         (match_operand:SI 5 "memory_operand" "m"))
5318    (set (match_operand:SI 2 "s_register_operand" "=r")
5319         (match_operand:SI 6 "memory_operand" "m"))
5320    (set (match_operand:SI 3 "s_register_operand" "=r")
5321         (match_operand:SI 7 "memory_operand" "m"))]
5322   "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5323   "*
5324   return emit_ldm_seq (operands, 4);
5327 (define_peephole
5328   [(set (match_operand:SI 0 "s_register_operand" "=r")
5329         (match_operand:SI 3 "memory_operand" "m"))
5330    (set (match_operand:SI 1 "s_register_operand" "=r")
5331         (match_operand:SI 4 "memory_operand" "m"))
5332    (set (match_operand:SI 2 "s_register_operand" "=r")
5333         (match_operand:SI 5 "memory_operand" "m"))]
5334   "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5335   "*
5336   return emit_ldm_seq (operands, 3);
5339 (define_peephole
5340   [(set (match_operand:SI 0 "s_register_operand" "=r")
5341         (match_operand:SI 2 "memory_operand" "m"))
5342    (set (match_operand:SI 1 "s_register_operand" "=r")
5343         (match_operand:SI 3 "memory_operand" "m"))]
5344   "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5345   "*
5346   return emit_ldm_seq (operands, 2);
5349 (define_peephole
5350   [(set (match_operand:SI 4 "memory_operand" "=m")
5351         (match_operand:SI 0 "s_register_operand" "r"))
5352    (set (match_operand:SI 5 "memory_operand" "=m")
5353         (match_operand:SI 1 "s_register_operand" "r"))
5354    (set (match_operand:SI 6 "memory_operand" "=m")
5355         (match_operand:SI 2 "s_register_operand" "r"))
5356    (set (match_operand:SI 7 "memory_operand" "=m")
5357         (match_operand:SI 3 "s_register_operand" "r"))]
5358   "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5359   "*
5360   return emit_stm_seq (operands, 4);
5363 (define_peephole
5364   [(set (match_operand:SI 3 "memory_operand" "=m")
5365         (match_operand:SI 0 "s_register_operand" "r"))
5366    (set (match_operand:SI 4 "memory_operand" "=m")
5367         (match_operand:SI 1 "s_register_operand" "r"))
5368    (set (match_operand:SI 5 "memory_operand" "=m")
5369         (match_operand:SI 2 "s_register_operand" "r"))]
5370   "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5371   "*
5372   return emit_stm_seq (operands, 3);
5375 (define_peephole
5376   [(set (match_operand:SI 2 "memory_operand" "=m")
5377         (match_operand:SI 0 "s_register_operand" "r"))
5378    (set (match_operand:SI 3 "memory_operand" "=m")
5379         (match_operand:SI 1 "s_register_operand" "r"))]
5380   "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5381   "*
5382   return emit_stm_seq (operands, 2);
5385 ;; A call followed by return can be replaced by restoring the regs and
5386 ;; jumping to the subroutine, provided we aren't passing the address of
5387 ;; any of our local variables.  If we call alloca then this is unsafe
5388 ;; since restoring the frame frees the memory, which is not what we want.
5389 ;; Sometimes the return might have been targeted by the final prescan:
5390 ;; if so then emit a proper return insn as well.
5391 ;; Unfortunately, if the frame pointer is required, we don't know if the
5392 ;; current function has any implicit stack pointer adjustments that will 
5393 ;; be restored by the return: we can't therefore do a tail call.
5394 ;; Another unfortunate that we can't handle is if current_function_args_size
5395 ;; is non-zero: in this case elimination of the argument pointer assumed
5396 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5397 ;; calculations.
5399 (define_peephole
5400   [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5401                           (match_operand:SI 1 "general_operand" "g"))
5402                     (clobber (reg:SI 14))])
5403    (return)]
5404   "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN
5405     && !get_frame_size () && !current_function_calls_alloca
5406     && !frame_pointer_needed && !current_function_args_size)"
5407   "*
5409   extern rtx arm_target_insn;
5410   extern int arm_ccfsm_state;
5412   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5413   {
5414     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5415     output_return_instruction (NULL, TRUE, FALSE);
5416     arm_ccfsm_state = 0;
5417     arm_target_insn = NULL;
5418   }
5420   output_return_instruction (NULL, FALSE, FALSE);
5421   return \"b%?\\t%a0\";
5423 [(set_attr "type" "call")
5424  (set_attr "length" "8")])
5426 (define_peephole
5427   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5428                    (call (mem:SI (match_operand:SI 1 "" "X"))
5429                          (match_operand:SI 2 "general_operand" "g")))
5430               (clobber (reg:SI 14))])
5431    (return)]
5432   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5433     && !get_frame_size () && !current_function_calls_alloca
5434     && !frame_pointer_needed && !current_function_args_size)"
5435   "*
5437   extern rtx arm_target_insn;
5438   extern int arm_ccfsm_state;
5440   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5441   {
5442     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5443     output_return_instruction (NULL, TRUE, FALSE);
5444     arm_ccfsm_state = 0;
5445     arm_target_insn = NULL;
5446   }
5448   output_return_instruction (NULL, FALSE, FALSE);
5449   return \"b%?\\t%a1\";
5451 [(set_attr "type" "call")
5452  (set_attr "length" "8")])
5454 ;; As above but when this function is not void, we must be returning the
5455 ;; result of the called subroutine.
5457 (define_peephole
5458   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5459                    (call (mem:SI (match_operand:SI 1 "" "X"))
5460                          (match_operand:SI 2 "general_operand" "g")))
5461               (clobber (reg:SI 14))])
5462    (use (match_dup 0))
5463    (return)]
5464   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5465     && !get_frame_size () && !current_function_calls_alloca
5466     && !frame_pointer_needed && !current_function_args_size)"
5467   "*
5469   extern rtx arm_target_insn;
5470   extern int arm_ccfsm_state;
5472   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5473   {
5474     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5475     output_return_instruction (NULL, TRUE, FALSE);
5476     arm_ccfsm_state = 0;
5477     arm_target_insn = NULL;
5478   }
5480   output_return_instruction (NULL, FALSE, FALSE);
5481   return \"b%?\\t%a1\";
5483 [(set_attr "type" "call")
5484  (set_attr "length" "8")])
5486 ;; If calling a subroutine and then jumping back to somewhere else, but not
5487 ;; too far away, then we can set the link register with the branch address
5488 ;; and jump direct to the subroutine.  On return from the subroutine
5489 ;; execution continues at the branch; this avoids a prefetch stall.
5490 ;; We use the length attribute (via short_branch ()) to establish whether or
5491 ;; not this is possible, this is the same as the sparc does.
5493 (define_peephole
5494   [(parallel[(call (mem:SI (match_operand:SI 0 "" "X"))
5495                    (match_operand:SI 1 "general_operand" "g"))
5496              (clobber (reg:SI 14))])
5497    (set (pc)
5498         (label_ref (match_operand 2 "" "")))]
5499   "0 && GET_CODE (operands[0]) == SYMBOL_REF 
5500    && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
5501    && arm_insn_not_targeted (insn)"
5502   "*
5504   int backward = arm_backwards_branch (INSN_UID (insn),
5505                                        INSN_UID (operands[2]));
5507 #if 0
5508   /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
5509    * above, leaving it out means that the code will still run on an arm 2 or 3
5510    */
5511   if (TARGET_6)
5512     {
5513       if (backward)
5514         output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l2)\", operands);
5515       else
5516         output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l2 - . -8)\", operands);
5517     }
5518   else
5519 #endif
5520     {
5521       output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands);
5522       if (backward)
5523         output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l2)\", operands);
5524       else
5525         output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l2 - . -4)\", operands);
5526     }
5527   return \"b%?\\t%a0\";
5529 [(set_attr "type" "call")
5530  (set (attr "length")
5531       (if_then_else (eq_attr "prog_mode" "prog32")
5532                     (const_int 8)
5533                     (const_int 12)))])
5535 (define_peephole
5536   [(parallel[(set (match_operand:SI 0 "s_register_operand" "=r")
5537                   (call (mem:SI (match_operand:SI 1 "" "X"))
5538                         (match_operand:SI 2 "general_operand" "g")))
5539              (clobber (reg:SI 14))])
5540    (set (pc)
5541         (label_ref (match_operand 3 "" "")))]
5542   "0 && GET_CODE (operands[0]) == SYMBOL_REF
5543    && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
5544    && arm_insn_not_targeted (insn)"
5545   "*
5547   int backward = arm_backwards_branch (INSN_UID (insn),
5548                                        INSN_UID (operands[3]));
5550 #if 0
5551   /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
5552    * above, leaving it out means that the code will still run on an arm 2 or 3
5553    */
5554   if (TARGET_6)
5555     {
5556       if (backward)
5557         output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l3)\", operands);
5558       else
5559         output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l3 - . -8)\", operands);
5560     }
5561   else
5562 #endif
5563     {
5564       output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands);
5565       if (backward)
5566         output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l3)\", operands);
5567       else
5568         output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l3 - . -4)\", operands);
5569     }
5570   return \"b%?\\t%a1\";
5572 [(set_attr "type" "call")
5573  (set (attr "length")
5574       (if_then_else (eq_attr "prog_mode" "prog32")
5575                     (const_int 8)
5576                     (const_int 12)))])
5578 (define_split
5579   [(set (match_operand:SI 0 "s_register_operand" "")
5580         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
5581                        (const_int 0))
5582                 (neg:SI (match_operator:SI 2 "comparison_operator"
5583                          [(match_operand:SI 3 "s_register_operand" "")
5584                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
5585    (clobber (match_operand:SI 5 "s_register_operand" ""))]
5586   ""
5587   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
5588    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5589                               (match_dup 5)))]
5590   "")
5592 ;; This split can be used because CC_Z mode implies that the following
5593 ;; branch will be an equality, or an unsigned inequality, so the sign
5594 ;; extension is not needed.
5596 (define_split
5597   [(set (reg:CC_Z 24)
5598         (compare:CC_Z
5599          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
5600                     (const_int 24))
5601          (match_operand 1 "const_int_operand" "")))
5602    (clobber (match_scratch:SI 2 ""))]
5603   "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
5604    == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
5605   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
5606    (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
5607   "
5608   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
5611 (define_expand "prologue"
5612   [(clobber (const_int 0))]
5613   ""
5614   "
5615   arm_expand_prologue ();
5616   DONE;
5619 ;; This split is only used during output to reduce the number of patterns
5620 ;; that need assembler instructions adding to them.  We allowed the setting
5621 ;; of the conditions to be implicit during rtl generation so that
5622 ;; the conditional compare patterns would work.  However this conflicts to
5623 ;; some extend with the conditional data operations, so we have to split them
5624 ;; up again here.
5626 (define_split
5627   [(set (match_operand:SI 0 "s_register_operand" "")
5628         (if_then_else:SI (match_operator 1 "comparison_operator"
5629                           [(match_operand 2 "" "") (match_operand 3 "" "")])
5630                          (match_operand 4 "" "")
5631                          (match_operand 5 "" "")))
5632    (clobber (reg 24))]
5633   "reload_completed"
5634   [(set (match_dup 6) (match_dup 7))
5635    (set (match_dup 0) 
5636         (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
5637                          (match_dup 4)
5638                          (match_dup 5)))]
5639   "
5641   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
5642                                            operands[3]);
5644   operands[6] = gen_rtx (REG, mode, 24);
5645   operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
5650 (define_insn "*cond_move_not"
5651   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5652         (if_then_else:SI (match_operator 4 "comparison_operator"
5653                           [(match_operand 3 "cc_register" "") (const_int 0)])
5654                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5655                          (not:SI
5656                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
5657   ""
5658   "@
5659    mvn%D4\\t%0, %2
5660    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
5661 [(set_attr "conds" "use")
5662  (set_attr "length" "4,8")])
5664 ;; The next two patterns occur when an AND operation is followed by a
5665 ;; scc insn sequence 
5667 (define_insn "*sign_extract_onebit"
5668   [(set (match_operand:SI 0 "s_register_operand" "=r")
5669         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5670                          (const_int 1)
5671                          (match_operand:SI 2 "const_int_operand" "n")))]
5672   ""
5673   "*
5674   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5675   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
5676   return \"mvnne\\t%0, #0\";
5678 [(set_attr "conds" "clob")
5679  (set_attr "length" "8")])
5681 (define_insn "*not_signextract_onebit"
5682   [(set (match_operand:SI 0 "s_register_operand" "=r")
5683         (not:SI
5684          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5685                           (const_int 1)
5686                           (match_operand:SI 2 "const_int_operand" "n"))))]
5687   ""
5688   "*
5689   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5690   output_asm_insn (\"tst\\t%1, %2\", operands);
5691   output_asm_insn (\"mvneq\\t%0, #0\", operands);
5692   return \"movne\\t%0, #0\";
5694 [(set_attr "conds" "clob")
5695  (set_attr "length" "12")])
5697 ;; Push multiple registers to the stack.  The first register is in the
5698 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
5699 ;; expressions.
5700 (define_insn "*push_multi"
5701   [(match_parallel 2 "multi_register_push"
5702     [(set (match_operand:BLK 0 "memory_operand" "=m")
5703           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
5704   ""
5705   "*
5707   char pattern[100];
5708   int i;
5709   extern int lr_save_eliminated;
5711   if (lr_save_eliminated)
5712     {
5713       if (XVECLEN (operands[2], 0) > 1)
5714         abort ();
5715       return \"\";
5716     }
5717   strcpy (pattern, \"stmfd\\t%m0!, {%1\");
5718   for (i = 1; i < XVECLEN (operands[2], 0); i++)
5719     {
5720       strcat (pattern, \", %|\");
5721       strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
5722                                               0))]);
5723     }
5724   strcat (pattern, \"}\");
5725   output_asm_insn (pattern, operands);
5726   return \"\";
5728 [(set_attr "type" "store4")])
5730 ;; Special patterns for dealing with the constant pool
5732 (define_insn "consttable_4"
5733   [(unspec_volatile [(match_operand 0 "" "")] 2)]
5734   ""
5735   "*
5737   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
5738     {
5739     case MODE_FLOAT:
5740     {
5741       union real_extract u;
5742       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
5743       assemble_real (u.d, GET_MODE (operands[0]));
5744       break;
5745     }
5746     default:
5747       assemble_integer (operands[0], 4, 1);
5748       break;
5749     }
5750   return \"\";
5752 [(set_attr "length" "4")])
5754 (define_insn "consttable_8"
5755   [(unspec_volatile [(match_operand 0 "" "")] 3)]
5756   ""
5757   "*
5759   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
5760     {
5761     case MODE_FLOAT:
5762     {
5763       union real_extract u;
5764       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
5765       assemble_real (u.d, GET_MODE (operands[0]));
5766       break;
5767     }
5768     default:
5769       assemble_integer (operands[0], 8, 1);
5770       break;
5771     }
5772   return \"\";
5774 [(set_attr "length" "8")])
5776 (define_insn "consttable_end"
5777   [(unspec_volatile [(const_int 0)] 4)]
5778   ""
5779   "*
5780   /* Nothing to do (currently).  */
5781   return \"\";
5784 (define_insn "align_4"
5785   [(unspec_volatile [(const_int 0)] 5)]
5786   ""
5787   "*
5788   assemble_align (32);
5789   return \"\";