OSDN Git Service

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