OSDN Git Service

* arm.md (mulhisi3, mulhisi3addsi, mulhidi3adddi): Enable for any
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
7
8 ;; This file is part of GCC.
9
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
14
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33   [(IP_REGNUM       12)         ; Scratch register
34    (SP_REGNUM       13)         ; Stack pointer
35    (LR_REGNUM       14)         ; Return address register
36    (PC_REGNUM       15)         ; Program counter
37    (CC_REGNUM       24)         ; Condition code pseudo register
38    (LAST_ARM_REGNUM 15)
39   ]
40 )
41
42 ;; UNSPEC Usage:
43 ;; Note: sin and cos are no-longer used.
44
45 (define_constants
46   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
47                         ;   operand 0 is the result,
48                         ;   operand 1 the parameter.
49    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
50                         ;   operand 0 is the result,
51                         ;   operand 1 the parameter.
52    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
53                         ;   operand 0 is the first register,
54                         ;   subsequent registers are in parallel (use ...)
55                         ;   expressions.
56    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
57                         ;   usage, that is, we will add the pic_register
58                         ;   value to it before trying to dereference it.
59    (UNSPEC_PRLG_STK  4) ; A special barrier that prevents frame accesses 
60                         ;   being scheduled before the stack adjustment insn.
61    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
62                         ; this unspec is used to prevent the deletion of
63                         ; instructions setting registers for EH handling
64                         ; and stack frame generation.  Operand 0 is the
65                         ; register to "use".
66    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
67   ]
68 )
69
70 ;; UNSPEC_VOLATILE Usage:
71
72 (define_constants
73   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
74                         ;   insn in the code.
75    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
76                         ;   instruction epilogue sequence that isn't expanded
77                         ;   into normal RTL.  Used for both normal and sibcall
78                         ;   epilogues.
79    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
80                         ;   for inlined constants.
81    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
82                         ;   table.
83    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
84                         ;   an 8-bit object.
85    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
86                         ;   a 16-bit object.
87    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
88                         ;   a 32-bit object.
89    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
90                         ;   a 64-bit object.
91   ]
92 )
93 \f
94 ;;---------------------------------------------------------------------------
95 ;; Attributes
96
97 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
98 ; generating ARM code.  This is used to control the length of some insn
99 ; patterns that share the same RTL in both ARM and Thumb code.
100 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
101
102 ; PROG_MODE attribute is used to determine whether condition codes are
103 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
104 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
105 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
106
107 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
108 ; scheduling decisions for the load unit and the multiplier.
109 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
110
111 ;; Operand number of an input operand that is shifted.  Zero if the
112 ;; given instruction does not shift one of its input operands.
113 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
114 (define_attr "shift" "" (const_int 0))
115
116 ; Floating Point Unit.  If we only have floating point emulation, then there
117 ; is no point in scheduling the floating point insns.  (Well, for best
118 ; performance we should try and group them together).
119 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
120
121 ; LENGTH of an instruction (in bytes)
122 (define_attr "length" "" (const_int 4))
123
124 ; POOL_RANGE is how far away from a constant pool entry that this insn
125 ; can be placed.  If the distance is zero, then this insn will never
126 ; reference the pool.
127 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
128 ; before its address.
129 (define_attr "pool_range" "" (const_int 0))
130 (define_attr "neg_pool_range" "" (const_int 0))
131
132 ; An assembler sequence may clobber the condition codes without us knowing.
133 ; If such an insn references the pool, then we have no way of knowing how,
134 ; so use the most conservative value for pool_range.
135 (define_asm_attributes
136  [(set_attr "conds" "clob")
137   (set_attr "length" "4")
138   (set_attr "pool_range" "250")])
139
140 ; TYPE attribute is used to detect floating point instructions which, if
141 ; running on a co-processor can run in parallel with other, basic instructions
142 ; If write-buffer scheduling is enabled then it can also be used in the
143 ; scheduling of writes.
144
145 ; Classification of each insn
146 ; normal        any data instruction that doesn't hit memory or fp regs
147 ; mult          a multiply instruction
148 ; block         blockage insn, this blocks all functional units
149 ; float         a floating point arithmetic operation (subject to expansion)
150 ; fdivd         DFmode floating point division
151 ; fdivs         SFmode floating point division
152 ; fmul          Floating point multiply
153 ; ffmul         Fast floating point multiply
154 ; farith        Floating point arithmetic (4 cycle)
155 ; ffarith       Fast floating point arithmetic (2 cycle)
156 ; float_em      a floating point arithmetic operation that is normally emulated
157 ;               even on a machine with an fpa.
158 ; f_load        a floating point load from memory
159 ; f_store       a floating point store to memory
160 ; f_mem_r       a transfer of a floating point register to a real reg via mem
161 ; r_mem_f       the reverse of f_mem_r
162 ; f_2_r         fast transfer float to arm (no memory needed)
163 ; r_2_f         fast transfer arm to float
164 ; call          a subroutine call
165 ; load          any load from memory
166 ; store1        store 1 word to memory from arm registers
167 ; store2        store 2 words
168 ; store3        store 3 words
169 ; store4        store 4 words
170 ;  Additions for Cirrus Maverick co-processor:
171 ; mav_farith    Floating point arithmetic (4 cycle)
172 ; mav_dmult     Double multiplies (7 cycle)
173 ;
174 (define_attr "type"
175         "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,mav_farith,mav_dmult" 
176         (const_string "normal"))
177
178 ; Load scheduling, set from the arm_ld_sched variable
179 ; initialized by arm_override_options() 
180 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
181
182 ; condition codes: this one is used by final_prescan_insn to speed up
183 ; conditionalizing instructions.  It saves having to scan the rtl to see if
184 ; it uses or alters the condition codes.
185
186 ; USE means that the condition codes are used by the insn in the process of
187 ;   outputting code, this means (at present) that we can't use the insn in
188 ;   inlined branches
189 ;
190 ; SET means that the purpose of the insn is to set the condition codes in a
191 ;   well defined manner.
192 ;
193 ; CLOB means that the condition codes are altered in an undefined manner, if
194 ;   they are altered at all
195 ;
196 ; JUMP_CLOB is used when the condition cannot be represented by a single
197 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
198 ;
199 ; NOCOND means that the condition codes are neither altered nor affect the
200 ;   output of this insn
201
202 (define_attr "conds" "use,set,clob,jump_clob,nocond"
203         (if_then_else (eq_attr "type" "call")
204          (if_then_else (eq_attr "prog_mode" "prog32")
205           (const_string "clob") (const_string "nocond"))
206          (const_string "nocond")))
207
208 ; Predicable means that the insn can be conditionally executed based on
209 ; an automatically added predicate (additional patterns are generated by 
210 ; gen...).  We default to 'no' because no Thumb patterns match this rule
211 ; and not all ARM patterns do.
212 (define_attr "predicable" "no,yes" (const_string "no"))
213
214 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
215 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
216 ; suffer blockages enough to warrent modelling this (and it can adversely
217 ; affect the schedule).
218 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
219
220 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
221 ; to stall the processor.  Used with model_wbuf above.
222 (define_attr "write_conflict" "no,yes"
223   (if_then_else (eq_attr "type"
224                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
225                 (const_string "yes")
226                 (const_string "no")))
227
228 ; Classify the insns into those that take one cycle and those that take more
229 ; than one on the main cpu execution unit.
230 (define_attr "core_cycles" "single,multi"
231   (if_then_else (eq_attr "type"
232                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
233                 (const_string "single")
234                 (const_string "multi")))
235
236 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
237 ;; distant label.  Only applicable to Thumb code.
238 (define_attr "far_jump" "yes,no" (const_string "no"))
239
240 ;; (define_function_unit {name} {num-units} {n-users} {test}
241 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
242
243 ;;--------------------------------------------------------------------
244 ;; Floating point unit (FPA)
245 ;;--------------------------------------------------------------------
246 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
247                                      (eq_attr "type" "fdivx")) 71 69)
248
249 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
250                                      (eq_attr "type" "fdivd")) 59 57)
251
252 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
253                                      (eq_attr "type" "fdivs")) 31 29)
254
255 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
256                                      (eq_attr "type" "fmul")) 9 7)
257
258 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
259                                      (eq_attr "type" "ffmul")) 6 4)
260
261 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
262                                      (eq_attr "type" "farith")) 4 2)
263
264 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
265                                      (eq_attr "type" "ffarith")) 2 2)
266
267 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
268                                      (eq_attr "type" "r_2_f")) 5 3)
269
270 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
271                                      (eq_attr "type" "f_2_r")) 1 2)
272
273 ; The fpa10 doesn't really have a memory read unit, but it can start to
274 ; speculatively execute the instruction in the pipeline, provided the data
275 ; is already loaded, so pretend reads have a delay of 2 (and that the
276 ; pipeline is infinite).
277
278 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
279                                          (eq_attr "type" "f_load")) 3 1)
280
281 ;;--------------------------------------------------------------------
282 ;; Write buffer
283 ;;--------------------------------------------------------------------
284 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
285 ;
286 ; The write buffer on some of the arm6 processors is hard to model exactly.
287 ; There is room in the buffer for up to two addresses and up to eight words
288 ; of memory, but the two needn't be split evenly.  When writing the two
289 ; addresses are fully pipelined.  However, a read from memory that is not
290 ; currently in the cache will block until the writes have completed.
291 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
292 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
293 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
294 ; cycle to add as well.
295
296 (define_function_unit "write_buf" 1 2
297   (and (eq_attr "model_wbuf" "yes")
298        (eq_attr "type" "store1,r_mem_f")) 5 3)
299 (define_function_unit "write_buf" 1 2 
300   (and (eq_attr "model_wbuf" "yes")
301        (eq_attr "type" "store2")) 7 4)
302 (define_function_unit "write_buf" 1 2
303   (and (eq_attr "model_wbuf" "yes")
304        (eq_attr "type" "store3")) 9 5)
305 (define_function_unit "write_buf" 1 2
306   (and (eq_attr "model_wbuf" "yes")
307        (eq_attr "type" "store4")) 11 6)
308
309 ;;--------------------------------------------------------------------
310 ;; Write blockage unit
311 ;;--------------------------------------------------------------------
312 ; The write_blockage unit models (partially), the fact that reads will stall
313 ; until the write buffer empties.
314 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
315 ; so we don't model them here
316 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
317                                                 (eq_attr "type" "store1")) 5 5
318         [(eq_attr "write_conflict" "yes")])
319 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
320                                                 (eq_attr "type" "store2")) 7 7
321         [(eq_attr "write_conflict" "yes")])
322 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
323                                                 (eq_attr "type" "store3")) 9 9
324         [(eq_attr "write_conflict" "yes")])
325 (define_function_unit "write_blockage" 1 0
326         (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
327         [(eq_attr "write_conflict" "yes")])
328 (define_function_unit "write_blockage" 1 0
329         (and (eq_attr "model_wbuf" "yes")
330              (eq_attr "write_conflict" "yes")) 1 1)
331
332 ;;--------------------------------------------------------------------
333 ;; Core unit
334 ;;--------------------------------------------------------------------
335 ; Everything must spend at least one cycle in the core unit
336 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
337
338 (define_function_unit "core" 1 0
339   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
340
341 (define_function_unit "core" 1 0
342   (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
343
344 ;; We do not need to conditionalize the define_function_unit immediately
345 ;; above.  This one will be ignored for anything other than xscale
346 ;; compiles and for xscale compiles it provides a larger delay
347 ;; and the scheduler will DTRT.
348 ;; FIXME: this test needs to be revamped to not depend on this feature 
349 ;; of the scheduler.
350
351 (define_function_unit "core" 1 0
352   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
353        (eq_attr "is_xscale" "yes"))
354    3 1)
355
356 (define_function_unit "core" 1 0
357   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
358
359 (define_function_unit "core" 1 0
360   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
361
362 (define_function_unit "core" 1 0
363   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
364
365 (define_function_unit "core" 1 0
366   (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
367
368 (define_function_unit "core" 1 0
369   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
370
371 (define_function_unit "core" 1 0
372   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
373
374 (define_function_unit "core" 1 0
375   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
376        (eq_attr "type" "mult")) 4 4)
377
378 (define_function_unit "core" 1 0
379   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
380        (eq_attr "type" "mult")) 3 2)
381
382 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
383
384 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
385
386 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
387
388 (define_function_unit "core" 1 0
389   (and (eq_attr "core_cycles" "multi")
390        (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
391 \f
392 (include "cirrus.md")
393
394 ;;---------------------------------------------------------------------------
395 ;; Insn patterns
396 ;;
397 ;; Addition insns.
398
399 ;; Note: For DImode insns, there is normally no reason why operands should
400 ;; not be in the same register, what we don't want is for something being
401 ;; written to partially overlap something that is an input.
402 ;; Cirrus 64bit additions should not be split because we have a native
403 ;; 64bit addition instructions.
404
405 (define_expand "adddi3"
406  [(parallel
407    [(set (match_operand:DI           0 "s_register_operand" "")
408           (plus:DI (match_operand:DI 1 "s_register_operand" "")
409                    (match_operand:DI 2 "s_register_operand" "")))
410     (clobber (reg:CC CC_REGNUM))])]
411   "TARGET_EITHER"
412   "
413   if (TARGET_CIRRUS)
414     {
415       if (!cirrus_fp_register (operands[0], DImode))
416         operands[0] = force_reg (DImode, operands[0]);
417       if (!cirrus_fp_register (operands[1], DImode))
418         operands[1] = force_reg (DImode, operands[1]);
419       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
420       DONE;
421     }
422
423   if (TARGET_THUMB)
424     {
425       if (GET_CODE (operands[1]) != REG)
426         operands[1] = force_reg (SImode, operands[1]);
427       if (GET_CODE (operands[2]) != REG)
428         operands[2] = force_reg (SImode, operands[2]);
429      }
430   "
431 )
432
433 (define_insn "*thumb_adddi3"
434   [(set (match_operand:DI          0 "register_operand" "=l")
435         (plus:DI (match_operand:DI 1 "register_operand" "%0")
436                  (match_operand:DI 2 "register_operand" "l")))
437    (clobber (reg:CC CC_REGNUM))
438   ]
439   "TARGET_THUMB"
440   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
441   [(set_attr "length" "4")]
442 )
443
444 (define_insn_and_split "*arm_adddi3"
445   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
446         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
447                  (match_operand:DI 2 "s_register_operand" "r,  0")))
448    (clobber (reg:CC CC_REGNUM))]
449   "TARGET_ARM && !TARGET_CIRRUS"
450   "#"
451   "TARGET_ARM && reload_completed"
452   [(parallel [(set (reg:CC_C CC_REGNUM)
453                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
454                                  (match_dup 1)))
455               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
456    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
457                                (plus:SI (match_dup 4) (match_dup 5))))]
458   "
459   {
460     operands[3] = gen_highpart (SImode, operands[0]);
461     operands[0] = gen_lowpart (SImode, operands[0]);
462     operands[4] = gen_highpart (SImode, operands[1]);
463     operands[1] = gen_lowpart (SImode, operands[1]);
464     operands[5] = gen_highpart (SImode, operands[2]);
465     operands[2] = gen_lowpart (SImode, operands[2]);
466   }"
467   [(set_attr "conds" "clob")
468    (set_attr "length" "8")]
469 )
470
471 (define_insn_and_split "*adddi_sesidi_di"
472   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
473         (plus:DI (sign_extend:DI
474                   (match_operand:SI 2 "s_register_operand" "r,r"))
475                  (match_operand:DI 1 "s_register_operand" "r,0")))
476    (clobber (reg:CC CC_REGNUM))]
477   "TARGET_ARM && !TARGET_CIRRUS"
478   "#"
479   "TARGET_ARM && reload_completed"
480   [(parallel [(set (reg:CC_C CC_REGNUM)
481                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
482                                  (match_dup 1)))
483               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
484    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
485                                (plus:SI (ashiftrt:SI (match_dup 2)
486                                                      (const_int 31))
487                                         (match_dup 4))))]
488   "
489   {
490     operands[3] = gen_highpart (SImode, operands[0]);
491     operands[0] = gen_lowpart (SImode, operands[0]);
492     operands[4] = gen_highpart (SImode, operands[1]);
493     operands[1] = gen_lowpart (SImode, operands[1]);
494     operands[2] = gen_lowpart (SImode, operands[2]);
495   }"
496   [(set_attr "conds" "clob")
497    (set_attr "length" "8")]
498 )
499
500 (define_insn_and_split "*adddi_zesidi_di"
501   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
502         (plus:DI (zero_extend:DI
503                   (match_operand:SI 2 "s_register_operand" "r,r"))
504                  (match_operand:DI 1 "s_register_operand" "r,0")))
505    (clobber (reg:CC CC_REGNUM))]
506   "TARGET_ARM && !TARGET_CIRRUS"
507   "#"
508   "TARGET_ARM && reload_completed"
509   [(parallel [(set (reg:CC_C CC_REGNUM)
510                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
511                                  (match_dup 1)))
512               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
513    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
514                                (plus:SI (match_dup 4) (const_int 0))))]
515   "
516   {
517     operands[3] = gen_highpart (SImode, operands[0]);
518     operands[0] = gen_lowpart (SImode, operands[0]);
519     operands[4] = gen_highpart (SImode, operands[1]);
520     operands[1] = gen_lowpart (SImode, operands[1]);
521     operands[2] = gen_lowpart (SImode, operands[2]);
522   }"
523   [(set_attr "conds" "clob")
524    (set_attr "length" "8")]
525 )
526
527 (define_expand "addsi3"
528   [(set (match_operand:SI          0 "s_register_operand" "")
529         (plus:SI (match_operand:SI 1 "s_register_operand" "")
530                  (match_operand:SI 2 "reg_or_int_operand" "")))]
531   "TARGET_EITHER"
532   "
533   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
534     {
535       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
536                           operands[1],
537                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
538       DONE;
539     }
540   "
541 )
542
543 ; If there is a scratch available, this will be faster than synthesising the
544 ; addition.
545 (define_peephole2
546   [(match_scratch:SI 3 "r")
547    (set (match_operand:SI          0 "s_register_operand" "")
548         (plus:SI (match_operand:SI 1 "s_register_operand" "")
549                  (match_operand:SI 2 "const_int_operand"  "")))]
550   "TARGET_ARM &&
551    !(const_ok_for_arm (INTVAL (operands[2]))
552      || const_ok_for_arm (-INTVAL (operands[2])))
553     && const_ok_for_arm (~INTVAL (operands[2]))"
554   [(set (match_dup 3) (match_dup 2))
555    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
556   ""
557 )
558
559 (define_insn_and_split "*arm_addsi3"
560   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
561         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
562                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
563   "TARGET_ARM"
564   "@
565    add%?\\t%0, %1, %2
566    sub%?\\t%0, %1, #%n2
567    #"
568   "TARGET_ARM &&
569    GET_CODE (operands[2]) == CONST_INT
570    && !(const_ok_for_arm (INTVAL (operands[2]))
571         || const_ok_for_arm (-INTVAL (operands[2])))"
572   [(clobber (const_int 0))]
573   "
574   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
575                       operands[1], 0);
576   DONE;
577   "
578   [(set_attr "length" "4,4,16")
579    (set_attr "predicable" "yes")]
580 )
581
582 ;; Register group 'k' is a single register group containing only the stack
583 ;; register.  Trying to reload it will always fail catastrophically,
584 ;; so never allow those alternatives to match if reloading is needed.
585
586 (define_insn "*thumb_addsi3"
587   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
588         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
589                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
590   "TARGET_THUMB"
591   "*
592    static const char * const asms[] = 
593    {
594      \"add\\t%0, %0, %2\",
595      \"sub\\t%0, %0, #%n2\",
596      \"add\\t%0, %1, %2\",
597      \"add\\t%0, %0, %2\",
598      \"add\\t%0, %0, %2\",
599      \"add\\t%0, %1, %2\",
600      \"add\\t%0, %1, %2\"
601    };
602    if ((which_alternative == 2 || which_alternative == 6)
603        && GET_CODE (operands[2]) == CONST_INT
604        && INTVAL (operands[2]) < 0)
605      return \"sub\\t%0, %1, #%n2\";
606    return asms[which_alternative];
607   "
608   [(set_attr "length" "2")]
609 )
610
611 ;; Reloading and elimination of the frame pointer can
612 ;; sometimes cause this optimization to be missed.
613 (define_peephole2
614   [(set (match_operand:SI 0 "register_operand" "")
615         (match_operand:SI 1 "const_int_operand" ""))
616    (set (match_dup 0)
617         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
618   "TARGET_THUMB
619    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
620    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
621    && (INTVAL (operands[1]) & 3) == 0"
622   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
623   ""
624 )
625
626 (define_insn "*addsi3_compare0"
627   [(set (reg:CC_NOOV CC_REGNUM)
628         (compare:CC_NOOV
629          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
630                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
631          (const_int 0)))
632    (set (match_operand:SI 0 "s_register_operand" "=r,r")
633         (plus:SI (match_dup 1) (match_dup 2)))]
634   "TARGET_ARM"
635   "@
636    add%?s\\t%0, %1, %2
637    sub%?s\\t%0, %1, #%n2"
638   [(set_attr "conds" "set")]
639 )
640
641 (define_insn "*addsi3_compare0_scratch"
642   [(set (reg:CC_NOOV CC_REGNUM)
643         (compare:CC_NOOV
644          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
645                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
646          (const_int 0)))]
647   "TARGET_ARM"
648   "@
649    cmn%?\\t%0, %1
650    cmp%?\\t%0, #%n1"
651   [(set_attr "conds" "set")]
652 )
653
654 ;; These patterns are the same ones as the two regular addsi3_compare0
655 ;; patterns, except we write them slightly different - the combiner
656 ;; tends to generate them this way.
657 (define_insn "*addsi3_compare0_for_combiner"
658   [(set (reg:CC CC_REGNUM)
659         (compare:CC
660          (match_operand:SI 1 "s_register_operand" "r,r")
661          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
662    (set (match_operand:SI 0 "s_register_operand" "=r,r")
663         (plus:SI (match_dup 1) (match_dup 2)))]
664   "TARGET_ARM"
665   "@
666    add%?s\\t%0, %1, %2
667    sub%?s\\t%0, %1, #%n2"
668   [(set_attr "conds" "set")]
669 )
670
671 (define_insn "*addsi3_compare0_scratch_for_combiner"
672   [(set (reg:CC CC_REGNUM)
673         (compare:CC
674          (match_operand:SI 0 "s_register_operand" "r,r")
675          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
676   "TARGET_ARM"
677   "@
678    cmn%?\\t%0, %1
679    cmp%?\\t%0, #%n1"
680   [(set_attr "conds" "set")]
681 )
682
683 ;; The next four insns work because they compare the result with one of
684 ;; the operands, and we know that the use of the condition code is
685 ;; either GEU or LTU, so we can use the carry flag from the addition
686 ;; instead of doing the compare a second time.
687 (define_insn "*addsi3_compare_op1"
688   [(set (reg:CC_C CC_REGNUM)
689         (compare:CC_C
690          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
691                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
692          (match_dup 1)))
693    (set (match_operand:SI 0 "s_register_operand" "=r,r")
694         (plus:SI (match_dup 1) (match_dup 2)))]
695   "TARGET_ARM"
696   "@
697    add%?s\\t%0, %1, %2
698    sub%?s\\t%0, %1, #%n2"
699   [(set_attr "conds" "set")]
700 )
701
702 (define_insn "*addsi3_compare_op2"
703   [(set (reg:CC_C CC_REGNUM)
704         (compare:CC_C
705          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
706                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
707          (match_dup 2)))
708    (set (match_operand:SI 0 "s_register_operand" "=r,r")
709         (plus:SI (match_dup 1) (match_dup 2)))]
710   "TARGET_ARM"
711   "@
712    add%?s\\t%0, %1, %2
713    sub%?s\\t%0, %1, #%n2"
714   [(set_attr "conds" "set")]
715 )
716
717 (define_insn "*compare_addsi2_op0"
718   [(set (reg:CC_C CC_REGNUM)
719         (compare:CC_C
720          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
721                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
722          (match_dup 0)))]
723   "TARGET_ARM"
724   "@
725    cmn%?\\t%0, %1
726    cmp%?\\t%0, #%n1"
727   [(set_attr "conds" "set")]
728 )
729
730 (define_insn "*compare_addsi2_op1"
731   [(set (reg:CC_C CC_REGNUM)
732         (compare:CC_C
733          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
734                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
735          (match_dup 1)))]
736   "TARGET_ARM"
737   "@
738    cmn%?\\t%0, %1
739    cmp%?\\t%0, #%n1"
740   [(set_attr "conds" "set")]
741 )
742
743 (define_insn "*addsi3_carryin"
744   [(set (match_operand:SI 0 "s_register_operand" "=r")
745         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
746                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
747                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
748   "TARGET_ARM"
749   "adc%?\\t%0, %1, %2"
750   [(set_attr "conds" "use")]
751 )
752
753 (define_insn "*addsi3_carryin_shift"
754   [(set (match_operand:SI 0 "s_register_operand" "")
755         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
756                  (plus:SI
757                    (match_operator:SI 2 "shift_operator"
758                       [(match_operand:SI 3 "s_register_operand" "")
759                        (match_operand:SI 4 "reg_or_int_operand" "")])
760                     (match_operand:SI 1 "s_register_operand" ""))))]
761   "TARGET_ARM"
762   "adc%?\\t%0, %1, %3%S2"
763   [(set_attr "conds" "use")]
764 )
765
766 (define_insn "*addsi3_carryin_alt1"
767   [(set (match_operand:SI 0 "s_register_operand" "=r")
768         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
769                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
770                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
771   "TARGET_ARM"
772   "adc%?\\t%0, %1, %2"
773   [(set_attr "conds" "use")]
774 )
775
776 (define_insn "*addsi3_carryin_alt2"
777   [(set (match_operand:SI 0 "s_register_operand" "=r")
778         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
779                           (match_operand:SI 1 "s_register_operand" "r"))
780                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
781   "TARGET_ARM"
782   "adc%?\\t%0, %1, %2"
783   [(set_attr "conds" "use")]
784 )
785
786 (define_insn "*addsi3_carryin_alt3"
787   [(set (match_operand:SI 0 "s_register_operand" "=r")
788         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
789                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
790                  (match_operand:SI 1 "s_register_operand" "r")))]
791   "TARGET_ARM"
792   "adc%?\\t%0, %1, %2"
793   [(set_attr "conds" "use")]
794 )
795
796 (define_insn "incscc"
797   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
798         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
799                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
800                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
801   "TARGET_ARM"
802   "@
803   add%d2\\t%0, %1, #1
804   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
805   [(set_attr "conds" "use")
806    (set_attr "length" "4,8")]
807 )
808
809 (define_insn "*arm_addsf3"
810   [(set (match_operand:SF          0 "s_register_operand" "=f,f")
811         (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
812                  (match_operand:SF 2 "fpu_add_operand"    "fG,H")))]
813   "TARGET_ARM && TARGET_HARD_FLOAT"
814   "@
815    adf%?s\\t%0, %1, %2
816    suf%?s\\t%0, %1, #%N2"
817   [(set_attr "type" "farith")
818    (set_attr "predicable" "yes")]
819 )
820
821 (define_insn "*arm_adddf3"
822   [(set (match_operand:DF          0 "s_register_operand" "=f,f")
823         (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
824                  (match_operand:DF 2 "fpu_add_operand"    "fG,H")))]
825   "TARGET_ARM && TARGET_HARD_FLOAT"
826   "@
827    adf%?d\\t%0, %1, %2
828    suf%?d\\t%0, %1, #%N2"
829   [(set_attr "type" "farith")
830    (set_attr "predicable" "yes")]
831 )
832
833 (define_insn "*adddf_esfdf_df"
834   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
835         (plus:DF (float_extend:DF
836                   (match_operand:SF 1 "s_register_operand"  "f,f"))
837                  (match_operand:DF  2 "fpu_add_operand"    "fG,H")))]
838   "TARGET_ARM && TARGET_HARD_FLOAT"
839   "@
840    adf%?d\\t%0, %1, %2
841    suf%?d\\t%0, %1, #%N2"
842   [(set_attr "type" "farith")
843    (set_attr "predicable" "yes")]
844 )
845
846 (define_insn "*adddf_df_esfdf"
847   [(set (match_operand:DF           0 "s_register_operand" "=f")
848         (plus:DF (match_operand:DF  1 "s_register_operand"  "f")
849                  (float_extend:DF
850                   (match_operand:SF 2 "s_register_operand"  "f"))))]
851   "TARGET_ARM && TARGET_HARD_FLOAT"
852   "adf%?d\\t%0, %1, %2"
853   [(set_attr "type" "farith")
854    (set_attr "predicable" "yes")]
855 )
856
857 (define_insn "*adddf_esfdf_esfdf"
858   [(set (match_operand:DF           0 "s_register_operand" "=f")
859         (plus:DF (float_extend:DF 
860                   (match_operand:SF 1 "s_register_operand" "f"))
861                  (float_extend:DF
862                   (match_operand:SF 2 "s_register_operand" "f"))))]
863   "TARGET_ARM && TARGET_HARD_FLOAT"
864   "adf%?d\\t%0, %1, %2"
865   [(set_attr "type" "farith")
866    (set_attr "predicable" "yes")]
867 )
868
869 (define_expand "subdi3"
870  [(parallel
871    [(set (match_operand:DI            0 "s_register_operand" "")
872           (minus:DI (match_operand:DI 1 "s_register_operand" "")
873                     (match_operand:DI 2 "s_register_operand" "")))
874     (clobber (reg:CC CC_REGNUM))])]
875   "TARGET_EITHER"
876   "
877   if (TARGET_CIRRUS
878       && TARGET_ARM
879       && cirrus_fp_register (operands[0], DImode)
880       && cirrus_fp_register (operands[1], DImode))
881     {
882       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
883       DONE;
884     }
885
886   if (TARGET_THUMB)
887     {
888       if (GET_CODE (operands[1]) != REG)
889         operands[1] = force_reg (SImode, operands[1]);
890       if (GET_CODE (operands[2]) != REG)
891         operands[2] = force_reg (SImode, operands[2]);
892      }  
893   "
894 )
895
896 (define_insn "*arm_subdi3"
897   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
898         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
899                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
900    (clobber (reg:CC CC_REGNUM))]
901   "TARGET_ARM"
902   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
903   [(set_attr "conds" "clob")
904    (set_attr "length" "8")]
905 )
906
907 (define_insn "*thumb_subdi3"
908   [(set (match_operand:DI           0 "register_operand" "=l")
909         (minus:DI (match_operand:DI 1 "register_operand"  "0")
910                   (match_operand:DI 2 "register_operand"  "l")))
911    (clobber (reg:CC CC_REGNUM))]
912   "TARGET_THUMB"
913   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
914   [(set_attr "length" "4")]
915 )
916
917 (define_insn "*subdi_di_zesidi"
918   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
919         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
920                   (zero_extend:DI
921                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
922    (clobber (reg:CC CC_REGNUM))]
923   "TARGET_ARM"
924   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
925   [(set_attr "conds" "clob")
926    (set_attr "length" "8")]
927 )
928
929 (define_insn "*subdi_di_sesidi"
930   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
931         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
932                   (sign_extend:DI
933                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
934    (clobber (reg:CC CC_REGNUM))]
935   "TARGET_ARM"
936   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
937   [(set_attr "conds" "clob")
938    (set_attr "length" "8")]
939 )
940
941 (define_insn "*subdi_zesidi_di"
942   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
943         (minus:DI (zero_extend:DI
944                    (match_operand:SI 2 "s_register_operand"  "r,r"))
945                   (match_operand:DI  1 "s_register_operand" "?r,0")))
946    (clobber (reg:CC CC_REGNUM))]
947   "TARGET_ARM"
948   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
949   [(set_attr "conds" "clob")
950    (set_attr "length" "8")]
951 )
952
953 (define_insn "*subdi_sesidi_di"
954   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
955         (minus:DI (sign_extend:DI
956                    (match_operand:SI 2 "s_register_operand"   "r,r"))
957                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
958    (clobber (reg:CC CC_REGNUM))]
959   "TARGET_ARM"
960   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
961   [(set_attr "conds" "clob")
962    (set_attr "length" "8")]
963 )
964
965 (define_insn "*subdi_zesidi_zesidi"
966   [(set (match_operand:DI            0 "s_register_operand" "=r")
967         (minus:DI (zero_extend:DI
968                    (match_operand:SI 1 "s_register_operand"  "r"))
969                   (zero_extend:DI
970                    (match_operand:SI 2 "s_register_operand"  "r"))))
971    (clobber (reg:CC CC_REGNUM))]
972   "TARGET_ARM"
973   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
974   [(set_attr "conds" "clob")
975    (set_attr "length" "8")]
976 )
977
978 (define_expand "subsi3"
979   [(set (match_operand:SI           0 "s_register_operand" "")
980         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
981                   (match_operand:SI 2 "s_register_operand" "")))]
982   "TARGET_EITHER"
983   "
984   if (GET_CODE (operands[1]) == CONST_INT)
985     {
986       if (TARGET_ARM)
987         {
988           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
989                               operands[2],
990                               (no_new_pseudos ? 0
991                                :  preserve_subexpressions_p ()));
992           DONE;
993         }
994       else /* TARGET_THUMB */
995         operands[1] = force_reg (SImode, operands[1]);
996     }
997   "
998 )
999
1000 (define_insn "*thumb_subsi3_insn"
1001   [(set (match_operand:SI           0 "register_operand" "=l")
1002         (minus:SI (match_operand:SI 1 "register_operand" "l")
1003                   (match_operand:SI 2 "register_operand" "l")))]
1004   "TARGET_THUMB"
1005   "sub\\t%0, %1, %2"
1006   [(set_attr "length" "2")]
1007 )
1008
1009 (define_insn_and_split "*arm_subsi3_insn"
1010   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
1011         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1012                   (match_operand:SI 2 "s_register_operand" "r,r")))]
1013   "TARGET_ARM"
1014   "@
1015    rsb%?\\t%0, %2, %1
1016    #"
1017   "TARGET_ARM
1018    && GET_CODE (operands[1]) == CONST_INT
1019    && !const_ok_for_arm (INTVAL (operands[1]))"
1020   [(clobber (const_int 0))]
1021   "
1022   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1023                       operands[2], 0);
1024   DONE;
1025   "
1026   [(set_attr "length" "4,16")
1027    (set_attr "predicable" "yes")]
1028 )
1029
1030 (define_peephole2
1031   [(match_scratch:SI 3 "r")
1032    (set (match_operand:SI           0 "s_register_operand" "")
1033         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1034                   (match_operand:SI 2 "s_register_operand" "")))]
1035   "TARGET_ARM
1036    && !const_ok_for_arm (INTVAL (operands[1]))
1037    && const_ok_for_arm (~INTVAL (operands[1]))"
1038   [(set (match_dup 3) (match_dup 1))
1039    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1040   ""
1041 )
1042
1043 (define_insn "*subsi3_compare0"
1044   [(set (reg:CC_NOOV CC_REGNUM)
1045         (compare:CC_NOOV
1046          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1047                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1048          (const_int 0)))
1049    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1050         (minus:SI (match_dup 1) (match_dup 2)))]
1051   "TARGET_ARM"
1052   "@
1053    sub%?s\\t%0, %1, %2
1054    rsb%?s\\t%0, %2, %1"
1055   [(set_attr "conds" "set")]
1056 )
1057
1058 (define_insn "decscc"
1059   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1060         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1061                   (match_operator:SI 2 "arm_comparison_operator"
1062                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1063   "TARGET_ARM"
1064   "@
1065    sub%d2\\t%0, %1, #1
1066    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1067   [(set_attr "conds" "use")
1068    (set_attr "length" "*,8")]
1069 )
1070
1071 (define_insn "*arm_subsf3"
1072   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1073         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1074                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1075   "TARGET_ARM && TARGET_HARD_FLOAT"
1076   "@
1077    suf%?s\\t%0, %1, %2
1078    rsf%?s\\t%0, %2, %1"
1079   [(set_attr "type" "farith")]
1080 )
1081
1082 (define_insn "*arm_subdf3"
1083   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
1084         (minus:DF (match_operand:DF 1 "fpu_rhs_operand"     "f,G")
1085                   (match_operand:DF 2 "fpu_rhs_operand"    "fG,f")))]
1086   "TARGET_ARM && TARGET_HARD_FLOAT"
1087   "@
1088    suf%?d\\t%0, %1, %2
1089    rsf%?d\\t%0, %2, %1"
1090   [(set_attr "type" "farith")
1091    (set_attr "predicable" "yes")]
1092 )
1093
1094 (define_insn "*subdf_esfdf_df"
1095   [(set (match_operand:DF            0 "s_register_operand" "=f")
1096         (minus:DF (float_extend:DF
1097                    (match_operand:SF 1 "s_register_operand"  "f"))
1098                   (match_operand:DF  2 "fpu_rhs_operand"    "fG")))]
1099   "TARGET_ARM && TARGET_HARD_FLOAT"
1100   "suf%?d\\t%0, %1, %2"
1101   [(set_attr "type" "farith")
1102    (set_attr "predicable" "yes")]
1103 )
1104
1105 (define_insn "*subdf_df_esfdf"
1106   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1107         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1108                   (float_extend:DF
1109                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
1110   "TARGET_ARM && TARGET_HARD_FLOAT"
1111   "@
1112    suf%?d\\t%0, %1, %2
1113    rsf%?d\\t%0, %2, %1"
1114   [(set_attr "type" "farith")
1115    (set_attr "predicable" "yes")]
1116 )
1117
1118 (define_insn "*subdf_esfdf_esfdf"
1119   [(set (match_operand:DF 0 "s_register_operand" "=f")
1120         (minus:DF (float_extend:DF
1121                    (match_operand:SF 1 "s_register_operand" "f"))
1122                   (float_extend:DF
1123                    (match_operand:SF 2 "s_register_operand" "f"))))]
1124   "TARGET_ARM && TARGET_HARD_FLOAT"
1125   "suf%?d\\t%0, %1, %2"
1126   [(set_attr "type" "farith")
1127    (set_attr "predicable" "yes")]
1128 )
1129 \f
1130 ;; Multiplication insns
1131
1132 (define_expand "mulsi3"
1133   [(set (match_operand:SI          0 "s_register_operand" "")
1134         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1135                  (match_operand:SI 1 "s_register_operand" "")))]
1136   "TARGET_EITHER"
1137   ""
1138 )
1139
1140 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1141 (define_insn "*arm_mulsi3"
1142   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1143         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1144                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1145   "TARGET_ARM"
1146   "mul%?\\t%0, %2, %1"
1147   [(set_attr "type" "mult")
1148    (set_attr "predicable" "yes")]
1149 )
1150
1151 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1152 ; 1 and 2; are the same, because reload will make operand 0 match 
1153 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1154 ; this by adding another alternative to match this case, and then `reload' 
1155 ; it ourselves.  This alternative must come first.
1156 (define_insn "*thumb_mulsi3"
1157   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1158         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1159                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1160   "TARGET_THUMB"
1161   "*
1162   if (which_alternative < 2)
1163     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1164   else
1165     return \"mul\\t%0, %0, %2\";
1166   "
1167   [(set_attr "length" "4,4,2")
1168    (set_attr "type" "mult")]
1169 )
1170
1171 (define_insn "*mulsi3_compare0"
1172   [(set (reg:CC_NOOV CC_REGNUM)
1173         (compare:CC_NOOV (mult:SI
1174                           (match_operand:SI 2 "s_register_operand" "r,r")
1175                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1176                          (const_int 0)))
1177    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1178         (mult:SI (match_dup 2) (match_dup 1)))]
1179   "TARGET_ARM && !arm_is_xscale"
1180   "mul%?s\\t%0, %2, %1"
1181   [(set_attr "conds" "set")
1182    (set_attr "type" "mult")]
1183 )
1184
1185 (define_insn "*mulsi_compare0_scratch"
1186   [(set (reg:CC_NOOV CC_REGNUM)
1187         (compare:CC_NOOV (mult:SI
1188                           (match_operand:SI 2 "s_register_operand" "r,r")
1189                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1190                          (const_int 0)))
1191    (clobber (match_scratch:SI 0 "=&r,&r"))]
1192   "TARGET_ARM && !arm_is_xscale"
1193   "mul%?s\\t%0, %2, %1"
1194   [(set_attr "conds" "set")
1195    (set_attr "type" "mult")]
1196 )
1197
1198 ;; Unnamed templates to match MLA instruction.
1199
1200 (define_insn "*mulsi3addsi"
1201   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1202         (plus:SI
1203           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1204                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1205           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1206   "TARGET_ARM"
1207   "mla%?\\t%0, %2, %1, %3"
1208   [(set_attr "type" "mult")
1209    (set_attr "predicable" "yes")]
1210 )
1211
1212 (define_insn "*mulsi3addsi_compare0"
1213   [(set (reg:CC_NOOV CC_REGNUM)
1214         (compare:CC_NOOV
1215          (plus:SI (mult:SI
1216                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1217                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1218                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1219          (const_int 0)))
1220    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1221         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1222                  (match_dup 3)))]
1223   "TARGET_ARM && !arm_is_xscale"
1224   "mla%?s\\t%0, %2, %1, %3"
1225   [(set_attr "conds" "set")
1226    (set_attr "type" "mult")]
1227 )
1228
1229 (define_insn "*mulsi3addsi_compare0_scratch"
1230   [(set (reg:CC_NOOV CC_REGNUM)
1231         (compare:CC_NOOV
1232          (plus:SI (mult:SI
1233                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1234                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1235                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1236          (const_int 0)))
1237    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1238   "TARGET_ARM && !arm_is_xscale"
1239   "mla%?s\\t%0, %2, %1, %3"
1240   [(set_attr "conds" "set")
1241    (set_attr "type" "mult")]
1242 )
1243
1244 ;; Unnamed template to match long long multiply-accumlate (smlal)
1245
1246 (define_insn "*mulsidi3adddi"
1247   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1248         (plus:DI
1249          (mult:DI
1250           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1251           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1252          (match_operand:DI 1 "s_register_operand" "0")))]
1253   "TARGET_ARM && arm_fast_multiply"
1254   "smlal%?\\t%Q0, %R0, %3, %2"
1255   [(set_attr "type" "mult")
1256    (set_attr "predicable" "yes")]
1257 )
1258
1259 (define_insn "mulsidi3"
1260   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1261         (mult:DI
1262          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1263          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1264   "TARGET_ARM && arm_fast_multiply"
1265   "smull%?\\t%Q0, %R0, %1, %2"
1266   [(set_attr "type" "mult")
1267    (set_attr "predicable" "yes")]
1268 )
1269
1270 (define_insn "umulsidi3"
1271   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1272         (mult:DI
1273          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1274          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1275   "TARGET_ARM && arm_fast_multiply"
1276   "umull%?\\t%Q0, %R0, %1, %2"
1277   [(set_attr "type" "mult")
1278    (set_attr "predicable" "yes")]
1279 )
1280
1281 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1282
1283 (define_insn "*umulsidi3adddi"
1284   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1285         (plus:DI
1286          (mult:DI
1287           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1288           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1289          (match_operand:DI 1 "s_register_operand" "0")))]
1290   "TARGET_ARM && arm_fast_multiply"
1291   "umlal%?\\t%Q0, %R0, %3, %2"
1292   [(set_attr "type" "mult")
1293    (set_attr "predicable" "yes")]
1294 )
1295
1296 (define_insn "smulsi3_highpart"
1297   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1298         (truncate:SI
1299          (lshiftrt:DI
1300           (mult:DI
1301            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1302            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1303           (const_int 32))))
1304    (clobber (match_scratch:SI 3 "=&r,&r"))]
1305   "TARGET_ARM && arm_fast_multiply"
1306   "smull%?\\t%3, %0, %2, %1"
1307   [(set_attr "type" "mult")
1308    (set_attr "predicable" "yes")]
1309 )
1310
1311 (define_insn "umulsi3_highpart"
1312   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1313         (truncate:SI
1314          (lshiftrt:DI
1315           (mult:DI
1316            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1317            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1318           (const_int 32))))
1319    (clobber (match_scratch:SI 3 "=&r,&r"))]
1320   "TARGET_ARM && arm_fast_multiply"
1321   "umull%?\\t%3, %0, %2, %1"
1322   [(set_attr "type" "mult")
1323    (set_attr "predicable" "yes")]
1324 )
1325
1326 (define_insn "mulhisi3"
1327   [(set (match_operand:SI 0 "s_register_operand" "=r")
1328         (mult:SI (sign_extend:SI
1329                   (match_operand:HI 1 "s_register_operand" "%r"))
1330                  (sign_extend:SI
1331                   (match_operand:HI 2 "s_register_operand" "r"))))]
1332   "TARGET_ARM && arm_arch5e"
1333   "smulbb%?\\t%0, %1, %2"
1334   [(set_attr "type" "mult")
1335    (set_attr "predicable" "yes")]
1336 )
1337
1338 (define_insn "*mulhisi3tb"
1339   [(set (match_operand:SI 0 "s_register_operand" "=r")
1340         (mult:SI (ashiftrt:SI
1341                   (match_operand:SI 1 "s_register_operand" "r")
1342                   (const_int 16))
1343                  (sign_extend:SI
1344                   (match_operand:HI 2 "s_register_operand" "r"))))]
1345   "TARGET_ARM && arm_arch5e"
1346   "smultb%?\\t%0, %1, %2"
1347   [(set_attr "type" "mult")
1348    (set_attr "predicable" "yes")]
1349 )
1350
1351 (define_insn "*mulhisi3bt"
1352   [(set (match_operand:SI 0 "s_register_operand" "=r")
1353         (mult:SI (sign_extend:SI
1354                   (match_operand:HI 1 "s_register_operand" "r"))
1355                  (ashiftrt:SI
1356                   (match_operand:SI 2 "s_register_operand" "r")
1357                   (const_int 16))))]
1358   "TARGET_ARM && arm_arch5e"
1359   "smulbt%?\\t%0, %1, %2"
1360   [(set_attr "type" "mult")
1361    (set_attr "predicable" "yes")]
1362 )
1363
1364 (define_insn "*mulhisi3tt"
1365   [(set (match_operand:SI 0 "s_register_operand" "=r")
1366         (mult:SI (ashiftrt:SI
1367                   (match_operand:SI 1 "s_register_operand" "r")
1368                   (const_int 16))
1369                  (ashiftrt:SI
1370                   (match_operand:SI 2 "s_register_operand" "r")
1371                   (const_int 16))))]
1372   "TARGET_ARM && arm_arch5e"
1373   "smultt%?\\t%0, %1, %2"
1374   [(set_attr "type" "mult")
1375    (set_attr "predicable" "yes")]
1376 )
1377
1378 (define_insn "*mulhisi3addsi"
1379   [(set (match_operand:SI 0 "s_register_operand" "=r")
1380         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1381                  (mult:SI (sign_extend:SI
1382                            (match_operand:HI 2 "s_register_operand" "%r"))
1383                           (sign_extend:SI
1384                            (match_operand:HI 3 "s_register_operand" "r")))))]
1385   "TARGET_ARM && arm_arch5e"
1386   "smlabb%?\\t%0, %2, %3, %1"
1387   [(set_attr "type" "mult")
1388    (set_attr "predicable" "yes")]
1389 )
1390
1391 (define_insn "*mulhidi3adddi"
1392   [(set (match_operand:DI 0 "s_register_operand" "=r")
1393         (plus:DI
1394           (match_operand:DI 1 "s_register_operand" "0")
1395           (mult:DI (sign_extend:DI
1396                     (match_operand:HI 2 "s_register_operand" "%r"))
1397                    (sign_extend:DI
1398                     (match_operand:HI 3 "s_register_operand" "r")))))]
1399   "TARGET_ARM && arm_arch5e"
1400   "smlalbb%?\\t%Q0, %R0, %2, %3"
1401   [(set_attr "type" "mult")
1402    (set_attr "predicable" "yes")])
1403
1404 (define_insn "*arm_mulsf3"
1405   [(set (match_operand:SF 0 "s_register_operand" "=f")
1406         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1407                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1408   "TARGET_ARM && TARGET_HARD_FLOAT"
1409   "fml%?s\\t%0, %1, %2"
1410   [(set_attr "type" "ffmul")
1411    (set_attr "predicable" "yes")]
1412 )
1413
1414 (define_insn "*arm_muldf3"
1415   [(set (match_operand:DF 0 "s_register_operand" "=f")
1416         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1417                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1418   "TARGET_ARM && TARGET_HARD_FLOAT"
1419   "muf%?d\\t%0, %1, %2"
1420   [(set_attr "type" "fmul")
1421    (set_attr "predicable" "yes")]
1422 )
1423
1424 (define_insn "*muldf_esfdf_df"
1425   [(set (match_operand:DF 0 "s_register_operand" "=f")
1426         (mult:DF (float_extend:DF
1427                   (match_operand:SF 1 "s_register_operand" "f"))
1428                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1429   "TARGET_ARM && TARGET_HARD_FLOAT"
1430   "muf%?d\\t%0, %1, %2"
1431   [(set_attr "type" "fmul")
1432    (set_attr "predicable" "yes")]
1433 )
1434
1435 (define_insn "*muldf_df_esfdf"
1436   [(set (match_operand:DF 0 "s_register_operand" "=f")
1437         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1438                  (float_extend:DF
1439                   (match_operand:SF 2 "s_register_operand" "f"))))]
1440   "TARGET_ARM && TARGET_HARD_FLOAT"
1441   "muf%?d\\t%0, %1, %2"
1442   [(set_attr "type" "fmul")
1443    (set_attr "predicable" "yes")]
1444 )
1445
1446 (define_insn "*muldf_esfdf_esfdf"
1447   [(set (match_operand:DF 0 "s_register_operand" "=f")
1448         (mult:DF
1449          (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1450          (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1451   "TARGET_ARM && TARGET_HARD_FLOAT"
1452   "muf%?d\\t%0, %1, %2"
1453   [(set_attr "type" "fmul")
1454    (set_attr "predicable" "yes")]
1455 )
1456 \f
1457 ;; Division insns
1458
1459 (define_insn "divsf3"
1460   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1461         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1462                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1463   "TARGET_ARM && TARGET_HARD_FLOAT"
1464   "@
1465    fdv%?s\\t%0, %1, %2
1466    frd%?s\\t%0, %2, %1"
1467   [(set_attr "type" "fdivs")
1468    (set_attr "predicable" "yes")]
1469 )
1470
1471 (define_insn "divdf3"
1472   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1473         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1474                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1475   "TARGET_ARM && TARGET_HARD_FLOAT"
1476   "@
1477    dvf%?d\\t%0, %1, %2
1478    rdf%?d\\t%0, %2, %1"
1479   [(set_attr "type" "fdivd")
1480    (set_attr "predicable" "yes")]
1481 )
1482
1483 (define_insn "*divdf_esfdf_df"
1484   [(set (match_operand:DF 0 "s_register_operand" "=f")
1485         (div:DF (float_extend:DF
1486                  (match_operand:SF 1 "s_register_operand" "f"))
1487                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1488   "TARGET_ARM && TARGET_HARD_FLOAT"
1489   "dvf%?d\\t%0, %1, %2"
1490   [(set_attr "type" "fdivd")
1491    (set_attr "predicable" "yes")]
1492 )
1493
1494 (define_insn "*divdf_df_esfdf"
1495   [(set (match_operand:DF 0 "s_register_operand" "=f")
1496         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1497                 (float_extend:DF
1498                  (match_operand:SF 2 "s_register_operand" "f"))))]
1499   "TARGET_ARM && TARGET_HARD_FLOAT"
1500   "rdf%?d\\t%0, %2, %1"
1501   [(set_attr "type" "fdivd")
1502    (set_attr "predicable" "yes")]
1503 )
1504
1505 (define_insn "*divdf_esfdf_esfdf"
1506   [(set (match_operand:DF 0 "s_register_operand" "=f")
1507         (div:DF (float_extend:DF
1508                  (match_operand:SF 1 "s_register_operand" "f"))
1509                 (float_extend:DF
1510                  (match_operand:SF 2 "s_register_operand" "f"))))]
1511   "TARGET_ARM && TARGET_HARD_FLOAT"
1512   "dvf%?d\\t%0, %1, %2"
1513   [(set_attr "type" "fdivd")
1514    (set_attr "predicable" "yes")]
1515 )
1516 \f
1517 ;; Modulo insns
1518
1519 (define_insn "modsf3"
1520   [(set (match_operand:SF 0 "s_register_operand" "=f")
1521         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1522                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1523   "TARGET_ARM && TARGET_HARD_FLOAT"
1524   "rmf%?s\\t%0, %1, %2"
1525   [(set_attr "type" "fdivs")
1526    (set_attr "predicable" "yes")]
1527 )
1528
1529 (define_insn "moddf3"
1530   [(set (match_operand:DF 0 "s_register_operand" "=f")
1531         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1532                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1533   "TARGET_ARM && TARGET_HARD_FLOAT"
1534   "rmf%?d\\t%0, %1, %2"
1535   [(set_attr "type" "fdivd")
1536    (set_attr "predicable" "yes")]
1537 )
1538
1539 (define_insn "*moddf_esfdf_df"
1540   [(set (match_operand:DF 0 "s_register_operand" "=f")
1541         (mod:DF (float_extend:DF
1542                  (match_operand:SF 1 "s_register_operand" "f"))
1543                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1544   "TARGET_ARM && TARGET_HARD_FLOAT"
1545   "rmf%?d\\t%0, %1, %2"
1546   [(set_attr "type" "fdivd")
1547    (set_attr "predicable" "yes")]
1548 )
1549
1550 (define_insn "*moddf_df_esfdf"
1551   [(set (match_operand:DF 0 "s_register_operand" "=f")
1552         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1553                 (float_extend:DF
1554                  (match_operand:SF 2 "s_register_operand" "f"))))]
1555   "TARGET_ARM && TARGET_HARD_FLOAT"
1556   "rmf%?d\\t%0, %1, %2"
1557   [(set_attr "type" "fdivd")
1558    (set_attr "predicable" "yes")]
1559 )
1560
1561 (define_insn "*moddf_esfdf_esfdf"
1562   [(set (match_operand:DF 0 "s_register_operand" "=f")
1563         (mod:DF (float_extend:DF
1564                  (match_operand:SF 1 "s_register_operand" "f"))
1565                 (float_extend:DF
1566                  (match_operand:SF 2 "s_register_operand" "f"))))]
1567   "TARGET_ARM && TARGET_HARD_FLOAT"
1568   "rmf%?d\\t%0, %1, %2"
1569   [(set_attr "type" "fdivd")
1570    (set_attr "predicable" "yes")]
1571 )
1572 \f
1573 ;; Boolean and,ior,xor insns
1574
1575 ;; Split up double word logical operations
1576
1577 ;; Split up simple DImode logical operations.  Simply perform the logical
1578 ;; operation on the upper and lower halves of the registers.
1579 (define_split
1580   [(set (match_operand:DI 0 "s_register_operand" "")
1581         (match_operator:DI 6 "logical_binary_operator"
1582           [(match_operand:DI 1 "s_register_operand" "")
1583            (match_operand:DI 2 "s_register_operand" "")]))]
1584   "TARGET_ARM && reload_completed"
1585   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1586    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1587   "
1588   {
1589     operands[3] = gen_highpart (SImode, operands[0]);
1590     operands[0] = gen_lowpart (SImode, operands[0]);
1591     operands[4] = gen_highpart (SImode, operands[1]);
1592     operands[1] = gen_lowpart (SImode, operands[1]);
1593     operands[5] = gen_highpart (SImode, operands[2]);
1594     operands[2] = gen_lowpart (SImode, operands[2]);
1595   }"
1596 )
1597
1598 (define_split
1599   [(set (match_operand:DI 0 "s_register_operand" "")
1600         (match_operator:DI 6 "logical_binary_operator"
1601           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1602            (match_operand:DI 1 "s_register_operand" "")]))]
1603   "TARGET_ARM && reload_completed"
1604   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1605    (set (match_dup 3) (match_op_dup:SI 6
1606                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1607                          (match_dup 4)]))]
1608   "
1609   {
1610     operands[3] = gen_highpart (SImode, operands[0]);
1611     operands[0] = gen_lowpart (SImode, operands[0]);
1612     operands[4] = gen_highpart (SImode, operands[1]);
1613     operands[1] = gen_lowpart (SImode, operands[1]);
1614     operands[5] = gen_highpart (SImode, operands[2]);
1615     operands[2] = gen_lowpart (SImode, operands[2]);
1616   }"
1617 )
1618
1619 ;; The zero extend of operand 2 means we can just copy the high part of
1620 ;; operand1 into operand0.
1621 (define_split
1622   [(set (match_operand:DI 0 "s_register_operand" "")
1623         (ior:DI
1624           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1625           (match_operand:DI 1 "s_register_operand" "")))]
1626   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1627   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1628    (set (match_dup 3) (match_dup 4))]
1629   "
1630   {
1631     operands[4] = gen_highpart (SImode, operands[1]);
1632     operands[3] = gen_highpart (SImode, operands[0]);
1633     operands[0] = gen_lowpart (SImode, operands[0]);
1634     operands[1] = gen_lowpart (SImode, operands[1]);
1635   }"
1636 )
1637
1638 ;; The zero extend of operand 2 means we can just copy the high part of
1639 ;; operand1 into operand0.
1640 (define_split
1641   [(set (match_operand:DI 0 "s_register_operand" "")
1642         (xor:DI
1643           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1644           (match_operand:DI 1 "s_register_operand" "")))]
1645   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1646   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1647    (set (match_dup 3) (match_dup 4))]
1648   "
1649   {
1650     operands[4] = gen_highpart (SImode, operands[1]);
1651     operands[3] = gen_highpart (SImode, operands[0]);
1652     operands[0] = gen_lowpart (SImode, operands[0]);
1653     operands[1] = gen_lowpart (SImode, operands[1]);
1654   }"
1655 )
1656
1657 (define_insn "anddi3"
1658   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1659         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1660                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1661   "TARGET_ARM"
1662   "#"
1663   [(set_attr "length" "8")]
1664 )
1665
1666 (define_insn_and_split "*anddi_zesidi_di"
1667   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1668         (and:DI (zero_extend:DI
1669                  (match_operand:SI 2 "s_register_operand" "r,r"))
1670                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1671   "TARGET_ARM"
1672   "#"
1673   "TARGET_ARM && reload_completed"
1674   ; The zero extend of operand 2 clears the high word of the output
1675   ; operand.
1676   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1677    (set (match_dup 3) (const_int 0))]
1678   "
1679   {
1680     operands[3] = gen_highpart (SImode, operands[0]);
1681     operands[0] = gen_lowpart (SImode, operands[0]);
1682     operands[1] = gen_lowpart (SImode, operands[1]);
1683   }"
1684   [(set_attr "length" "8")]
1685 )
1686
1687 (define_insn "*anddi_sesdi_di"
1688   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1689         (and:DI (sign_extend:DI
1690                  (match_operand:SI 2 "s_register_operand" "r,r"))
1691                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1692   "TARGET_ARM"
1693   "#"
1694   [(set_attr "length" "8")]
1695 )
1696
1697 (define_expand "andsi3"
1698   [(set (match_operand:SI         0 "s_register_operand" "")
1699         (and:SI (match_operand:SI 1 "s_register_operand" "")
1700                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1701   "TARGET_EITHER"
1702   "
1703   if (TARGET_ARM)
1704     {
1705       if (GET_CODE (operands[2]) == CONST_INT)
1706         {
1707           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1708                               operands[1],
1709                               (no_new_pseudos
1710                                ? 0 : preserve_subexpressions_p ()));
1711           DONE;
1712         }
1713     }
1714   else /* TARGET_THUMB */
1715     {
1716       if (GET_CODE (operands[2]) != CONST_INT)
1717         operands[2] = force_reg (SImode, operands[2]);
1718       else
1719         {
1720           int i;
1721           
1722           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1723             {
1724               operands[2] = force_reg (SImode,
1725                                        GEN_INT (~INTVAL (operands[2])));
1726               
1727               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1728               
1729               DONE;
1730             }
1731
1732           for (i = 9; i <= 31; i++)
1733             {
1734               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1735                 {
1736                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1737                                         const0_rtx));
1738                   DONE;
1739                 }
1740               else if ((((HOST_WIDE_INT) 1) << i) - 1
1741                        == ~INTVAL (operands[2]))
1742                 {
1743                   rtx shift = GEN_INT (i);
1744                   rtx reg = gen_reg_rtx (SImode);
1745                 
1746                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1747                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1748                   
1749                   DONE;
1750                 }
1751             }
1752
1753           operands[2] = force_reg (SImode, operands[2]);
1754         }
1755     }
1756   "
1757 )
1758
1759 (define_insn_and_split "*arm_andsi3_insn"
1760   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1761         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1762                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1763   "TARGET_ARM"
1764   "@
1765    and%?\\t%0, %1, %2
1766    bic%?\\t%0, %1, #%B2
1767    #"
1768   "TARGET_ARM
1769    && GET_CODE (operands[2]) == CONST_INT
1770    && !(const_ok_for_arm (INTVAL (operands[2]))
1771         || const_ok_for_arm (~INTVAL (operands[2])))"
1772   [(clobber (const_int 0))]
1773   "
1774   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1775                        operands[1], 0);
1776   DONE;
1777   "
1778   [(set_attr "length" "4,4,16")
1779    (set_attr "predicable" "yes")]
1780 )
1781
1782 (define_insn "*thumb_andsi3_insn"
1783   [(set (match_operand:SI         0 "register_operand" "=l")
1784         (and:SI (match_operand:SI 1 "register_operand" "%0")
1785                 (match_operand:SI 2 "register_operand" "l")))]
1786   "TARGET_THUMB"
1787   "and\\t%0, %0, %2"
1788   [(set_attr "length" "2")]
1789 )
1790
1791 (define_insn "*andsi3_compare0"
1792   [(set (reg:CC_NOOV CC_REGNUM)
1793         (compare:CC_NOOV
1794          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1795                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1796          (const_int 0)))
1797    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1798         (and:SI (match_dup 1) (match_dup 2)))]
1799   "TARGET_ARM"
1800   "@
1801    and%?s\\t%0, %1, %2
1802    bic%?s\\t%0, %1, #%B2"
1803   [(set_attr "conds" "set")]
1804 )
1805
1806 (define_insn "*andsi3_compare0_scratch"
1807   [(set (reg:CC_NOOV CC_REGNUM)
1808         (compare:CC_NOOV
1809          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1810                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1811          (const_int 0)))
1812    (clobber (match_scratch:SI 2 "=X,r"))]
1813   "TARGET_ARM"
1814   "@
1815    tst%?\\t%0, %1
1816    bic%?s\\t%2, %0, #%B1"
1817   [(set_attr "conds" "set")]
1818 )
1819
1820 (define_insn "*zeroextractsi_compare0_scratch"
1821   [(set (reg:CC_NOOV CC_REGNUM)
1822         (compare:CC_NOOV (zero_extract:SI
1823                           (match_operand:SI 0 "s_register_operand" "r")
1824                           (match_operand 1 "const_int_operand" "n")
1825                           (match_operand 2 "const_int_operand" "n"))
1826                          (const_int 0)))]
1827   "TARGET_ARM
1828   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1829       && INTVAL (operands[1]) > 0 
1830       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1831       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1832   "*
1833   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1834                          << INTVAL (operands[2]));
1835   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1836   return \"\";
1837   "
1838   [(set_attr "conds" "set")]
1839 )
1840
1841 (define_insn "*ne_zeroextractsi"
1842   [(set (match_operand:SI 0 "s_register_operand" "=r")
1843         (ne:SI (zero_extract:SI
1844                 (match_operand:SI 1 "s_register_operand" "r")
1845                 (match_operand:SI 2 "const_int_operand" "n")
1846                 (match_operand:SI 3 "const_int_operand" "n"))
1847                (const_int 0)))
1848    (clobber (reg:CC CC_REGNUM))]
1849   "TARGET_ARM
1850    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1851        && INTVAL (operands[2]) > 0 
1852        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1853        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1854   "*
1855   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1856                          << INTVAL (operands[3]));
1857   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1858   return \"movne\\t%0, #1\";
1859   "
1860   [(set_attr "conds" "clob")
1861    (set_attr "length" "8")]
1862 )
1863
1864 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1865 ;;; represented by the bitfield, then this will produce incorrect results.
1866 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1867 ;;; which have a real bit-field insert instruction, the truncation happens
1868 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1869 ;;; bit-field insert instruction, we would have to emit code here to truncate
1870 ;;; the value before we insert.  This loses some of the advantage of having
1871 ;;; this insv pattern, so this pattern needs to be reevalutated.
1872
1873 (define_expand "insv"
1874   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1875                          (match_operand:SI 1 "general_operand" "")
1876                          (match_operand:SI 2 "general_operand" ""))
1877         (match_operand:SI 3 "reg_or_int_operand" ""))]
1878   "TARGET_ARM"
1879   "
1880   {
1881     int start_bit = INTVAL (operands[2]);
1882     int width = INTVAL (operands[1]);
1883     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1884     rtx target, subtarget;
1885
1886     target = operands[0];
1887     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1888        subreg as the final target.  */
1889     if (GET_CODE (target) == SUBREG)
1890       {
1891         subtarget = gen_reg_rtx (SImode);
1892         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1893             < GET_MODE_SIZE (SImode))
1894           target = SUBREG_REG (target);
1895       }
1896     else
1897       subtarget = target;    
1898
1899     if (GET_CODE (operands[3]) == CONST_INT)
1900       {
1901         /* Since we are inserting a known constant, we may be able to
1902            reduce the number of bits that we have to clear so that
1903            the mask becomes simple.  */
1904         /* ??? This code does not check to see if the new mask is actually
1905            simpler.  It may not be.  */
1906         rtx op1 = gen_reg_rtx (SImode);
1907         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1908            start of this pattern.  */
1909         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1910         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1911
1912         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1913         emit_insn (gen_iorsi3 (subtarget, op1,
1914                                GEN_INT (op3_value << start_bit)));
1915       }
1916     else if (start_bit == 0
1917              && !(const_ok_for_arm (mask)
1918                   || const_ok_for_arm (~mask)))
1919       {
1920         /* A Trick, since we are setting the bottom bits in the word,
1921            we can shift operand[3] up, operand[0] down, OR them together
1922            and rotate the result back again.  This takes 3 insns, and
1923            the third might be mergable into another op.  */
1924         /* The shift up copes with the possibility that operand[3] is
1925            wider than the bitfield.  */
1926         rtx op0 = gen_reg_rtx (SImode);
1927         rtx op1 = gen_reg_rtx (SImode);
1928
1929         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1930         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1931         emit_insn (gen_iorsi3  (op1, op1, op0));
1932         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1933       }
1934     else if ((width + start_bit == 32)
1935              && !(const_ok_for_arm (mask)
1936                   || const_ok_for_arm (~mask)))
1937       {
1938         /* Similar trick, but slightly less efficient.  */
1939
1940         rtx op0 = gen_reg_rtx (SImode);
1941         rtx op1 = gen_reg_rtx (SImode);
1942
1943         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1944         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1945         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1946         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1947       }
1948     else
1949       {
1950         rtx op0 = GEN_INT (mask);
1951         rtx op1 = gen_reg_rtx (SImode);
1952         rtx op2 = gen_reg_rtx (SImode);
1953
1954         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1955           {
1956             rtx tmp = gen_reg_rtx (SImode);
1957
1958             emit_insn (gen_movsi (tmp, op0));
1959             op0 = tmp;
1960           }
1961
1962         /* Mask out any bits in operand[3] that are not needed.  */
1963            emit_insn (gen_andsi3 (op1, operands[3], op0));
1964
1965         if (GET_CODE (op0) == CONST_INT
1966             && (const_ok_for_arm (mask << start_bit)
1967                 || const_ok_for_arm (~(mask << start_bit))))
1968           {
1969             op0 = GEN_INT (~(mask << start_bit));
1970             emit_insn (gen_andsi3 (op2, operands[0], op0));
1971           }
1972         else
1973           {
1974             if (GET_CODE (op0) == CONST_INT)
1975               {
1976                 rtx tmp = gen_reg_rtx (SImode);
1977
1978                 emit_insn (gen_movsi (tmp, op0));
1979                 op0 = tmp;
1980               }
1981
1982             if (start_bit != 0)
1983               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1984             
1985             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1986           }
1987
1988         if (start_bit != 0)
1989           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1990
1991         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1992       }
1993
1994     if (subtarget != target)
1995       {
1996         /* If TARGET is still a SUBREG, then it must be wider than a word,
1997            so we must be careful only to set the subword we were asked to.  */
1998         if (GET_CODE (target) == SUBREG)
1999           emit_move_insn (target, subtarget);
2000         else
2001           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2002       }
2003
2004     DONE;
2005   }"
2006 )
2007
2008 ; constants for op 2 will never be given to these patterns.
2009 (define_insn_and_split "*anddi_notdi_di"
2010   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2011         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2012                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2013   "TARGET_ARM"
2014   "#"
2015   "TARGET_ARM && reload_completed"
2016   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2017    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2018   "
2019   {
2020     operands[3] = gen_highpart (SImode, operands[0]);
2021     operands[0] = gen_lowpart (SImode, operands[0]);
2022     operands[4] = gen_highpart (SImode, operands[1]);
2023     operands[1] = gen_lowpart (SImode, operands[1]);
2024     operands[5] = gen_highpart (SImode, operands[2]);
2025     operands[2] = gen_lowpart (SImode, operands[2]);
2026   }"
2027   [(set_attr "length" "8")
2028    (set_attr "predicable" "yes")]
2029 )
2030   
2031 (define_insn_and_split "*anddi_notzesidi_di"
2032   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2033         (and:DI (not:DI (zero_extend:DI
2034                          (match_operand:SI 2 "s_register_operand" "r,r")))
2035                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2036   "TARGET_ARM"
2037   "@
2038    bic%?\\t%Q0, %Q1, %2
2039    #"
2040   ; (not (zero_extend ...)) allows us to just copy the high word from
2041   ; operand1 to operand0.
2042   "TARGET_ARM
2043    && reload_completed
2044    && operands[0] != operands[1]"
2045   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2046    (set (match_dup 3) (match_dup 4))]
2047   "
2048   {
2049     operands[3] = gen_highpart (SImode, operands[0]);
2050     operands[0] = gen_lowpart (SImode, operands[0]);
2051     operands[4] = gen_highpart (SImode, operands[1]);
2052     operands[1] = gen_lowpart (SImode, operands[1]);
2053   }"
2054   [(set_attr "length" "4,8")
2055    (set_attr "predicable" "yes")]
2056 )
2057   
2058 (define_insn_and_split "*anddi_notsesidi_di"
2059   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2060         (and:DI (not:DI (sign_extend:DI
2061                          (match_operand:SI 2 "s_register_operand" "r,r")))
2062                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2063   "TARGET_ARM"
2064   "#"
2065   "TARGET_ARM && reload_completed"
2066   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2067    (set (match_dup 3) (and:SI (not:SI
2068                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2069                                (match_dup 4)))]
2070   "
2071   {
2072     operands[3] = gen_highpart (SImode, operands[0]);
2073     operands[0] = gen_lowpart (SImode, operands[0]);
2074     operands[4] = gen_highpart (SImode, operands[1]);
2075     operands[1] = gen_lowpart (SImode, operands[1]);
2076   }"
2077   [(set_attr "length" "8")
2078    (set_attr "predicable" "yes")]
2079 )
2080   
2081 (define_insn "andsi_notsi_si"
2082   [(set (match_operand:SI 0 "s_register_operand" "=r")
2083         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2084                 (match_operand:SI 1 "s_register_operand" "r")))]
2085   "TARGET_ARM"
2086   "bic%?\\t%0, %1, %2"
2087   [(set_attr "predicable" "yes")]
2088 )
2089
2090 (define_insn "bicsi3"
2091   [(set (match_operand:SI                 0 "register_operand" "=l")
2092         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2093                 (match_operand:SI         2 "register_operand" "0")))]
2094   "TARGET_THUMB"
2095   "bic\\t%0, %0, %1"
2096   [(set_attr "length" "2")]
2097 )
2098
2099 (define_insn "andsi_not_shiftsi_si"
2100   [(set (match_operand:SI                   0 "s_register_operand" "=r")
2101         (and:SI (not:SI (match_operator:SI  4 "shift_operator"
2102                          [(match_operand:SI 2 "s_register_operand"  "r")
2103                           (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2104                 (match_operand:SI           1 "s_register_operand"  "r")))]
2105   "TARGET_ARM"
2106   "bic%?\\t%0, %1, %2%S4"
2107   [(set_attr "predicable" "yes")
2108    (set_attr "shift" "2")
2109    ]
2110 )
2111
2112 (define_insn "*andsi_notsi_si_compare0"
2113   [(set (reg:CC_NOOV CC_REGNUM)
2114         (compare:CC_NOOV
2115          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2116                  (match_operand:SI 1 "s_register_operand" "r"))
2117          (const_int 0)))
2118    (set (match_operand:SI 0 "s_register_operand" "=r")
2119         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2120   "TARGET_ARM"
2121   "bic%?s\\t%0, %1, %2"
2122   [(set_attr "conds" "set")]
2123 )
2124
2125 (define_insn "*andsi_notsi_si_compare0_scratch"
2126   [(set (reg:CC_NOOV CC_REGNUM)
2127         (compare:CC_NOOV
2128          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2129                  (match_operand:SI 1 "s_register_operand" "r"))
2130          (const_int 0)))
2131    (clobber (match_scratch:SI 0 "=r"))]
2132   "TARGET_ARM"
2133   "bic%?s\\t%0, %1, %2"
2134   [(set_attr "conds" "set")]
2135 )
2136
2137 (define_insn "iordi3"
2138   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2139         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2140                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2141   "TARGET_ARM"
2142   "#"
2143   [(set_attr "length" "8")
2144    (set_attr "predicable" "yes")]
2145 )
2146
2147 (define_insn "*iordi_zesidi_di"
2148   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2149         (ior:DI (zero_extend:DI
2150                  (match_operand:SI 2 "s_register_operand" "r,r"))
2151                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2152   "TARGET_ARM"
2153   "@
2154    orr%?\\t%Q0, %Q1, %2
2155    #"
2156   [(set_attr "length" "4,8")
2157    (set_attr "predicable" "yes")]
2158 )
2159
2160 (define_insn "*iordi_sesidi_di"
2161   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2162         (ior:DI (sign_extend:DI
2163                  (match_operand:SI 2 "s_register_operand" "r,r"))
2164                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2165   "TARGET_ARM"
2166   "#"
2167   [(set_attr "length" "8")
2168    (set_attr "predicable" "yes")]
2169 )
2170
2171 (define_expand "iorsi3"
2172   [(set (match_operand:SI         0 "s_register_operand" "")
2173         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2174                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2175   "TARGET_EITHER"
2176   "
2177   if (GET_CODE (operands[2]) == CONST_INT)
2178     {
2179       if (TARGET_ARM)
2180         {
2181           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2182                               operands[1],
2183                               (no_new_pseudos
2184                               ? 0 : preserve_subexpressions_p ()));
2185           DONE;
2186         }
2187       else /* TARGET_THUMB */
2188         operands [2] = force_reg (SImode, operands [2]);
2189     }
2190   "
2191 )
2192
2193 (define_insn_and_split "*arm_iorsi3"
2194   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2195         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2196                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2197   "TARGET_ARM"
2198   "@
2199    orr%?\\t%0, %1, %2
2200    #"
2201   "TARGET_ARM
2202    && GET_CODE (operands[2]) == CONST_INT
2203    && !const_ok_for_arm (INTVAL (operands[2]))"
2204   [(clobber (const_int 0))]
2205   "
2206   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2207                       operands[1], 0);
2208   DONE;
2209   "
2210   [(set_attr "length" "4,16")
2211    (set_attr "predicable" "yes")]
2212 )
2213
2214 (define_insn "*thumb_iorsi3"
2215   [(set (match_operand:SI         0 "register_operand" "=l")
2216         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2217                 (match_operand:SI 2 "register_operand" "l")))]
2218   "TARGET_THUMB"
2219   "orr\\t%0, %0, %2"
2220   [(set_attr "length" "2")]
2221 )
2222
2223 (define_peephole2
2224   [(match_scratch:SI 3 "r")
2225    (set (match_operand:SI         0 "s_register_operand" "")
2226         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2227                 (match_operand:SI 2 "const_int_operand" "")))]
2228   "TARGET_ARM
2229    && !const_ok_for_arm (INTVAL (operands[2]))
2230    && const_ok_for_arm (~INTVAL (operands[2]))"
2231   [(set (match_dup 3) (match_dup 2))
2232    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2233   ""
2234 )
2235
2236 (define_insn "*iorsi3_compare0"
2237   [(set (reg:CC_NOOV CC_REGNUM)
2238         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2239                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2240                          (const_int 0)))
2241    (set (match_operand:SI 0 "s_register_operand" "=r")
2242         (ior:SI (match_dup 1) (match_dup 2)))]
2243   "TARGET_ARM"
2244   "orr%?s\\t%0, %1, %2"
2245   [(set_attr "conds" "set")]
2246 )
2247
2248 (define_insn "*iorsi3_compare0_scratch"
2249   [(set (reg:CC_NOOV CC_REGNUM)
2250         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2251                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2252                          (const_int 0)))
2253    (clobber (match_scratch:SI 0 "=r"))]
2254   "TARGET_ARM"
2255   "orr%?s\\t%0, %1, %2"
2256   [(set_attr "conds" "set")]
2257 )
2258
2259 (define_insn "xordi3"
2260   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2261         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2262                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2263   "TARGET_ARM"
2264   "#"
2265   [(set_attr "length" "8")
2266    (set_attr "predicable" "yes")]
2267 )
2268
2269 (define_insn "*xordi_zesidi_di"
2270   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2271         (xor:DI (zero_extend:DI
2272                  (match_operand:SI 2 "s_register_operand" "r,r"))
2273                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2274   "TARGET_ARM"
2275   "@
2276    eor%?\\t%Q0, %Q1, %2
2277    #"
2278   [(set_attr "length" "4,8")
2279    (set_attr "predicable" "yes")]
2280 )
2281
2282 (define_insn "*xordi_sesidi_di"
2283   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2284         (xor:DI (sign_extend:DI
2285                  (match_operand:SI 2 "s_register_operand" "r,r"))
2286                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2287   "TARGET_ARM"
2288   "#"
2289   [(set_attr "length" "8")
2290    (set_attr "predicable" "yes")]
2291 )
2292
2293 (define_expand "xorsi3"
2294   [(set (match_operand:SI         0 "s_register_operand" "")
2295         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2296                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2297   "TARGET_EITHER"
2298   "if (TARGET_THUMB)
2299      if (GET_CODE (operands[2]) == CONST_INT)
2300        operands[2] = force_reg (SImode, operands[2]);
2301   "
2302 )
2303
2304 (define_insn "*arm_xorsi3"
2305   [(set (match_operand:SI         0 "s_register_operand" "=r")
2306         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2307                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2308   "TARGET_ARM"
2309   "eor%?\\t%0, %1, %2"
2310   [(set_attr "predicable" "yes")]
2311 )
2312
2313 (define_insn "*thumb_xorsi3"
2314   [(set (match_operand:SI         0 "register_operand" "=l")
2315         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2316                 (match_operand:SI 2 "register_operand" "l")))]
2317   "TARGET_THUMB"
2318   "eor\\t%0, %0, %2"
2319   [(set_attr "length" "2")]
2320 )
2321
2322 (define_insn "*xorsi3_compare0"
2323   [(set (reg:CC_NOOV CC_REGNUM)
2324         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2325                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2326                          (const_int 0)))
2327    (set (match_operand:SI 0 "s_register_operand" "=r")
2328         (xor:SI (match_dup 1) (match_dup 2)))]
2329   "TARGET_ARM"
2330   "eor%?s\\t%0, %1, %2"
2331   [(set_attr "conds" "set")]
2332 )
2333
2334 (define_insn "*xorsi3_compare0_scratch"
2335   [(set (reg:CC_NOOV CC_REGNUM)
2336         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2337                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2338                          (const_int 0)))]
2339   "TARGET_ARM"
2340   "teq%?\\t%0, %1"
2341   [(set_attr "conds" "set")]
2342 )
2343
2344 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2345 ; (NOT D) we can sometimes merge the final NOT into one of the following
2346 ; insns.
2347
2348 (define_split
2349   [(set (match_operand:SI 0 "s_register_operand" "")
2350         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2351                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2352                 (match_operand:SI 3 "arm_rhs_operand" "")))
2353    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2354   "TARGET_ARM"
2355   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2356                               (not:SI (match_dup 3))))
2357    (set (match_dup 0) (not:SI (match_dup 4)))]
2358   ""
2359 )
2360
2361 (define_insn "*andsi_iorsi3_notsi"
2362   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2363         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2364                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2365                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2366   "TARGET_ARM"
2367   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2368   [(set_attr "length" "8")
2369    (set_attr "predicable" "yes")]
2370 )
2371
2372 \f
2373
2374 ;; Minimum and maximum insns
2375
2376 (define_insn "smaxsi3"
2377   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2378         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2379                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2380    (clobber (reg:CC CC_REGNUM))]
2381   "TARGET_ARM"
2382   "@
2383    cmp\\t%1, %2\;movlt\\t%0, %2
2384    cmp\\t%1, %2\;movge\\t%0, %1
2385    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2386   [(set_attr "conds" "clob")
2387    (set_attr "length" "8,8,12")]
2388 )
2389
2390 (define_insn "sminsi3"
2391   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2392         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2393                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2394    (clobber (reg:CC CC_REGNUM))]
2395   "TARGET_ARM"
2396   "@
2397    cmp\\t%1, %2\;movge\\t%0, %2
2398    cmp\\t%1, %2\;movlt\\t%0, %1
2399    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2400   [(set_attr "conds" "clob")
2401    (set_attr "length" "8,8,12")]
2402 )
2403
2404 (define_insn "umaxsi3"
2405   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2406         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2407                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2408    (clobber (reg:CC CC_REGNUM))]
2409   "TARGET_ARM"
2410   "@
2411    cmp\\t%1, %2\;movcc\\t%0, %2
2412    cmp\\t%1, %2\;movcs\\t%0, %1
2413    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2414   [(set_attr "conds" "clob")
2415    (set_attr "length" "8,8,12")]
2416 )
2417
2418 (define_insn "uminsi3"
2419   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2420         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2421                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2422    (clobber (reg:CC CC_REGNUM))]
2423   "TARGET_ARM"
2424   "@
2425    cmp\\t%1, %2\;movcs\\t%0, %2
2426    cmp\\t%1, %2\;movcc\\t%0, %1
2427    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2428   [(set_attr "conds" "clob")
2429    (set_attr "length" "8,8,12")]
2430 )
2431
2432 (define_insn "*store_minmaxsi"
2433   [(set (match_operand:SI 0 "memory_operand" "=m")
2434         (match_operator:SI 3 "minmax_operator"
2435          [(match_operand:SI 1 "s_register_operand" "r")
2436           (match_operand:SI 2 "s_register_operand" "r")]))
2437    (clobber (reg:CC CC_REGNUM))]
2438   "TARGET_ARM"
2439   "*
2440   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2441                          operands[2]);
2442   output_asm_insn (\"cmp\\t%1, %2\", operands);
2443   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2444   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2445   return \"\";
2446   "
2447   [(set_attr "conds" "clob")
2448    (set_attr "length" "12")
2449    (set_attr "type" "store1")]
2450 )
2451
2452 ; Reject the frame pointer in operand[1], since reloading this after
2453 ; it has been eliminated can cause carnage.
2454 (define_insn "*minmax_arithsi"
2455   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2456         (match_operator:SI 4 "shiftable_operator"
2457          [(match_operator:SI 5 "minmax_operator"
2458            [(match_operand:SI 2 "s_register_operand" "r,r")
2459             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2460           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2461    (clobber (reg:CC CC_REGNUM))]
2462   "TARGET_ARM
2463    && (GET_CODE (operands[1]) != REG
2464        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2465            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2466   "*
2467   {
2468     enum rtx_code code = GET_CODE (operands[4]);
2469
2470     operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2471                            operands[3]);
2472     output_asm_insn (\"cmp\\t%2, %3\", operands);
2473     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2474     if (which_alternative != 0 || operands[3] != const0_rtx
2475         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2476       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2477     return \"\";
2478   }"
2479   [(set_attr "conds" "clob")
2480    (set_attr "length" "12")]
2481 )
2482
2483 \f
2484 ;; Shift and rotation insns
2485
2486 (define_expand "ashlsi3"
2487   [(set (match_operand:SI            0 "s_register_operand" "")
2488         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2489                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2490   "TARGET_EITHER"
2491   "
2492   if (GET_CODE (operands[2]) == CONST_INT
2493       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2494     {
2495       emit_insn (gen_movsi (operands[0], const0_rtx));
2496       DONE;
2497     }
2498   "
2499 )
2500
2501 (define_insn "*thumb_ashlsi3"
2502   [(set (match_operand:SI            0 "register_operand" "=l,l")
2503         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2504                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2505   "TARGET_THUMB"
2506   "lsl\\t%0, %1, %2"
2507   [(set_attr "length" "2")]
2508 )
2509
2510 (define_expand "ashrsi3"
2511   [(set (match_operand:SI              0 "s_register_operand" "")
2512         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2513                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2514   "TARGET_EITHER"
2515   "
2516   if (GET_CODE (operands[2]) == CONST_INT
2517       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2518     operands[2] = GEN_INT (31);
2519   "
2520 )
2521
2522 (define_insn "*thumb_ashrsi3"
2523   [(set (match_operand:SI              0 "register_operand" "=l,l")
2524         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2525                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2526   "TARGET_THUMB"
2527   "asr\\t%0, %1, %2"
2528   [(set_attr "length" "2")]
2529 )
2530
2531 (define_expand "lshrsi3"
2532   [(set (match_operand:SI              0 "s_register_operand" "")
2533         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2534                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2535   "TARGET_EITHER"
2536   "
2537   if (GET_CODE (operands[2]) == CONST_INT
2538       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2539     {
2540       emit_insn (gen_movsi (operands[0], const0_rtx));
2541       DONE;
2542     }
2543   "
2544 )
2545
2546 (define_insn "*thumb_lshrsi3"
2547   [(set (match_operand:SI              0 "register_operand" "=l,l")
2548         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2549                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2550   "TARGET_THUMB"
2551   "lsr\\t%0, %1, %2"
2552   [(set_attr "length" "2")]
2553 )
2554
2555 (define_expand "rotlsi3"
2556   [(set (match_operand:SI              0 "s_register_operand" "")
2557         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2558                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2559   "TARGET_ARM"
2560   "
2561   if (GET_CODE (operands[2]) == CONST_INT)
2562     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2563   else
2564     {
2565       rtx reg = gen_reg_rtx (SImode);
2566       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2567       operands[2] = reg;
2568     }
2569   "
2570 )
2571
2572 (define_expand "rotrsi3"
2573   [(set (match_operand:SI              0 "s_register_operand" "")
2574         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2575                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2576   "TARGET_EITHER"
2577   "
2578   if (TARGET_ARM)
2579     {
2580       if (GET_CODE (operands[2]) == CONST_INT
2581           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2582         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2583     }
2584   else /* TARGET_THUMB */
2585     {
2586       if (GET_CODE (operands [2]) == CONST_INT)
2587         operands [2] = force_reg (SImode, operands[2]);
2588     }
2589   "
2590 )
2591
2592 (define_insn "*thumb_rotrsi3"
2593   [(set (match_operand:SI              0 "register_operand" "=l")
2594         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2595                      (match_operand:SI 2 "register_operand" "l")))]
2596   "TARGET_THUMB"
2597   "ror\\t%0, %0, %2"
2598   [(set_attr "length" "2")]
2599 )
2600
2601 (define_expand "ashldi3"
2602   [(set (match_operand:DI            0 "s_register_operand" "")
2603         (ashift:DI (match_operand:DI 1 "general_operand"    "")
2604                    (match_operand:SI 2 "general_operand"    "")))]
2605   "TARGET_ARM && (TARGET_CIRRUS)"
2606   "
2607   if (! s_register_operand (operands[1], DImode))
2608     operands[1] = copy_to_mode_reg (DImode, operands[1]);
2609   if (! s_register_operand (operands[2], SImode))
2610     operands[2] = copy_to_mode_reg (SImode, operands[2]);
2611   "
2612 )
2613
2614 (define_insn "*arm_shiftsi3"
2615   [(set (match_operand:SI   0 "s_register_operand" "=r")
2616         (match_operator:SI  3 "shift_operator"
2617          [(match_operand:SI 1 "s_register_operand"  "r")
2618           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2619   "TARGET_ARM"
2620   "mov%?\\t%0, %1%S3"
2621   [(set_attr "predicable" "yes")
2622    (set_attr "shift" "1")
2623    ]
2624 )
2625
2626 (define_insn "*shiftsi3_compare0"
2627   [(set (reg:CC_NOOV CC_REGNUM)
2628         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2629                           [(match_operand:SI 1 "s_register_operand" "r")
2630                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2631                          (const_int 0)))
2632    (set (match_operand:SI 0 "s_register_operand" "=r")
2633         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2634   "TARGET_ARM"
2635   "mov%?s\\t%0, %1%S3"
2636   [(set_attr "conds" "set")
2637    (set_attr "shift" "1")
2638    ]
2639 )
2640
2641 (define_insn "*shiftsi3_compare0_scratch"
2642   [(set (reg:CC_NOOV CC_REGNUM)
2643         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2644                           [(match_operand:SI 1 "s_register_operand" "r")
2645                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2646                          (const_int 0)))
2647    (clobber (match_scratch:SI 0 "=r"))]
2648   "TARGET_ARM"
2649   "mov%?s\\t%0, %1%S3"
2650   [(set_attr "conds" "set")
2651    (set_attr "shift" "1")
2652    ]
2653 )
2654
2655 (define_insn "*notsi_shiftsi"
2656   [(set (match_operand:SI 0 "s_register_operand" "=r")
2657         (not:SI (match_operator:SI 3 "shift_operator"
2658                  [(match_operand:SI 1 "s_register_operand" "r")
2659                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2660   "TARGET_ARM"
2661   "mvn%?\\t%0, %1%S3"
2662   [(set_attr "predicable" "yes")
2663    (set_attr "shift" "1")
2664    ]
2665 )
2666
2667 (define_insn "*notsi_shiftsi_compare0"
2668   [(set (reg:CC_NOOV CC_REGNUM)
2669         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2670                           [(match_operand:SI 1 "s_register_operand" "r")
2671                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2672                          (const_int 0)))
2673    (set (match_operand:SI 0 "s_register_operand" "=r")
2674         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2675   "TARGET_ARM"
2676   "mvn%?s\\t%0, %1%S3"
2677   [(set_attr "conds" "set")
2678    (set_attr "shift" "1")
2679    ]
2680 )
2681
2682 (define_insn "*not_shiftsi_compare0_scratch"
2683   [(set (reg:CC_NOOV CC_REGNUM)
2684         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2685                           [(match_operand:SI 1 "s_register_operand" "r")
2686                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2687                          (const_int 0)))
2688    (clobber (match_scratch:SI 0 "=r"))]
2689   "TARGET_ARM"
2690   "mvn%?s\\t%0, %1%S3"
2691   [(set_attr "conds" "set")
2692    (set_attr "shift" "1")
2693   ]
2694 )
2695
2696 ;; We don't really have extzv, but defining this using shifts helps
2697 ;; to reduce register pressure later on.
2698
2699 (define_expand "extzv"
2700   [(set (match_dup 4)
2701         (ashift:SI (match_operand:SI   1 "register_operand" "")
2702                    (match_operand:SI   2 "const_int_operand" "")))
2703    (set (match_operand:SI              0 "register_operand" "")
2704         (lshiftrt:SI (match_dup 4)
2705                      (match_operand:SI 3 "const_int_operand" "")))]
2706   "TARGET_THUMB"
2707   "
2708   {
2709     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2710     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2711     
2712     operands[3] = GEN_INT (rshift);
2713     
2714     if (lshift == 0)
2715       {
2716         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2717         DONE;
2718       }
2719       
2720     operands[2] = GEN_INT (lshift);
2721     operands[4] = gen_reg_rtx (SImode);
2722   }"
2723 )
2724
2725 \f
2726 ;; Unary arithmetic insns
2727
2728 (define_expand "negdi2"
2729  [(parallel
2730    [(set (match_operand:DI          0 "s_register_operand" "")
2731           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2732     (clobber (reg:CC CC_REGNUM))])]
2733   "TARGET_EITHER"
2734   "
2735   if (TARGET_THUMB)
2736     {
2737       if (GET_CODE (operands[1]) != REG)
2738         operands[1] = force_reg (SImode, operands[1]);
2739      }
2740   "
2741 )
2742
2743 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2744 ;; The second alternative is to allow the common case of a *full* overlap.
2745 (define_insn "*arm_negdi2"
2746   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2747         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2748    (clobber (reg:CC CC_REGNUM))]
2749   "TARGET_ARM"
2750   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2751   [(set_attr "conds" "clob")
2752    (set_attr "length" "8")]
2753 )
2754
2755 (define_insn "*thumb_negdi2"
2756   [(set (match_operand:DI         0 "register_operand" "=&l")
2757         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2758    (clobber (reg:CC CC_REGNUM))]
2759   "TARGET_THUMB"
2760   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2761   [(set_attr "length" "6")]
2762 )
2763
2764 (define_expand "negsi2"
2765   [(set (match_operand:SI         0 "s_register_operand" "")
2766         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2767   "TARGET_EITHER"
2768   ""
2769 )
2770
2771 (define_insn "*arm_negsi2"
2772   [(set (match_operand:SI         0 "s_register_operand" "=r")
2773         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2774   "TARGET_ARM"
2775   "rsb%?\\t%0, %1, #0"
2776   [(set_attr "predicable" "yes")]
2777 )
2778
2779 (define_insn "*thumb_negsi2"
2780   [(set (match_operand:SI         0 "register_operand" "=l")
2781         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2782   "TARGET_THUMB"
2783   "neg\\t%0, %1"
2784   [(set_attr "length" "2")]
2785 )
2786
2787 (define_insn "*arm_negsf2"
2788   [(set (match_operand:SF         0 "s_register_operand" "=f")
2789         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2790   "TARGET_ARM && TARGET_HARD_FLOAT"
2791   "mnf%?s\\t%0, %1"
2792   [(set_attr "type" "ffarith")
2793    (set_attr "predicable" "yes")]
2794 )
2795
2796 (define_insn "*arm_negdf2"
2797   [(set (match_operand:DF         0 "s_register_operand" "=f")
2798         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2799   "TARGET_ARM && TARGET_HARD_FLOAT"
2800   "mnf%?d\\t%0, %1"
2801   [(set_attr "type" "ffarith")
2802    (set_attr "predicable" "yes")]
2803 )
2804
2805 (define_insn "*negdf_esfdf"
2806   [(set (match_operand:DF 0 "s_register_operand" "=f")
2807         (neg:DF (float_extend:DF
2808                  (match_operand:SF 1 "s_register_operand" "f"))))]
2809   "TARGET_ARM && TARGET_HARD_FLOAT"
2810   "mnf%?d\\t%0, %1"
2811   [(set_attr "type" "ffarith")
2812    (set_attr "predicable" "yes")]
2813 )
2814
2815 ;; abssi2 doesn't really clobber the condition codes if a different register
2816 ;; is being set.  To keep things simple, assume during rtl manipulations that
2817 ;; it does, but tell the final scan operator the truth.  Similarly for
2818 ;; (neg (abs...))
2819
2820 (define_insn "*arm_abssi2"
2821   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2822         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2823    (clobber (reg:CC CC_REGNUM))]
2824   "TARGET_ARM"
2825   "@
2826    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2827    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2828   [(set_attr "conds" "clob,*")
2829    (set_attr "shift" "1")
2830    ;; predicable can't be set based on the variant, so left as no
2831    (set_attr "length" "8")]
2832 )
2833
2834 (define_insn "*neg_abssi2"
2835   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2836         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2837    (clobber (reg:CC CC_REGNUM))]
2838   "TARGET_ARM"
2839   "@
2840    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2841    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2842   [(set_attr "conds" "clob,*")
2843    (set_attr "shift" "1")
2844    ;; predicable can't be set based on the variant, so left as no
2845    (set_attr "length" "8")]
2846 )
2847
2848 (define_insn "*arm_abssf2"
2849   [(set (match_operand:SF          0 "s_register_operand" "=f")
2850          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2851   "TARGET_ARM && TARGET_HARD_FLOAT"
2852   "abs%?s\\t%0, %1"
2853   [(set_attr "type" "ffarith")
2854    (set_attr "predicable" "yes")]
2855 )
2856
2857 (define_insn "*arm_absdf2"
2858   [(set (match_operand:DF         0 "s_register_operand" "=f")
2859         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2860   "TARGET_ARM && TARGET_HARD_FLOAT"
2861   "abs%?d\\t%0, %1"
2862   [(set_attr "type" "ffarith")
2863    (set_attr "predicable" "yes")]
2864 )
2865
2866 (define_insn "*absdf_esfdf"
2867   [(set (match_operand:DF 0 "s_register_operand" "=f")
2868         (abs:DF (float_extend:DF
2869                  (match_operand:SF 1 "s_register_operand" "f"))))]
2870   "TARGET_ARM && TARGET_HARD_FLOAT"
2871   "abs%?d\\t%0, %1"
2872   [(set_attr "type" "ffarith")
2873    (set_attr "predicable" "yes")]
2874 )
2875
2876 (define_insn "sqrtsf2"
2877   [(set (match_operand:SF 0 "s_register_operand" "=f")
2878         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2879   "TARGET_ARM && TARGET_HARD_FLOAT"
2880   "sqt%?s\\t%0, %1"
2881   [(set_attr "type" "float_em")
2882    (set_attr "predicable" "yes")]
2883 )
2884
2885 (define_insn "sqrtdf2"
2886   [(set (match_operand:DF 0 "s_register_operand" "=f")
2887         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2888   "TARGET_ARM && TARGET_HARD_FLOAT"
2889   "sqt%?d\\t%0, %1"
2890   [(set_attr "type" "float_em")
2891    (set_attr "predicable" "yes")]
2892 )
2893
2894 (define_insn "*sqrtdf_esfdf"
2895   [(set (match_operand:DF 0 "s_register_operand" "=f")
2896         (sqrt:DF (float_extend:DF
2897                   (match_operand:SF 1 "s_register_operand" "f"))))]
2898   "TARGET_ARM && TARGET_HARD_FLOAT"
2899   "sqt%?d\\t%0, %1"
2900   [(set_attr "type" "float_em")
2901    (set_attr "predicable" "yes")]
2902 )
2903
2904 (define_insn_and_split "one_cmpldi2"
2905   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2906         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2907   "TARGET_ARM"
2908   "#"
2909   "TARGET_ARM && reload_completed"
2910   [(set (match_dup 0) (not:SI (match_dup 1)))
2911    (set (match_dup 2) (not:SI (match_dup 3)))]
2912   "
2913   {
2914     operands[2] = gen_highpart (SImode, operands[0]);
2915     operands[0] = gen_lowpart (SImode, operands[0]);
2916     operands[3] = gen_highpart (SImode, operands[1]);
2917     operands[1] = gen_lowpart (SImode, operands[1]);
2918   }"
2919   [(set_attr "length" "8")
2920    (set_attr "predicable" "yes")]
2921 )
2922
2923 (define_expand "one_cmplsi2"
2924   [(set (match_operand:SI         0 "s_register_operand" "")
2925         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2926   "TARGET_EITHER"
2927   ""
2928 )
2929
2930 (define_insn "*arm_one_cmplsi2"
2931   [(set (match_operand:SI         0 "s_register_operand" "=r")
2932         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2933   "TARGET_ARM"
2934   "mvn%?\\t%0, %1"
2935   [(set_attr "predicable" "yes")]
2936 )
2937
2938 (define_insn "*thumb_one_cmplsi2"
2939   [(set (match_operand:SI         0 "register_operand" "=l")
2940         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
2941   "TARGET_THUMB"
2942   "mvn\\t%0, %1"
2943   [(set_attr "length" "2")]
2944 )
2945
2946 (define_insn "*notsi_compare0"
2947   [(set (reg:CC_NOOV CC_REGNUM)
2948         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2949                          (const_int 0)))
2950    (set (match_operand:SI 0 "s_register_operand" "=r")
2951         (not:SI (match_dup 1)))]
2952   "TARGET_ARM"
2953   "mvn%?s\\t%0, %1"
2954   [(set_attr "conds" "set")]
2955 )
2956
2957 (define_insn "*notsi_compare0_scratch"
2958   [(set (reg:CC_NOOV CC_REGNUM)
2959         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2960                          (const_int 0)))
2961    (clobber (match_scratch:SI 0 "=r"))]
2962   "TARGET_ARM"
2963   "mvn%?s\\t%0, %1"
2964   [(set_attr "conds" "set")]
2965 )
2966 \f
2967 ;; Fixed <--> Floating conversion insns
2968
2969 (define_insn "*arm_floatsisf2"
2970   [(set (match_operand:SF           0 "s_register_operand" "=f")
2971         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2972   "TARGET_ARM && TARGET_HARD_FLOAT"
2973   "flt%?s\\t%0, %1"
2974   [(set_attr "type" "r_2_f")
2975    (set_attr "predicable" "yes")]
2976 )
2977
2978 (define_insn "*arm_floatsidf2"
2979   [(set (match_operand:DF           0 "s_register_operand" "=f")
2980         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2981   "TARGET_ARM && TARGET_HARD_FLOAT"
2982   "flt%?d\\t%0, %1"
2983   [(set_attr "type" "r_2_f")
2984    (set_attr "predicable" "yes")]
2985 )
2986
2987 (define_insn "*arm_fix_truncsfsi2"
2988   [(set (match_operand:SI         0 "s_register_operand" "=r")
2989         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2990   "TARGET_ARM && TARGET_HARD_FLOAT"
2991   "fix%?z\\t%0, %1"
2992   [(set_attr "type" "f_2_r")
2993    (set_attr "predicable" "yes")]
2994 )
2995
2996 (define_insn "*arm_fix_truncdfsi2"
2997   [(set (match_operand:SI         0 "s_register_operand" "=r")
2998         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2999   "TARGET_ARM && TARGET_HARD_FLOAT"
3000   "fix%?z\\t%0, %1"
3001   [(set_attr "type" "f_2_r")
3002    (set_attr "predicable" "yes")]
3003 )
3004
3005 ;; Truncation insns
3006
3007 (define_insn "*arm_truncdfsf2"
3008   [(set (match_operand:SF 0 "s_register_operand" "=f")
3009         (float_truncate:SF
3010          (match_operand:DF 1 "s_register_operand" "f")))]
3011   "TARGET_ARM && TARGET_HARD_FLOAT"
3012   "mvf%?s\\t%0, %1"
3013   [(set_attr "type" "ffarith")
3014    (set_attr "predicable" "yes")]
3015 )
3016 \f
3017 ;; Zero and sign extension instructions.
3018
3019 (define_insn "zero_extendsidi2"
3020   [(set (match_operand:DI 0 "s_register_operand" "=r")
3021         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3022   "TARGET_ARM"
3023   "*
3024     if (REGNO (operands[1])
3025         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3026       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3027     return \"mov%?\\t%R0, #0\";
3028   "
3029   [(set_attr "length" "8")
3030    (set_attr "predicable" "yes")]
3031 )
3032
3033 (define_insn "zero_extendqidi2"
3034   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3035         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3036   "TARGET_ARM"
3037   "@
3038    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3039    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3040   [(set_attr "length" "8")
3041    (set_attr "predicable" "yes")
3042    (set_attr "type" "*,load")
3043    (set_attr "pool_range" "*,4092")
3044    (set_attr "neg_pool_range" "*,4084")]
3045 )
3046
3047 (define_insn "extendsidi2"
3048   [(set (match_operand:DI 0 "s_register_operand" "=r")
3049         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3050   "TARGET_ARM"
3051   "*
3052     if (REGNO (operands[1])
3053         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3054       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3055     return \"mov%?\\t%R0, %Q0, asr #31\";
3056   "
3057   [(set_attr "length" "8")
3058    (set_attr "shift" "1")
3059    (set_attr "predicable" "yes")]
3060 )
3061
3062 (define_expand "zero_extendhisi2"
3063   [(set (match_dup 2)
3064         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3065                    (const_int 16)))
3066    (set (match_operand:SI 0 "s_register_operand" "")
3067         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3068   "TARGET_EITHER"
3069   "
3070   {
3071     if (TARGET_ARM)
3072       {
3073         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3074           {
3075            /* Note: We do not have to worry about TARGET_MMU_TRAPS
3076               here because the insn below will generate an LDRH instruction
3077               rather than an LDR instruction, so we cannot get an unaligned
3078               word access.  */
3079             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3080                                     gen_rtx_ZERO_EXTEND (SImode,
3081                                                          operands[1])));
3082             DONE;
3083           }
3084         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3085           {
3086             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3087             DONE;
3088           }
3089         if (!s_register_operand (operands[1], HImode))
3090           operands[1] = copy_to_mode_reg (HImode, operands[1]);
3091         operands[1] = gen_lowpart (SImode, operands[1]);
3092         operands[2] = gen_reg_rtx (SImode);
3093       }
3094     else /* TARGET_THUMB */
3095       {
3096         if (GET_CODE (operands[1]) == MEM)
3097           {
3098             rtx tmp;
3099
3100             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3101             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3102             emit_insn (tmp);
3103           }
3104         else
3105           {
3106             rtx ops[3];
3107             
3108             if (!s_register_operand (operands[1], HImode))
3109               operands[1] = copy_to_mode_reg (HImode, operands[1]);
3110             operands[1] = gen_lowpart (SImode, operands[1]);
3111             operands[2] = gen_reg_rtx (SImode);
3112             
3113             ops[0] = operands[2];
3114             ops[1] = operands[1];
3115             ops[2] = GEN_INT (16);
3116             
3117             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3118                                     gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3119
3120             ops[0] = operands[0];
3121             ops[1] = operands[2];
3122             ops[2] = GEN_INT (16);
3123
3124             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3125                                     gen_rtx_LSHIFTRT (SImode, ops[1],
3126                                                       ops[2])));
3127           }
3128         DONE; 
3129       }
3130   }"
3131 )
3132
3133 (define_insn "*thumb_zero_extendhisi2"
3134   [(set (match_operand:SI                 0 "register_operand" "=l")
3135         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3136   "TARGET_THUMB"
3137   "*
3138   rtx mem = XEXP (operands[1], 0);
3139
3140   if (GET_CODE (mem) == CONST)
3141     mem = XEXP (mem, 0);
3142     
3143   if (GET_CODE (mem) == LABEL_REF)
3144     return \"ldr\\t%0, %1\";
3145     
3146   if (GET_CODE (mem) == PLUS)
3147     {
3148       rtx a = XEXP (mem, 0);
3149       rtx b = XEXP (mem, 1);
3150
3151       /* This can happen due to bugs in reload.  */
3152       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3153         {
3154           rtx ops[2];
3155           ops[0] = operands[0];
3156           ops[1] = a;
3157       
3158           output_asm_insn (\"mov        %0, %1\", ops);
3159
3160           XEXP (mem, 0) = operands[0];
3161        }
3162
3163       else if (   GET_CODE (a) == LABEL_REF
3164                && GET_CODE (b) == CONST_INT)
3165         return \"ldr\\t%0, %1\";
3166     }
3167     
3168   return \"ldrh\\t%0, %1\";
3169   "
3170   [(set_attr "length" "4")
3171    (set_attr "type" "load")
3172    (set_attr "pool_range" "60")]
3173 )
3174
3175 (define_insn "*arm_zero_extendhisi2"
3176   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3177         (zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3178   "TARGET_ARM && arm_arch4"
3179   "ldr%?h\\t%0, %1"
3180   [(set_attr "type" "load")
3181    (set_attr "predicable" "yes")
3182    (set_attr "pool_range" "256")
3183    (set_attr "neg_pool_range" "244")]
3184 )
3185
3186 (define_split
3187   [(set (match_operand:SI 0 "s_register_operand" "")
3188         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3189    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3190   "TARGET_ARM && (!arm_arch4)"
3191   [(set (match_dup 2) (match_dup 1))
3192    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3193   "
3194   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3195     FAIL;
3196   "
3197 )
3198
3199 (define_split
3200   [(set (match_operand:SI 0 "s_register_operand" "")
3201         (match_operator:SI 3 "shiftable_operator"
3202          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3203           (match_operand:SI 4 "s_register_operand" "")]))
3204    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3205   "TARGET_ARM && (!arm_arch4)"
3206   [(set (match_dup 2) (match_dup 1))
3207    (set (match_dup 0)
3208         (match_op_dup 3
3209          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3210   "
3211   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3212     FAIL;
3213   "
3214 )
3215
3216 (define_expand "zero_extendqisi2"
3217   [(set (match_operand:SI 0 "s_register_operand" "")
3218         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3219   "TARGET_EITHER"
3220   "
3221   if (GET_CODE (operands[1]) != MEM)
3222     {
3223       if (TARGET_ARM)
3224         {
3225           emit_insn (gen_andsi3 (operands[0],
3226                                  gen_lowpart (SImode, operands[1]),
3227                                  GEN_INT (255)));
3228         }
3229       else /* TARGET_THUMB */
3230         {
3231           rtx temp = gen_reg_rtx (SImode);
3232           rtx ops[3];
3233           
3234           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3235           operands[1] = gen_lowpart (SImode, operands[1]);
3236
3237           ops[0] = temp;
3238           ops[1] = operands[1];
3239           ops[2] = GEN_INT (24);
3240
3241           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3242                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3243           
3244           ops[0] = operands[0];
3245           ops[1] = temp;
3246           ops[2] = GEN_INT (24);
3247
3248           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3249                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3250         }
3251       DONE;
3252     }
3253   "
3254 )
3255
3256 (define_insn "*thumb_zero_extendqisi2"
3257   [(set (match_operand:SI                 0 "register_operand" "=l")
3258         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3259   "TARGET_THUMB"
3260   "ldrb\\t%0, %1"
3261   [(set_attr "length" "2")
3262    (set_attr "type" "load")
3263    (set_attr "pool_range" "32")]
3264 )
3265
3266 (define_insn "*arm_zero_extendqisi2"
3267   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3268         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3269   "TARGET_ARM"
3270   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3271   [(set_attr "type" "load")
3272    (set_attr "predicable" "yes")
3273    (set_attr "pool_range" "4096")
3274    (set_attr "neg_pool_range" "4084")]
3275 )
3276
3277 (define_split
3278   [(set (match_operand:SI 0 "s_register_operand" "")
3279         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3280    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3281   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3282   [(set (match_dup 2) (match_dup 1))
3283    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3284   ""
3285 )
3286
3287 (define_insn "*compareqi_eq0"
3288   [(set (reg:CC_Z CC_REGNUM)
3289         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3290                          (const_int 0)))]
3291   "TARGET_ARM"
3292   "tst\\t%0, #255"
3293   [(set_attr "conds" "set")]
3294 )
3295
3296 (define_expand "extendhisi2"
3297   [(set (match_dup 2)
3298         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3299                    (const_int 16)))
3300    (set (match_operand:SI 0 "s_register_operand" "")
3301         (ashiftrt:SI (match_dup 2)
3302                      (const_int 16)))]
3303   "TARGET_EITHER"
3304   "
3305   {
3306     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3307       {
3308        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3309           here because the insn below will generate an LDRH instruction
3310           rather than an LDR instruction, so we cannot get an unaligned
3311           word access.  */
3312         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3313                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3314         DONE;
3315       }
3316
3317     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3318       {
3319         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3320         DONE;
3321       }
3322     if (!s_register_operand (operands[1], HImode))
3323       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3324     operands[1] = gen_lowpart (SImode, operands[1]);
3325     operands[2] = gen_reg_rtx (SImode);
3326
3327     if (TARGET_THUMB)
3328       {
3329         rtx ops[3];
3330         
3331         ops[0] = operands[2];
3332         ops[1] = operands[1];
3333         ops[2] = GEN_INT (16);
3334         
3335         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3336                                 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3337             
3338         ops[0] = operands[0];
3339         ops[1] = operands[2];
3340         ops[2] = GEN_INT (16);
3341         
3342         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3343                                 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3344         
3345         DONE;
3346       }
3347   }"
3348 )
3349
3350 (define_insn "*thumb_extendhisi2_insn"
3351   [(set (match_operand:SI                 0 "register_operand" "=l")
3352         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3353    (clobber (match_scratch:SI             2                   "=&l"))]
3354   "TARGET_THUMB"
3355   "*
3356   {
3357     rtx ops[4];
3358     rtx mem = XEXP (operands[1], 0);
3359
3360     /* This code used to try to use 'V', and fix the address only if it was
3361        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3362        range of QImode offsets, and offsettable_address_p does a QImode
3363        address check.  */
3364        
3365     if (GET_CODE (mem) == CONST)
3366       mem = XEXP (mem, 0);
3367     
3368     if (GET_CODE (mem) == LABEL_REF)
3369       return \"ldr\\t%0, %1\";
3370     
3371     if (GET_CODE (mem) == PLUS)
3372       {
3373         rtx a = XEXP (mem, 0);
3374         rtx b = XEXP (mem, 1);
3375
3376         if (GET_CODE (a) == LABEL_REF
3377             && GET_CODE (b) == CONST_INT)
3378           return \"ldr\\t%0, %1\";
3379
3380         if (GET_CODE (b) == REG)
3381           return \"ldrsh\\t%0, %1\";
3382           
3383         ops[1] = a;
3384         ops[2] = b;
3385       }
3386     else
3387       {
3388         ops[1] = mem;
3389         ops[2] = const0_rtx;
3390       }
3391       
3392     if (GET_CODE (ops[1]) != REG)
3393       {
3394         debug_rtx (ops[1]);
3395         abort ();
3396       }
3397
3398     ops[0] = operands[0];
3399     ops[3] = operands[2];
3400     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3401     return \"\";
3402   }"
3403   [(set_attr "length" "4")
3404    (set_attr "type" "load")
3405    (set_attr "pool_range" "1020")]
3406 )
3407
3408 (define_expand "extendhisi2_mem"
3409   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3410    (set (match_dup 3)
3411         (zero_extend:SI (match_dup 7)))
3412    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3413    (set (match_operand:SI 0 "" "")
3414         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3415   "TARGET_ARM"
3416   "
3417   {
3418     rtx mem1, mem2;
3419     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3420
3421     mem1 = gen_rtx_MEM (QImode, addr);
3422     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3423     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3424     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3425     operands[0] = gen_lowpart (SImode, operands[0]);
3426     operands[1] = mem1;
3427     operands[2] = gen_reg_rtx (SImode);
3428     operands[3] = gen_reg_rtx (SImode);
3429     operands[6] = gen_reg_rtx (SImode);
3430     operands[7] = mem2;
3431
3432     if (BYTES_BIG_ENDIAN)
3433       {
3434         operands[4] = operands[2];
3435         operands[5] = operands[3];
3436       }
3437     else
3438       {
3439         operands[4] = operands[3];
3440         operands[5] = operands[2];
3441       }
3442   }"
3443 )
3444
3445 (define_insn "*arm_extendhisi_insn"
3446   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3447         (sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3448   "TARGET_ARM && arm_arch4"
3449   "ldr%?sh\\t%0, %1"
3450   [(set_attr "type" "load")
3451    (set_attr "predicable" "yes")
3452    (set_attr "pool_range" "256")
3453    (set_attr "neg_pool_range" "244")]
3454 )
3455
3456 (define_split
3457   [(set (match_operand:SI                 0 "s_register_operand" "")
3458         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3459    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3460   "TARGET_ARM && (!arm_arch4)"
3461   [(set (match_dup 2) (match_dup 1))
3462    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3463   "
3464   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3465     FAIL;
3466   "
3467 )
3468
3469 (define_split
3470   [(set (match_operand:SI                   0 "s_register_operand" "")
3471         (match_operator:SI                  3 "shiftable_operator"
3472          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3473           (match_operand:SI                 4 "s_register_operand" "")]))
3474    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3475   "TARGET_ARM && (!arm_arch4)"
3476   [(set (match_dup 2) (match_dup 1))
3477    (set (match_dup 0)
3478         (match_op_dup 3
3479          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3480   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3481      FAIL;
3482   "
3483 )
3484
3485 (define_expand "extendqihi2"
3486   [(set (match_dup 2)
3487         (ashift:SI (match_operand:QI 1 "general_operand" "")
3488                    (const_int 24)))
3489    (set (match_operand:HI 0 "s_register_operand" "")
3490         (ashiftrt:SI (match_dup 2)
3491                      (const_int 24)))]
3492   "TARGET_ARM"
3493   "
3494   {
3495     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3496       {
3497         emit_insn (gen_rtx_SET (VOIDmode,
3498                                 operands[0],
3499                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3500         DONE;
3501       }
3502     if (!s_register_operand (operands[1], QImode))
3503       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3504     operands[0] = gen_lowpart (SImode, operands[0]);
3505     operands[1] = gen_lowpart (SImode, operands[1]);
3506     operands[2] = gen_reg_rtx (SImode);
3507   }"
3508 )
3509
3510 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3511 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3512 (define_insn "*extendqihi_insn"
3513   [(set (match_operand:HI                 0 "s_register_operand" "=r")
3514         (sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3515   "TARGET_ARM && arm_arch4"
3516   "*
3517   /* If the address is invalid, this will split the instruction into two. */
3518   if (bad_signed_byte_operand (operands[1], VOIDmode))
3519     return \"#\";
3520   return \"ldr%?sb\\t%0, %1\";
3521   "
3522   [(set_attr "type" "load")
3523    (set_attr "predicable" "yes")
3524    (set_attr "length" "8")
3525    (set_attr "pool_range" "256")
3526    (set_attr "neg_pool_range" "244")]
3527 )
3528
3529 (define_split
3530   [(set (match_operand:HI 0 "s_register_operand" "")
3531         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3532   "TARGET_ARM && arm_arch4 && reload_completed"
3533   [(set (match_dup 3) (match_dup 1))
3534    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3535   "
3536   {
3537     HOST_WIDE_INT offset;
3538
3539     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3540     operands[2] = gen_rtx_MEM (QImode, operands[3]);
3541     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3542     operands[1] = XEXP (operands[1], 0);
3543     if (GET_CODE (operands[1]) == PLUS
3544         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3545         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3546              || const_ok_for_arm (-offset)))
3547       {
3548         HOST_WIDE_INT low = (offset > 0
3549                              ? (offset & 0xff) : -((-offset) & 0xff));
3550         XEXP (operands[2], 0) = plus_constant (operands[3], low);
3551         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3552       }
3553     /* Ensure the sum is in correct canonical form */
3554     else if (GET_CODE (operands[1]) == PLUS
3555              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3556              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3557       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3558                                            XEXP (operands[1], 1),
3559                                            XEXP (operands[1], 0));
3560   }"
3561 )
3562
3563 (define_expand "extendqisi2"
3564   [(set (match_dup 2)
3565         (ashift:SI (match_operand:QI 1 "general_operand" "")
3566                    (const_int 24)))
3567    (set (match_operand:SI 0 "s_register_operand" "")
3568         (ashiftrt:SI (match_dup 2)
3569                      (const_int 24)))]
3570   "TARGET_EITHER"
3571   "
3572   {
3573     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3574       {
3575         emit_insn (gen_rtx_SET (VOIDmode,
3576                                 operands[0],
3577                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3578         DONE;
3579       }
3580     if (!s_register_operand (operands[1], QImode))
3581       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3582     operands[1] = gen_lowpart (SImode, operands[1]);
3583     operands[2] = gen_reg_rtx (SImode);
3584     
3585     if (TARGET_THUMB)
3586       {
3587         rtx ops[3];
3588         
3589         ops[0] = operands[2];
3590         ops[1] = operands[1];
3591         ops[2] = GEN_INT (24);
3592         
3593         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3594                    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3595
3596         ops[0] = operands[0];
3597         ops[1] = operands[2];
3598         ops[2] = GEN_INT (24);
3599         
3600         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3601                    gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3602         
3603         DONE;
3604       }
3605   }"
3606 )
3607
3608 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3609 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3610 (define_insn "*arm_extendqisi_insn"
3611   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3612         (sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3613   "TARGET_ARM && arm_arch4"
3614   "*
3615   /* If the address is invalid, this will split the instruction into two. */
3616   if (bad_signed_byte_operand (operands[1], VOIDmode))
3617     return \"#\";
3618   return \"ldr%?sb\\t%0, %1\";
3619   "
3620   [(set_attr "type" "load")
3621    (set_attr "predicable" "yes")
3622    (set_attr "length" "8")
3623    (set_attr "pool_range" "256")
3624    (set_attr "neg_pool_range" "244")]
3625 )
3626
3627 (define_split
3628   [(set (match_operand:SI 0 "s_register_operand" "")
3629         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3630   "TARGET_ARM && arm_arch4 && reload_completed"
3631   [(set (match_dup 0) (match_dup 1))
3632    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3633   "
3634   {
3635     HOST_WIDE_INT offset;
3636
3637     operands[2] = gen_rtx_MEM (QImode, operands[0]);
3638     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3639     operands[1] = XEXP (operands[1], 0);
3640     if (GET_CODE (operands[1]) == PLUS
3641         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3642         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3643              || const_ok_for_arm (-offset)))
3644       {
3645         HOST_WIDE_INT low = (offset > 0
3646                              ? (offset & 0xff) : -((-offset) & 0xff));
3647         XEXP (operands[2], 0) = plus_constant (operands[0], low);
3648         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3649       }
3650     /* Ensure the sum is in correct canonical form */
3651     else if (GET_CODE (operands[1]) == PLUS
3652              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3653              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3654       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3655                                            XEXP (operands[1], 1),
3656                                            XEXP (operands[1], 0));
3657   }"
3658 )
3659
3660 (define_insn "*thumb_extendqisi2_insn"
3661   [(set (match_operand:SI                 0 "register_operand" "=l,l")
3662         (sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3663   "TARGET_THUMB"
3664   "*
3665   {
3666     rtx ops[3];
3667     rtx mem = XEXP (operands[1], 0);
3668     
3669     if (GET_CODE (mem) == CONST)
3670       mem = XEXP (mem, 0);
3671     
3672     if (GET_CODE (mem) == LABEL_REF)
3673       return \"ldr\\t%0, %1\";
3674
3675     if (GET_CODE (mem) == PLUS
3676         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3677       return \"ldr\\t%0, %1\";
3678       
3679     if (which_alternative == 0)
3680       return \"ldrsb\\t%0, %1\";
3681       
3682     ops[0] = operands[0];
3683     
3684     if (GET_CODE (mem) == PLUS)
3685       {
3686         rtx a = XEXP (mem, 0);
3687         rtx b = XEXP (mem, 1);
3688         
3689         ops[1] = a;
3690         ops[2] = b;
3691
3692         if (GET_CODE (a) == REG)
3693           {
3694             if (GET_CODE (b) == REG)
3695               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3696             else if (REGNO (a) == REGNO (ops[0]))
3697               {
3698                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3699                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3700                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3701               }
3702             else
3703               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3704           }
3705         else if (GET_CODE (b) != REG)
3706           abort ();
3707         else
3708           {
3709             if (REGNO (b) == REGNO (ops[0]))
3710               {
3711                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3712                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3713                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3714               }
3715             else
3716               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3717           }
3718       }
3719     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3720       {
3721         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3722         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3723         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3724       }
3725     else
3726       {
3727         ops[1] = mem;
3728         ops[2] = const0_rtx;
3729         
3730         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3731       }
3732     return \"\";
3733   }"
3734   [(set_attr "length" "2,6")
3735    (set_attr "type" "load,load")
3736    (set_attr "pool_range" "32,32")]
3737 )
3738
3739 (define_expand "extendsfdf2"
3740   [(set (match_operand:DF                  0 "s_register_operand" "")
3741         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3742   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3743   ""
3744 )
3745
3746 (define_insn "*arm_extendsfdf2"
3747   [(set (match_operand:DF                  0 "s_register_operand" "=f")
3748         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "f")))]
3749   "TARGET_ARM && TARGET_HARD_FLOAT"
3750   "mvf%?d\\t%0, %1"
3751   [(set_attr "type" "ffarith")
3752    (set_attr "predicable" "yes")]
3753 )
3754 \f
3755 ;; Move insns (including loads and stores)
3756
3757 ;; XXX Just some ideas about movti.
3758 ;; I don't think these are a good idea on the arm, there just aren't enough
3759 ;; registers
3760 ;;(define_expand "loadti"
3761 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3762 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3763 ;;  "" "")
3764
3765 ;;(define_expand "storeti"
3766 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3767 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3768 ;;  "" "")
3769
3770 ;;(define_expand "movti"
3771 ;;  [(set (match_operand:TI 0 "general_operand" "")
3772 ;;      (match_operand:TI 1 "general_operand" ""))]
3773 ;;  ""
3774 ;;  "
3775 ;;{
3776 ;;  rtx insn;
3777 ;;
3778 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3779 ;;    operands[1] = copy_to_reg (operands[1]);
3780 ;;  if (GET_CODE (operands[0]) == MEM)
3781 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3782 ;;  else if (GET_CODE (operands[1]) == MEM)
3783 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3784 ;;  else
3785 ;;    FAIL;
3786 ;;
3787 ;;  emit_insn (insn);
3788 ;;  DONE;
3789 ;;}")
3790
3791 ;; Recognize garbage generated above.
3792
3793 ;;(define_insn ""
3794 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3795 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3796 ;;  ""
3797 ;;  "*
3798 ;;  {
3799 ;;    register mem = (which_alternative < 3);
3800 ;;    register const char *template;
3801 ;;
3802 ;;    operands[mem] = XEXP (operands[mem], 0);
3803 ;;    switch (which_alternative)
3804 ;;      {
3805 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3806 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3807 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3808 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3809 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3810 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3811 ;;      }
3812 ;;    output_asm_insn (template, operands);
3813 ;;    return \"\";
3814 ;;  }")
3815
3816 (define_expand "movdi"
3817   [(set (match_operand:DI 0 "general_operand" "")
3818         (match_operand:DI 1 "general_operand" ""))]
3819   "TARGET_EITHER"
3820   "
3821   if (TARGET_THUMB)
3822     {
3823       if (!no_new_pseudos)
3824         {
3825           if (GET_CODE (operands[0]) != REG)
3826             operands[1] = force_reg (DImode, operands[1]);
3827         }
3828     }
3829   "
3830 )
3831
3832 (define_insn "*arm_movdi"
3833   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3834         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3835   "TARGET_ARM && !TARGET_CIRRUS"
3836   "*
3837   return (output_move_double (operands));
3838   "
3839   [(set_attr "length" "8")
3840    (set_attr "type" "*,load,store2")
3841    (set_attr "pool_range" "*,1020,*")
3842    (set_attr "neg_pool_range" "*,1008,*")]
3843 )
3844
3845 ;;; ??? This should have alternatives for constants.
3846 ;;; ??? This was originally identical to the movdf_insn pattern.
3847 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3848 ;;; thumb_reorg with a memory reference.
3849 (define_insn "*thumb_movdi_insn"
3850   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3851         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3852   "TARGET_THUMB
3853    && !TARGET_CIRRUS
3854    && (   register_operand (operands[0], DImode)
3855        || register_operand (operands[1], DImode))"
3856   "*
3857   {
3858   switch (which_alternative)
3859     {
3860     default:
3861     case 0:
3862       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3863         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3864       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3865     case 1:
3866       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3867     case 2:
3868       operands[1] = GEN_INT (- INTVAL (operands[1]));
3869       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3870     case 3:
3871       return \"ldmia\\t%1, {%0, %H0}\";
3872     case 4:
3873       return \"stmia\\t%0, {%1, %H1}\";
3874     case 5:
3875       return thumb_load_double_from_address (operands);
3876     case 6:
3877       operands[2] = gen_rtx (MEM, SImode,
3878                              plus_constant (XEXP (operands[0], 0), 4));
3879       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3880       return \"\";
3881     case 7:
3882       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3883         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3884       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3885     }
3886   }"
3887   [(set_attr "length" "4,4,6,2,2,6,4,4")
3888    (set_attr "type" "*,*,*,load,store2,load,store2,*")
3889    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3890 )
3891
3892 (define_expand "movsi"
3893   [(set (match_operand:SI 0 "general_operand" "")
3894         (match_operand:SI 1 "general_operand" ""))]
3895   "TARGET_EITHER"
3896   "
3897   if (TARGET_ARM)
3898     {
3899       /* Everything except mem = const or mem = mem can be done easily */
3900       if (GET_CODE (operands[0]) == MEM)
3901         operands[1] = force_reg (SImode, operands[1]);
3902       if (GET_CODE (operands[1]) == CONST_INT
3903           && !(const_ok_for_arm (INTVAL (operands[1]))
3904                || const_ok_for_arm (~INTVAL (operands[1]))))
3905         {
3906            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3907                               NULL_RTX,
3908                               (no_new_pseudos ? 0
3909                                : preserve_subexpressions_p ()));
3910           DONE;
3911         }
3912     }
3913   else /* TARGET_THUMB.... */
3914     {
3915       if (!no_new_pseudos)
3916         {
3917           if (GET_CODE (operands[0]) != REG)
3918             operands[1] = force_reg (SImode, operands[1]);
3919         }
3920     }
3921     
3922   if (flag_pic
3923       && (CONSTANT_P (operands[1])
3924          || symbol_mentioned_p (operands[1])
3925          || label_mentioned_p (operands[1])))
3926     operands[1] = legitimize_pic_address (operands[1], SImode,
3927                                           (no_new_pseudos ? operands[0] : 0));
3928   "
3929 )
3930
3931 (define_insn "*arm_movsi_insn"
3932   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3933         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
3934   "TARGET_ARM
3935    && (   register_operand (operands[0], SImode)
3936        || register_operand (operands[1], SImode))"
3937   "@
3938    mov%?\\t%0, %1
3939    mvn%?\\t%0, #%B1
3940    ldr%?\\t%0, %1
3941    str%?\\t%1, %0"
3942   [(set_attr "type" "*,*,load,store1")
3943    (set_attr "predicable" "yes")
3944    (set_attr "pool_range" "*,*,4096,*")
3945    (set_attr "neg_pool_range" "*,*,4084,*")]
3946 )
3947
3948 (define_split
3949   [(set (match_operand:SI 0 "s_register_operand" "")
3950         (match_operand:SI 1 "const_int_operand" ""))]
3951   "TARGET_ARM
3952   && (!(const_ok_for_arm (INTVAL (operands[1]))
3953         || const_ok_for_arm (~INTVAL (operands[1]))))"
3954   [(clobber (const_int 0))]
3955   "
3956   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3957                       NULL_RTX, 0);
3958   DONE;
3959   "
3960 )
3961
3962 (define_insn "*thumb_movsi_insn"
3963   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3964         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
3965   "TARGET_THUMB
3966    && (   register_operand (operands[0], SImode) 
3967        || register_operand (operands[1], SImode))"
3968   "@
3969    mov  %0, %1
3970    mov  %0, %1
3971    #
3972    #
3973    ldmia\\t%1, {%0}
3974    stmia\\t%0, {%1}
3975    ldr\\t%0, %1
3976    str\\t%1, %0
3977    mov\\t%0, %1"
3978   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3979    (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3980    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3981 )
3982
3983 (define_split 
3984   [(set (match_operand:SI 0 "register_operand" "")
3985         (match_operand:SI 1 "const_int_operand" ""))]
3986   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3987   [(set (match_dup 0) (match_dup 1))
3988    (set (match_dup 0) (neg:SI (match_dup 0)))]
3989   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3990 )
3991
3992 (define_split 
3993   [(set (match_operand:SI 0 "register_operand" "")
3994         (match_operand:SI 1 "const_int_operand" ""))]
3995   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3996   [(set (match_dup 0) (match_dup 1))
3997    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3998   "
3999   {
4000     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4001     unsigned HOST_WIDE_INT mask = 0xff;
4002     int i;
4003     
4004     for (i = 0; i < 25; i++)
4005       if ((val & (mask << i)) == val)
4006         break;
4007
4008     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4009     if (i == 0)
4010       FAIL;
4011
4012     operands[1] = GEN_INT (val >> i);
4013     operands[2] = GEN_INT (i);
4014   }"
4015 )
4016
4017 ;; When generating pic, we need to load the symbol offset into a register.
4018 ;; So that the optimizer does not confuse this with a normal symbol load
4019 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4020 ;; since that is the only type of relocation we can use.
4021
4022 ;; The rather odd constraints on the following are to force reload to leave
4023 ;; the insn alone, and to force the minipool generation pass to then move
4024 ;; the GOT symbol to memory.
4025
4026 (define_insn "pic_load_addr_arm"
4027   [(set (match_operand:SI 0 "s_register_operand" "=r")
4028         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4029   "TARGET_ARM && flag_pic"
4030   "ldr%?\\t%0, %1"
4031   [(set_attr "type" "load")
4032    (set (attr "pool_range")     (const_int 4096))
4033    (set (attr "neg_pool_range") (const_int 4084))]
4034 )
4035
4036 (define_insn "pic_load_addr_thumb"
4037   [(set (match_operand:SI 0 "s_register_operand" "=l")
4038         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4039   "TARGET_THUMB && flag_pic"
4040   "ldr\\t%0, %1"
4041   [(set_attr "type" "load")
4042    (set (attr "pool_range") (const_int 1024))]
4043 )
4044
4045 ;; This variant is used for AOF assembly, since it needs to mention the
4046 ;; pic register in the rtl.
4047 (define_expand "pic_load_addr_based"
4048   [(set (match_operand:SI 0 "s_register_operand" "=r")
4049         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4050   "TARGET_ARM && flag_pic"
4051   "operands[2] = pic_offset_table_rtx;"
4052 )
4053
4054 (define_insn "*pic_load_addr_based_insn"
4055   [(set (match_operand:SI 0 "s_register_operand" "=r")
4056         (unspec:SI [(match_operand 1 "" "")
4057                     (match_operand 2 "s_register_operand" "r")]
4058                    UNSPEC_PIC_SYM))]
4059   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4060   "*
4061 #ifdef AOF_ASSEMBLER
4062   operands[1] = aof_pic_entry (operands[1]);
4063 #endif
4064   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4065   return \"\";
4066   "
4067   [(set_attr "type" "load")
4068    (set (attr "pool_range")
4069         (if_then_else (eq_attr "is_thumb" "yes")
4070                       (const_int 1024)
4071                       (const_int 4096)))
4072    (set (attr "neg_pool_range")
4073         (if_then_else (eq_attr "is_thumb" "yes")
4074                       (const_int 0)
4075                       (const_int 4084)))]
4076 )
4077
4078 (define_insn "pic_add_dot_plus_four"
4079   [(set (match_operand:SI 0 "register_operand" "+r")
4080         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4081    (use (label_ref (match_operand 1 "" "")))]
4082   "TARGET_THUMB && flag_pic"
4083   "*
4084   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4085                              CODE_LABEL_NUMBER (operands[1]));
4086   return \"add\\t%0, %|pc\";
4087   "
4088   [(set_attr "length" "2")]
4089 )
4090
4091 (define_insn "pic_add_dot_plus_eight"
4092   [(set (match_operand:SI 0 "register_operand" "+r")
4093         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4094    (use (label_ref (match_operand 1 "" "")))]
4095   "TARGET_ARM && flag_pic"
4096   "*
4097     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4098                                CODE_LABEL_NUMBER (operands[1]));
4099     return \"add%?\\t%0, %|pc, %0\";
4100   "
4101   [(set_attr "predicable" "yes")]
4102 )
4103
4104 (define_expand "builtin_setjmp_receiver"
4105   [(label_ref (match_operand 0 "" ""))]
4106   "flag_pic"
4107   "
4108 {
4109   arm_finalize_pic (0);
4110   DONE;
4111 }")
4112
4113 ;; If copying one reg to another we can set the condition codes according to
4114 ;; its value.  Such a move is common after a return from subroutine and the
4115 ;; result is being tested against zero.
4116
4117 (define_insn "*movsi_compare0"
4118   [(set (reg:CC CC_REGNUM)
4119         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4120                     (const_int 0)))
4121    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4122         (match_dup 1))]
4123   "TARGET_ARM"
4124   "@
4125    cmp%?\\t%0, #0
4126    sub%?s\\t%0, %1, #0"
4127   [(set_attr "conds" "set")]
4128 )
4129
4130 ;; Subroutine to store a half word from a register into memory.
4131 ;; Operand 0 is the source register (HImode)
4132 ;; Operand 1 is the destination address in a register (SImode)
4133
4134 ;; In both this routine and the next, we must be careful not to spill
4135 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4136 ;; can generate unrecognizable rtl.
4137
4138 (define_expand "storehi"
4139   [;; store the low byte
4140    (set (match_operand 1 "" "") (match_dup 3))
4141    ;; extract the high byte
4142    (set (match_dup 2)
4143         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4144    ;; store the high byte
4145    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
4146   "TARGET_ARM"
4147   "
4148   {
4149     rtx op1 = operands[1];
4150     rtx addr = XEXP (op1, 0);
4151     enum rtx_code code = GET_CODE (addr);
4152
4153     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4154         || code == MINUS)
4155       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4156
4157     operands[4] = adjust_address (op1, QImode, 1);
4158     operands[1] = adjust_address (operands[1], QImode, 0);
4159     operands[3] = gen_lowpart (QImode, operands[0]);
4160     operands[0] = gen_lowpart (SImode, operands[0]);
4161     operands[2] = gen_reg_rtx (SImode); 
4162   }"
4163 )
4164
4165 (define_expand "storehi_bigend"
4166   [(set (match_dup 4) (match_dup 3))
4167    (set (match_dup 2)
4168         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4169    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4170   "TARGET_ARM"
4171   "
4172   {
4173     rtx op1 = operands[1];
4174     rtx addr = XEXP (op1, 0);
4175     enum rtx_code code = GET_CODE (addr);
4176
4177     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4178         || code == MINUS)
4179       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4180
4181     operands[4] = adjust_address (op1, QImode, 1);
4182     operands[1] = adjust_address (operands[1], QImode, 0);
4183     operands[3] = gen_lowpart (QImode, operands[0]);
4184     operands[0] = gen_lowpart (SImode, operands[0]);
4185     operands[2] = gen_reg_rtx (SImode);
4186   }"
4187 )
4188
4189 ;; Subroutine to store a half word integer constant into memory.
4190 (define_expand "storeinthi"
4191   [(set (match_operand 0 "" "")
4192         (subreg:QI (match_operand 1 "" "") 0))
4193    (set (match_dup 3) (match_dup 2))]
4194   "TARGET_ARM"
4195   "
4196   {
4197     HOST_WIDE_INT value = INTVAL (operands[1]);
4198     rtx addr = XEXP (operands[0], 0);
4199     rtx op0 = operands[0];
4200     enum rtx_code code = GET_CODE (addr);
4201
4202     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4203         || code == MINUS)
4204       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4205
4206     operands[1] = gen_reg_rtx (SImode);
4207     if (BYTES_BIG_ENDIAN)
4208       {
4209         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4210         if ((value & 255) == ((value >> 8) & 255))
4211           operands[2] = operands[1];
4212         else
4213           {
4214             operands[2] = gen_reg_rtx (SImode);
4215             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4216           }
4217       }
4218     else
4219       {
4220         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4221         if ((value & 255) == ((value >> 8) & 255))
4222           operands[2] = operands[1];
4223         else
4224           {
4225             operands[2] = gen_reg_rtx (SImode);
4226             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4227           }
4228       }
4229
4230     operands[3] = adjust_address (op0, QImode, 1);
4231     operands[0] = adjust_address (operands[0], QImode, 0);
4232     operands[2] = gen_lowpart (QImode, operands[2]);
4233   }"
4234 )
4235
4236 (define_expand "storehi_single_op"
4237   [(set (match_operand:HI 0 "memory_operand" "")
4238         (match_operand:HI 1 "general_operand" ""))]
4239   "TARGET_ARM && arm_arch4"
4240   "
4241   if (!s_register_operand (operands[1], HImode))
4242     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4243   "
4244 )
4245
4246 (define_expand "movhi"
4247   [(set (match_operand:HI 0 "general_operand" "")
4248         (match_operand:HI 1 "general_operand" ""))]
4249   "TARGET_EITHER"
4250   "
4251   if (TARGET_ARM)
4252     {
4253       if (!no_new_pseudos)
4254         {
4255           if (GET_CODE (operands[0]) == MEM)
4256             {
4257               if (arm_arch4)
4258                 {
4259                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4260                   DONE;
4261                 }
4262               if (GET_CODE (operands[1]) == CONST_INT)
4263                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4264               else
4265                 {
4266                   if (GET_CODE (operands[1]) == MEM)
4267                     operands[1] = force_reg (HImode, operands[1]);
4268                   if (BYTES_BIG_ENDIAN)
4269                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4270                   else
4271                    emit_insn (gen_storehi (operands[1], operands[0]));
4272                 }
4273               DONE;
4274             }
4275           /* Sign extend a constant, and keep it in an SImode reg.  */
4276           else if (GET_CODE (operands[1]) == CONST_INT)
4277             {
4278               rtx reg = gen_reg_rtx (SImode);
4279               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4280
4281               /* If the constant is already valid, leave it alone.  */
4282               if (!const_ok_for_arm (val))
4283                 {
4284                   /* If setting all the top bits will make the constant 
4285                      loadable in a single instruction, then set them.  
4286                      Otherwise, sign extend the number.  */
4287
4288                   if (const_ok_for_arm (~(val | ~0xffff)))
4289                     val |= ~0xffff;
4290                   else if (val & 0x8000)
4291                     val |= ~0xffff;
4292                 }
4293
4294               emit_insn (gen_movsi (reg, GEN_INT (val)));
4295               operands[1] = gen_lowpart (HImode, reg);
4296             }
4297           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4298                    && GET_CODE (operands[1]) == MEM)
4299             {
4300               rtx reg = gen_reg_rtx (SImode);
4301
4302               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4303               operands[1] = gen_lowpart (HImode, reg);
4304             }
4305           else if (!arm_arch4)
4306             {
4307              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4308                 for v4 and up architectures because LDRH instructions will
4309                 be used to access the HI values, and these cannot generate
4310                 unaligned word access faults in the MMU.  */
4311               if (GET_CODE (operands[1]) == MEM)
4312                 {
4313                   if (TARGET_MMU_TRAPS)
4314                     {
4315                       rtx base;
4316                       rtx offset = const0_rtx;
4317                       rtx reg = gen_reg_rtx (SImode);
4318
4319                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4320                            || (GET_CODE (base) == PLUS
4321                                && (GET_CODE (offset = XEXP (base, 1))
4322                                    == CONST_INT)
4323                                && ((INTVAL(offset) & 1) != 1)
4324                                && GET_CODE (base = XEXP (base, 0)) == REG))
4325                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4326                         {
4327                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4328                           rtx new;
4329
4330                           new = gen_rtx_MEM (SImode,
4331                                              plus_constant (base, new_offset));
4332                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4333                           emit_insn (gen_movsi (reg, new));
4334                           if (((INTVAL (offset) & 2) != 0)
4335                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4336                             {
4337                               rtx reg2 = gen_reg_rtx (SImode);
4338
4339                               emit_insn (gen_lshrsi3 (reg2, reg,
4340                                          GEN_INT (16)));
4341                               reg = reg2;
4342                             }
4343                         }
4344                       else
4345                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4346
4347                       operands[1] = gen_lowpart (HImode, reg);
4348                     }
4349                   else if (BYTES_BIG_ENDIAN)
4350                     {
4351                       rtx base;
4352                       rtx offset = const0_rtx;
4353
4354                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4355                            || (GET_CODE (base) == PLUS
4356                               && (GET_CODE (offset = XEXP (base, 1))
4357                                   == CONST_INT)
4358                               && GET_CODE (base = XEXP (base, 0)) == REG))
4359                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4360                         {
4361                           rtx reg = gen_reg_rtx (SImode);
4362                           rtx new;
4363
4364                           if ((INTVAL (offset) & 2) == 2)
4365                             {
4366                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4367                               new = gen_rtx_MEM (SImode,
4368                                                  plus_constant (base,
4369                                                                 new_offset));
4370                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4371                               emit_insn (gen_movsi (reg, new));
4372                             }
4373                           else
4374                             {
4375                               new = gen_rtx_MEM (SImode,
4376                                                  XEXP (operands[1], 0));
4377                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4378                               emit_insn (gen_rotated_loadsi (reg, new));
4379                             }
4380
4381                           operands[1] = gen_lowpart (HImode, reg);
4382                         }
4383                       else
4384                         {
4385                           emit_insn (gen_movhi_bigend (operands[0],
4386                                                        operands[1]));
4387                           DONE;
4388                         }
4389                     }
4390                }
4391            }
4392         }
4393       /* Handle loading a large integer during reload */
4394       else if (GET_CODE (operands[1]) == CONST_INT
4395                && !const_ok_for_arm (INTVAL (operands[1]))
4396                && !const_ok_for_arm (~INTVAL (operands[1])))
4397         {
4398           /* Writing a constant to memory needs a scratch, which should
4399              be handled with SECONDARY_RELOADs.  */
4400           if (GET_CODE (operands[0]) != REG)
4401             abort ();
4402
4403           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4404           emit_insn (gen_movsi (operands[0], operands[1]));
4405           DONE;
4406        }
4407     }
4408   else /* TARGET_THUMB */
4409     {
4410       if (!no_new_pseudos)
4411         {
4412           if (GET_CODE (operands[0]) != REG)
4413             operands[1] = force_reg (HImode, operands[1]);
4414
4415           /* ??? We shouldn't really get invalid addresses here, but this can
4416              happen if we are passed a SP (never OK for HImode/QImode) or 
4417              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4418              HImode/QImode) relative address.  */
4419           /* ??? This should perhaps be fixed elsewhere, for instance, in
4420              fixup_stack_1, by checking for other kinds of invalid addresses,
4421              e.g. a bare reference to a virtual register.  This may confuse the
4422              alpha though, which must handle this case differently.  */
4423           if (GET_CODE (operands[0]) == MEM
4424               && !memory_address_p (GET_MODE (operands[0]),
4425                                     XEXP (operands[0], 0)))
4426             operands[0]
4427               = replace_equiv_address (operands[0],
4428                                        copy_to_reg (XEXP (operands[0], 0)));
4429    
4430           if (GET_CODE (operands[1]) == MEM
4431               && !memory_address_p (GET_MODE (operands[1]),
4432                                     XEXP (operands[1], 0)))
4433             operands[1]
4434               = replace_equiv_address (operands[1],
4435                                        copy_to_reg (XEXP (operands[1], 0)));
4436         }
4437       /* Handle loading a large integer during reload */
4438       else if (GET_CODE (operands[1]) == CONST_INT
4439                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4440         {
4441           /* Writing a constant to memory needs a scratch, which should
4442              be handled with SECONDARY_RELOADs.  */
4443           if (GET_CODE (operands[0]) != REG)
4444             abort ();
4445
4446           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4447           emit_insn (gen_movsi (operands[0], operands[1]));
4448           DONE;
4449         }
4450     }
4451   "
4452 )
4453
4454 (define_insn "*thumb_movhi_insn"
4455   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4456         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4457   "TARGET_THUMB
4458    && (   register_operand (operands[0], HImode)
4459        || register_operand (operands[1], HImode))"
4460   "*
4461   switch (which_alternative)
4462     {
4463     case 0: return \"add        %0, %1, #0\";
4464     case 2: return \"strh       %1, %0\";
4465     case 3: return \"mov        %0, %1\";
4466     case 4: return \"mov        %0, %1\";
4467     case 5: return \"mov        %0, %1\";
4468     default: abort ();
4469     case 1:
4470       /* The stack pointer can end up being taken as an index register.
4471           Catch this case here and deal with it.  */
4472       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4473           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4474           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4475         {
4476           rtx ops[2];
4477           ops[0] = operands[0];
4478           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4479       
4480           output_asm_insn (\"mov        %0, %1\", ops);
4481
4482           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4483     
4484         }
4485       return \"ldrh     %0, %1\";
4486     }"
4487   [(set_attr "length" "2,4,2,2,2,2")
4488    (set_attr "type" "*,load,store1,*,*,*")
4489    (set_attr "pool_range" "*,64,*,*,*,*")]
4490 )
4491
4492
4493 (define_insn "rotated_loadsi"
4494   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4495         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4496                    (const_int 16)))]
4497   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4498   "*
4499   {
4500     rtx ops[2];
4501
4502     ops[0] = operands[0];
4503     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4504     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4505     return \"\";
4506   }"
4507   [(set_attr "type" "load")
4508    (set_attr "predicable" "yes")]
4509 )
4510
4511 (define_expand "movhi_bytes"
4512   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4513    (set (match_dup 3)
4514         (zero_extend:SI (match_dup 6)))
4515    (set (match_operand:SI 0 "" "")
4516          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4517   "TARGET_ARM"
4518   "
4519   {
4520     rtx mem1, mem2;
4521     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4522
4523     mem1 = gen_rtx_MEM (QImode, addr);
4524     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4525     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4526     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4527     operands[0] = gen_lowpart (SImode, operands[0]);
4528     operands[1] = mem1;
4529     operands[2] = gen_reg_rtx (SImode);
4530     operands[3] = gen_reg_rtx (SImode);
4531     operands[6] = mem2;
4532
4533     if (BYTES_BIG_ENDIAN)
4534       {
4535         operands[4] = operands[2];
4536         operands[5] = operands[3];
4537       }
4538     else
4539       {
4540         operands[4] = operands[3];
4541         operands[5] = operands[2];
4542       }
4543   }"
4544 )
4545
4546 (define_expand "movhi_bigend"
4547   [(set (match_dup 2)
4548         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4549                    (const_int 16)))
4550    (set (match_dup 3)
4551         (ashiftrt:SI (match_dup 2) (const_int 16)))
4552    (set (match_operand:HI 0 "s_register_operand" "")
4553         (subreg:HI (match_dup 3) 0))]
4554   "TARGET_ARM"
4555   "
4556   operands[2] = gen_reg_rtx (SImode);
4557   operands[3] = gen_reg_rtx (SImode);
4558   "
4559 )
4560
4561 ;; Pattern to recognize insn generated default case above
4562 (define_insn "*movhi_insn_arch4"
4563   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4564         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4565   "TARGET_ARM
4566    && arm_arch4
4567    && (GET_CODE (operands[1]) != CONST_INT
4568        || const_ok_for_arm (INTVAL (operands[1]))
4569        || const_ok_for_arm (~INTVAL (operands[1])))"
4570   "@
4571    mov%?\\t%0, %1\\t%@ movhi
4572    mvn%?\\t%0, #%B1\\t%@ movhi
4573    str%?h\\t%1, %0\\t%@ movhi 
4574    ldr%?h\\t%0, %1\\t%@ movhi"
4575   [(set_attr "type" "*,*,store1,load")
4576    (set_attr "predicable" "yes")
4577    (set_attr "pool_range" "*,*,*,256")
4578    (set_attr "neg_pool_range" "*,*,*,244")]
4579 )
4580
4581 (define_insn "*movhi_insn_littleend"
4582   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4583         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4584   "TARGET_ARM
4585    && !arm_arch4
4586    && !BYTES_BIG_ENDIAN
4587    && !TARGET_MMU_TRAPS
4588    && (GET_CODE (operands[1]) != CONST_INT
4589        || const_ok_for_arm (INTVAL (operands[1]))
4590        || const_ok_for_arm (~INTVAL (operands[1])))"
4591   "@
4592    mov%?\\t%0, %1\\t%@ movhi
4593    mvn%?\\t%0, #%B1\\t%@ movhi
4594    ldr%?\\t%0, %1\\t%@ movhi"
4595   [(set_attr "type" "*,*,load")
4596    (set_attr "predicable" "yes")
4597    (set_attr "pool_range" "4096")
4598    (set_attr "neg_pool_range" "4084")]
4599 )
4600
4601 (define_insn "*movhi_insn_bigend"
4602   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4603         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4604   "TARGET_ARM
4605    && !arm_arch4
4606    && BYTES_BIG_ENDIAN
4607    && !TARGET_MMU_TRAPS
4608    && (GET_CODE (operands[1]) != CONST_INT
4609        || const_ok_for_arm (INTVAL (operands[1]))
4610        || const_ok_for_arm (~INTVAL (operands[1])))"
4611   "@
4612    mov%?\\t%0, %1\\t%@ movhi
4613    mvn%?\\t%0, #%B1\\t%@ movhi
4614    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4615   [(set_attr "type" "*,*,load")
4616    (set_attr "predicable" "yes")
4617    (set_attr "length" "4,4,8")
4618    (set_attr "pool_range" "*,*,4092")
4619    (set_attr "neg_pool_range" "*,*,4084")]
4620 )
4621
4622 (define_insn "*loadhi_si_bigend"
4623   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4624         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4625                    (const_int 16)))]
4626   "TARGET_ARM
4627    && BYTES_BIG_ENDIAN
4628    && !TARGET_MMU_TRAPS"
4629   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4630   [(set_attr "type" "load")
4631    (set_attr "predicable" "yes")
4632    (set_attr "pool_range" "4096")
4633    (set_attr "neg_pool_range" "4084")]
4634 )
4635
4636 (define_insn "*movhi_bytes"
4637   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4638         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4639   "TARGET_ARM && TARGET_MMU_TRAPS"
4640   "@
4641    mov%?\\t%0, %1\\t%@ movhi
4642    mvn%?\\t%0, #%B1\\t%@ movhi"
4643   [(set_attr "predicable" "yes")]
4644 )
4645
4646 (define_insn "thumb_movhi_clobber"
4647   [(set (match_operand:HI     0 "memory_operand"   "=m")
4648         (match_operand:HI     1 "register_operand" "l"))
4649    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4650   "TARGET_THUMB"
4651   "*
4652   abort ();"
4653 )
4654         
4655 ;; We use a DImode scratch because we may occasionally need an additional
4656 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4657 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4658 (define_expand "reload_outhi"
4659   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4660               (match_operand:HI 1 "s_register_operand"        "r")
4661               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4662   "TARGET_EITHER"
4663   "if (TARGET_ARM)
4664      arm_reload_out_hi (operands);
4665    else
4666      thumb_reload_out_hi (operands);
4667   DONE;
4668   "
4669 )
4670
4671 (define_expand "reload_inhi"
4672   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4673               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4674               (match_operand:DI 2 "s_register_operand" "=&r")])]
4675   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4676   "
4677   if (TARGET_ARM)
4678     arm_reload_in_hi (operands);
4679   else
4680     thumb_reload_out_hi (operands);
4681   DONE;
4682 ")
4683
4684 (define_expand "movqi"
4685   [(set (match_operand:QI 0 "general_operand" "")
4686         (match_operand:QI 1 "general_operand" ""))]
4687   "TARGET_EITHER"
4688   "
4689   if (TARGET_ARM)
4690     {
4691       /* Everything except mem = const or mem = mem can be done easily */
4692
4693       if (!no_new_pseudos)
4694         {
4695           if (GET_CODE (operands[1]) == CONST_INT)
4696             {
4697               rtx reg = gen_reg_rtx (SImode);
4698
4699               emit_insn (gen_movsi (reg, operands[1]));
4700               operands[1] = gen_lowpart (QImode, reg);
4701             }
4702           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4703             {
4704               rtx reg = gen_reg_rtx (SImode);
4705
4706               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4707               operands[1] = gen_lowpart (QImode, reg);
4708             }
4709           if (GET_CODE (operands[0]) == MEM)
4710             operands[1] = force_reg (QImode, operands[1]);
4711         }
4712     }
4713   else /* TARGET_THUMB */
4714     {
4715       if (!no_new_pseudos)
4716         {
4717           if (GET_CODE (operands[0]) != REG)
4718             operands[1] = force_reg (QImode, operands[1]);
4719
4720           /* ??? We shouldn't really get invalid addresses here, but this can
4721              happen if we are passed a SP (never OK for HImode/QImode) or
4722              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4723              HImode/QImode) relative address.  */
4724           /* ??? This should perhaps be fixed elsewhere, for instance, in
4725              fixup_stack_1, by checking for other kinds of invalid addresses,
4726              e.g. a bare reference to a virtual register.  This may confuse the
4727              alpha though, which must handle this case differently.  */
4728           if (GET_CODE (operands[0]) == MEM
4729               && !memory_address_p (GET_MODE (operands[0]),
4730                                      XEXP (operands[0], 0)))
4731             operands[0]
4732               = replace_equiv_address (operands[0],
4733                                        copy_to_reg (XEXP (operands[0], 0)));
4734           if (GET_CODE (operands[1]) == MEM
4735               && !memory_address_p (GET_MODE (operands[1]),
4736                                     XEXP (operands[1], 0)))
4737              operands[1]
4738                = replace_equiv_address (operands[1],
4739                                         copy_to_reg (XEXP (operands[1], 0)));
4740         }
4741       /* Handle loading a large integer during reload */
4742       else if (GET_CODE (operands[1]) == CONST_INT
4743                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4744         {
4745           /* Writing a constant to memory needs a scratch, which should
4746              be handled with SECONDARY_RELOADs.  */
4747           if (GET_CODE (operands[0]) != REG)
4748             abort ();
4749
4750           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4751           emit_insn (gen_movsi (operands[0], operands[1]));
4752           DONE;
4753        }
4754     }
4755   "
4756 )
4757
4758
4759 (define_insn "*arm_movqi_insn"
4760   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4761         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4762   "TARGET_ARM
4763    && (   register_operand (operands[0], QImode)
4764        || register_operand (operands[1], QImode))"
4765   "@
4766    mov%?\\t%0, %1
4767    mvn%?\\t%0, #%B1
4768    ldr%?b\\t%0, %1
4769    str%?b\\t%1, %0"
4770   [(set_attr "type" "*,*,load,store1")
4771    (set_attr "predicable" "yes")]
4772 )
4773
4774 (define_insn "*thumb_movqi_insn"
4775   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4776         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4777   "TARGET_THUMB
4778    && (   register_operand (operands[0], QImode)
4779        || register_operand (operands[1], QImode))"
4780   "@
4781    add\\t%0, %1, #0
4782    ldrb\\t%0, %1
4783    strb\\t%1, %0
4784    mov\\t%0, %1
4785    mov\\t%0, %1
4786    mov\\t%0, %1"
4787   [(set_attr "length" "2")
4788    (set_attr "type" "*,load,store1,*,*,*")
4789    (set_attr "pool_range" "*,32,*,*,*,*")]
4790 )
4791
4792 (define_expand "movsf"
4793   [(set (match_operand:SF 0 "general_operand" "")
4794         (match_operand:SF 1 "general_operand" ""))]
4795   "TARGET_EITHER"
4796   "
4797   if (TARGET_ARM)
4798     {
4799       if (GET_CODE (operands[0]) == MEM)
4800         operands[1] = force_reg (SFmode, operands[1]);
4801     }
4802   else /* TARGET_THUMB */
4803     {
4804       if (!no_new_pseudos)
4805         {
4806            if (GET_CODE (operands[0]) != REG)
4807              operands[1] = force_reg (SFmode, operands[1]);
4808         }
4809     }
4810   "
4811 )
4812
4813 (define_split
4814   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4815         (match_operand:SF 1 "immediate_operand" ""))]
4816   "TARGET_ARM
4817    && !TARGET_HARD_FLOAT
4818    && reload_completed
4819    && GET_CODE (operands[1]) == CONST_DOUBLE"
4820   [(set (match_dup 2) (match_dup 3))]
4821   "
4822   operands[2] = gen_lowpart (SImode, operands[0]);
4823   operands[3] = gen_lowpart (SImode, operands[1]);
4824   if (operands[2] == 0 || operands[3] == 0)
4825     FAIL;
4826   "
4827 )
4828
4829 (define_insn "*arm_movsf_hard_insn"
4830   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4831         (match_operand:SF 1 "general_operand"      "fG,H,mE,f,r,f,r,mE,r"))]
4832   "TARGET_ARM
4833    && TARGET_HARD_FLOAT
4834    && (GET_CODE (operands[0]) != MEM
4835        || register_operand (operands[1], SFmode))"
4836   "@
4837    mvf%?s\\t%0, %1
4838    mnf%?s\\t%0, #%N1
4839    ldf%?s\\t%0, %1
4840    stf%?s\\t%1, %0
4841    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4842    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4843    mov%?\\t%0, %1
4844    ldr%?\\t%0, %1\\t%@ float
4845    str%?\\t%1, %0\\t%@ float"
4846   [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4847    (set_attr "predicable" "yes")
4848    (set_attr "type"
4849          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4850    (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4851    (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4852 )
4853
4854 ;; Exactly the same as above, except that all `f' cases are deleted.
4855 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4856 ;; when -msoft-float.
4857
4858 (define_insn "*arm_movsf_soft_insn"
4859   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4860         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4861   "TARGET_ARM
4862    && !TARGET_CIRRUS
4863    && TARGET_SOFT_FLOAT
4864    && (GET_CODE (operands[0]) != MEM
4865        || register_operand (operands[1], SFmode))"
4866   "@
4867    mov%?\\t%0, %1
4868    ldr%?\\t%0, %1\\t%@ float
4869    str%?\\t%1, %0\\t%@ float"
4870   [(set_attr "length" "4,4,4")
4871    (set_attr "predicable" "yes")
4872    (set_attr "type" "*,load,store1")
4873    (set_attr "pool_range" "*,4096,*")
4874    (set_attr "neg_pool_range" "*,4084,*")]
4875 )
4876
4877 ;;; ??? This should have alternatives for constants.
4878 (define_insn "*thumb_movsf_insn"
4879   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4880         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4881   "TARGET_THUMB
4882    && (   register_operand (operands[0], SFmode) 
4883        || register_operand (operands[1], SFmode))"
4884   "@
4885    add\\t%0, %1, #0
4886    ldmia\\t%1, {%0}
4887    stmia\\t%0, {%1}
4888    ldr\\t%0, %1
4889    str\\t%1, %0
4890    mov\\t%0, %1
4891    mov\\t%0, %1"
4892   [(set_attr "length" "2")
4893    (set_attr "type" "*,load,store1,load,store1,*,*")
4894    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4895 )
4896
4897 (define_expand "movdf"
4898   [(set (match_operand:DF 0 "general_operand" "")
4899         (match_operand:DF 1 "general_operand" ""))]
4900   "TARGET_EITHER"
4901   "
4902   if (TARGET_ARM)
4903     {
4904       if (GET_CODE (operands[0]) == MEM)
4905         operands[1] = force_reg (DFmode, operands[1]);
4906     }
4907   else /* TARGET_THUMB */
4908     {
4909       if (!no_new_pseudos)
4910         {
4911           if (GET_CODE (operands[0]) != REG)
4912             operands[1] = force_reg (DFmode, operands[1]);
4913         }
4914     }
4915   "
4916 )
4917
4918 ;; Reloading a df mode value stored in integer regs to memory can require a
4919 ;; scratch reg.
4920 (define_expand "reload_outdf"
4921   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4922    (match_operand:DF 1 "s_register_operand" "r")
4923    (match_operand:SI 2 "s_register_operand" "=&r")]
4924   "TARGET_ARM"
4925   "
4926   {
4927     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4928
4929     if (code == REG)
4930       operands[2] = XEXP (operands[0], 0);
4931     else if (code == POST_INC || code == PRE_DEC)
4932       {
4933         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4934         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4935         emit_insn (gen_movdi (operands[0], operands[1]));
4936         DONE;
4937       }
4938     else if (code == PRE_INC)
4939       {
4940         rtx reg = XEXP (XEXP (operands[0], 0), 0);
4941
4942         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4943         operands[2] = reg;
4944       }
4945     else if (code == POST_DEC)
4946       operands[2] = XEXP (XEXP (operands[0], 0), 0);
4947     else
4948       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4949                              XEXP (XEXP (operands[0], 0), 1)));
4950
4951     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4952                             operands[1]));
4953
4954     if (code == POST_DEC)
4955       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4956
4957     DONE;
4958   }"
4959 )
4960
4961 (define_insn "*movdf_hard_insn"
4962   [(set (match_operand:DF 0 "nonimmediate_operand"
4963                                                 "=r,Q,r,m,r, f, f,f, m,!f,!r")
4964         (match_operand:DF 1 "general_operand"
4965                                                 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
4966   "TARGET_ARM
4967    && TARGET_HARD_FLOAT
4968    && (GET_CODE (operands[0]) != MEM
4969        || register_operand (operands[1], DFmode))"
4970   "*
4971   {
4972   switch (which_alternative)
4973     {
4974     default:
4975     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
4976     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
4977     case 2: case 3: case 4: return output_move_double (operands);
4978     case 5: return \"mvf%?d\\t%0, %1\";
4979     case 6: return \"mnf%?d\\t%0, #%N1\";
4980     case 7: return \"ldf%?d\\t%0, %1\";
4981     case 8: return \"stf%?d\\t%1, %0\";
4982     case 9: return output_mov_double_fpu_from_arm (operands);
4983     case 10: return output_mov_double_arm_from_fpu (operands);
4984     }
4985   }
4986   "
4987   [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
4988    (set_attr "predicable" "yes")
4989    (set_attr "type"
4990     "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
4991    (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
4992    (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
4993 )
4994
4995 ;; Software floating point version.  This is essentially the same as movdi.
4996 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
4997 ;; an `f' reg.
4998
4999 (define_insn "*movdf_soft_insn"
5000   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5001         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5002   "TARGET_ARM && TARGET_SOFT_FLOAT
5003    && !TARGET_CIRRUS
5004   "
5005   "* return output_move_double (operands);"
5006   [(set_attr "length" "8,8,8")
5007    (set_attr "type" "*,load,store2")
5008    (set_attr "pool_range" "1020")
5009    (set_attr "neg_pool_range" "1008")]
5010 )
5011
5012 ;;; ??? This should have alternatives for constants.
5013 ;;; ??? This was originally identical to the movdi_insn pattern.
5014 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5015 ;;; thumb_reorg with a memory reference.
5016 (define_insn "*thumb_movdf_insn"
5017   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5018         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5019   "TARGET_THUMB
5020    && (   register_operand (operands[0], DFmode)
5021        || register_operand (operands[1], DFmode))"
5022   "*
5023   switch (which_alternative)
5024     {
5025     default:
5026     case 0:
5027       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5028         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5029       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5030     case 1:
5031       return \"ldmia\\t%1, {%0, %H0}\";
5032     case 2:
5033       return \"stmia\\t%0, {%1, %H1}\";
5034     case 3:
5035       return thumb_load_double_from_address (operands);
5036     case 4:
5037       operands[2] = gen_rtx (MEM, SImode,
5038                              plus_constant (XEXP (operands[0], 0), 4));
5039       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5040       return \"\";
5041     case 5:
5042       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5043         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5044       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5045     }
5046   "
5047   [(set_attr "length" "4,2,2,6,4,4")
5048    (set_attr "type" "*,load,store2,load,store2,*")
5049    (set_attr "pool_range" "*,*,*,1020,*,*")]
5050 )
5051
5052
5053 ;; Saving and restoring the floating point registers in the prologue should
5054 ;; be done in XFmode, even though we don't support that for anything else
5055 ;; (Well, strictly it's 'internal representation', but that's effectively
5056 ;; XFmode).
5057
5058 (define_insn "*movxf_hard_insn"
5059   [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5060         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5061   "TARGET_ARM && TARGET_HARD_FLOAT && reload_completed"
5062   "*
5063   switch (which_alternative)
5064     {
5065     default:
5066     case 0: return \"mvf%?e\\t%0, %1\";
5067     case 1: return \"mnf%?e\\t%0, #%N1\";
5068     case 2: return \"ldf%?e\\t%0, %1\";
5069     case 3: return \"stf%?e\\t%1, %0\";
5070     case 4: return output_mov_long_double_fpu_from_arm (operands);
5071     case 5: return output_mov_long_double_arm_from_fpu (operands);
5072     case 6: return output_mov_long_double_arm_from_arm (operands);
5073     }
5074   "
5075   [(set_attr "length" "4,4,4,4,8,8,12")
5076    (set_attr "predicable" "yes")
5077    (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5078    (set_attr "pool_range" "*,*,1024,*,*,*,*")
5079    (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5080 )
5081 \f
5082
5083 ;; load- and store-multiple insns
5084 ;; The arm can load/store any set of registers, provided that they are in
5085 ;; ascending order; but that is beyond GCC so stick with what it knows.
5086
5087 (define_expand "load_multiple"
5088   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5089                           (match_operand:SI 1 "" ""))
5090                      (use (match_operand:SI 2 "" ""))])]
5091   "TARGET_ARM"
5092   "
5093   /* Support only fixed point registers.  */
5094   if (GET_CODE (operands[2]) != CONST_INT
5095       || INTVAL (operands[2]) > 14
5096       || INTVAL (operands[2]) < 2
5097       || GET_CODE (operands[1]) != MEM
5098       || GET_CODE (operands[0]) != REG
5099       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5100       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5101     FAIL;
5102
5103   operands[3]
5104     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5105                              force_reg (SImode, XEXP (operands[1], 0)),
5106                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5107                              MEM_IN_STRUCT_P(operands[1]),
5108                              MEM_SCALAR_P (operands[1]));
5109   "
5110 )
5111
5112 ;; Load multiple with write-back
5113
5114 (define_insn "*ldmsi_postinc4"
5115   [(match_parallel 0 "load_multiple_operation"
5116     [(set (match_operand:SI 1 "s_register_operand" "=r")
5117           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5118                    (const_int 16)))
5119      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5120           (mem:SI (match_dup 2)))
5121      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5122           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5123      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5124           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5125      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5126           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5127   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5128   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5129   [(set_attr "type" "load")
5130    (set_attr "predicable" "yes")]
5131 )
5132
5133 (define_insn "*ldmsi_postinc3"
5134   [(match_parallel 0 "load_multiple_operation"
5135     [(set (match_operand:SI 1 "s_register_operand" "=r")
5136           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5137                    (const_int 12)))
5138      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5139           (mem:SI (match_dup 2)))
5140      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5141           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5142      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5143           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5144   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5145   "ldm%?ia\\t%1!, {%3, %4, %5}"
5146   [(set_attr "type" "load")
5147    (set_attr "predicable" "yes")]
5148 )
5149
5150 (define_insn "*ldmsi_postinc2"
5151   [(match_parallel 0 "load_multiple_operation"
5152     [(set (match_operand:SI 1 "s_register_operand" "=r")
5153           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5154                    (const_int 8)))
5155      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5156           (mem:SI (match_dup 2)))
5157      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5158           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5159   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5160   "ldm%?ia\\t%1!, {%3, %4}"
5161   [(set_attr "type" "load")
5162    (set_attr "predicable" "yes")]
5163 )
5164
5165 ;; Ordinary load multiple
5166
5167 (define_insn "*ldmsi4"
5168   [(match_parallel 0 "load_multiple_operation"
5169     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5170           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5171      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5172           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5173      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5174           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5175      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5176           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5177   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5178   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5179   [(set_attr "type" "load")
5180    (set_attr "predicable" "yes")]
5181 )
5182
5183 (define_insn "*ldmsi3"
5184   [(match_parallel 0 "load_multiple_operation"
5185     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5186           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5187      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5188           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5189      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5190           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5191   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5192   "ldm%?ia\\t%1, {%2, %3, %4}"
5193   [(set_attr "type" "load")
5194    (set_attr "predicable" "yes")]
5195 )
5196
5197 (define_insn "*ldmsi2"
5198   [(match_parallel 0 "load_multiple_operation"
5199     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5200           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5201      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5202           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5203   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5204   "ldm%?ia\\t%1, {%2, %3}"
5205   [(set_attr "type" "load")
5206    (set_attr "predicable" "yes")]
5207 )
5208
5209 (define_expand "store_multiple"
5210   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5211                           (match_operand:SI 1 "" ""))
5212                      (use (match_operand:SI 2 "" ""))])]
5213   "TARGET_ARM"
5214   "
5215   /* Support only fixed point registers */
5216   if (GET_CODE (operands[2]) != CONST_INT
5217       || INTVAL (operands[2]) > 14
5218       || INTVAL (operands[2]) < 2
5219       || GET_CODE (operands[1]) != REG
5220       || GET_CODE (operands[0]) != MEM
5221       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5222       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5223     FAIL;
5224
5225   operands[3]
5226     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5227                               force_reg (SImode, XEXP (operands[0], 0)),
5228                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5229                               MEM_IN_STRUCT_P(operands[0]), 
5230                               MEM_SCALAR_P (operands[0]));
5231   "
5232 )
5233
5234 ;; Store multiple with write-back
5235
5236 (define_insn "*stmsi_postinc4"
5237   [(match_parallel 0 "store_multiple_operation"
5238     [(set (match_operand:SI 1 "s_register_operand" "=r")
5239           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5240                    (const_int 16)))
5241      (set (mem:SI (match_dup 2))
5242           (match_operand:SI 3 "arm_hard_register_operand" ""))
5243      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5244           (match_operand:SI 4 "arm_hard_register_operand" ""))
5245      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5246           (match_operand:SI 5 "arm_hard_register_operand" ""))
5247      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5248           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5249   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5250   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5251   [(set_attr "predicable" "yes")
5252    (set_attr "type" "store4")]
5253 )
5254
5255 (define_insn "*stmsi_postinc3"
5256   [(match_parallel 0 "store_multiple_operation"
5257     [(set (match_operand:SI 1 "s_register_operand" "=r")
5258           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5259                    (const_int 12)))
5260      (set (mem:SI (match_dup 2))
5261           (match_operand:SI 3 "arm_hard_register_operand" ""))
5262      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5263           (match_operand:SI 4 "arm_hard_register_operand" ""))
5264      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5265           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5266   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5267   "stm%?ia\\t%1!, {%3, %4, %5}"
5268   [(set_attr "predicable" "yes")
5269    (set_attr "type" "store3")]
5270 )
5271
5272 (define_insn "*stmsi_postinc2"
5273   [(match_parallel 0 "store_multiple_operation"
5274     [(set (match_operand:SI 1 "s_register_operand" "=r")
5275           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5276                    (const_int 8)))
5277      (set (mem:SI (match_dup 2))
5278           (match_operand:SI 3 "arm_hard_register_operand" ""))
5279      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5280           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5281   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5282   "stm%?ia\\t%1!, {%3, %4}"
5283   [(set_attr "predicable" "yes")
5284    (set_attr "type" "store2")]
5285 )
5286
5287 ;; Ordinary store multiple
5288
5289 (define_insn "*stmsi4"
5290   [(match_parallel 0 "store_multiple_operation"
5291     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5292           (match_operand:SI 2 "arm_hard_register_operand" ""))
5293      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5294           (match_operand:SI 3 "arm_hard_register_operand" ""))
5295      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5296           (match_operand:SI 4 "arm_hard_register_operand" ""))
5297      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5298           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5299   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5300   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5301   [(set_attr "predicable" "yes")
5302    (set_attr "type" "store4")]
5303 )
5304
5305 (define_insn "*stmsi3"
5306   [(match_parallel 0 "store_multiple_operation"
5307     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5308           (match_operand:SI 2 "arm_hard_register_operand" ""))
5309      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5310           (match_operand:SI 3 "arm_hard_register_operand" ""))
5311      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5312           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5313   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5314   "stm%?ia\\t%1, {%2, %3, %4}"
5315   [(set_attr "predicable" "yes")
5316    (set_attr "type" "store3")]
5317 )
5318
5319 (define_insn "*stmsi2"
5320   [(match_parallel 0 "store_multiple_operation"
5321     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5322           (match_operand:SI 2 "arm_hard_register_operand" ""))
5323      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5324           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5325   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5326   "stm%?ia\\t%1, {%2, %3}"
5327   [(set_attr "predicable" "yes")
5328    (set_attr "type" "store2")]
5329 )
5330
5331 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5332 ;; We could let this apply for blocks of less than this, but it clobbers so
5333 ;; many registers that there is then probably a better way.
5334
5335 (define_expand "movstrqi"
5336   [(match_operand:BLK 0 "general_operand" "")
5337    (match_operand:BLK 1 "general_operand" "")
5338    (match_operand:SI 2 "const_int_operand" "")
5339    (match_operand:SI 3 "const_int_operand" "")]
5340   "TARGET_EITHER"
5341   "
5342   if (TARGET_ARM)
5343     {
5344       if (arm_gen_movstrqi (operands))
5345         DONE;
5346       FAIL;
5347     }
5348   else /* TARGET_THUMB */
5349     {
5350       if (   INTVAL (operands[3]) != 4
5351           || INTVAL (operands[2]) > 48)
5352         FAIL;
5353
5354       thumb_expand_movstrqi (operands);
5355       DONE;
5356     }
5357   "
5358 )
5359
5360 ;; Thumb block-move insns
5361
5362 (define_insn "movmem12b"
5363   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5364         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5365    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5366         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5367    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5368         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5369    (set (match_operand:SI 0 "register_operand" "=l")
5370         (plus:SI (match_dup 2) (const_int 12)))
5371    (set (match_operand:SI 1 "register_operand" "=l")
5372         (plus:SI (match_dup 3) (const_int 12)))
5373    (clobber (match_scratch:SI 4 "=&l"))
5374    (clobber (match_scratch:SI 5 "=&l"))
5375    (clobber (match_scratch:SI 6 "=&l"))]
5376   "TARGET_THUMB"
5377   "* return thumb_output_move_mem_multiple (3, operands);"
5378   [(set_attr "length" "4")
5379    ; This isn't entirely accurate...  It loads as well, but in terms of
5380    ; scheduling the following insn it is better to consider it as a store
5381    (set_attr "type" "store3")]
5382 )
5383
5384 (define_insn "movmem8b"
5385   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5386         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5387    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5388         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5389    (set (match_operand:SI 0 "register_operand" "=l")
5390         (plus:SI (match_dup 2) (const_int 8)))
5391    (set (match_operand:SI 1 "register_operand" "=l")
5392         (plus:SI (match_dup 3) (const_int 8)))
5393    (clobber (match_scratch:SI 4 "=&l"))
5394    (clobber (match_scratch:SI 5 "=&l"))]
5395   "TARGET_THUMB"
5396   "* return thumb_output_move_mem_multiple (2, operands);"
5397   [(set_attr "length" "4")
5398    ; This isn't entirely accurate...  It loads as well, but in terms of
5399    ; scheduling the following insn it is better to consider it as a store
5400    (set_attr "type" "store2")]
5401 )
5402
5403 \f
5404
5405 ;; Compare & branch insns
5406 ;; The range calcualations are based as follows:
5407 ;; For forward branches, the address calculation returns the address of
5408 ;; the next instruction.  This is 2 beyond the branch instruction.
5409 ;; For backward branches, the address calculation returns the address of
5410 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5411 ;; instruction for the shortest sequence, and 4 before the branch instruction
5412 ;; if we have to jump around an unconditional branch.
5413 ;; To the basic branch range the PC offset must be added (this is +4).
5414 ;; So for forward branches we have 
5415 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5416 ;; And for backward branches we have 
5417 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5418 ;;
5419 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5420 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5421
5422 (define_insn "cbranchsi4"
5423   [(set (pc)
5424         (if_then_else
5425             (match_operator                    0 "arm_comparison_operator"
5426                             [(match_operand:SI 1 "register_operand"   "l,r")
5427                              (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5428             (label_ref       (match_operand    3 "" ""))
5429             (pc)))]
5430   "TARGET_THUMB"
5431   "*
5432   output_asm_insn (\"cmp\\t%1, %2\", operands);
5433   switch (get_attr_length (insn))
5434     {
5435     case 4:  return \"b%d0\\t%l3\";
5436     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5437     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5438     }
5439   "
5440   [(set (attr "far_jump")
5441         (if_then_else
5442             (eq_attr "length" "8")
5443             (const_string "yes")
5444             (const_string "no")))
5445    (set (attr "length") 
5446         (if_then_else
5447             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5448                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5449             (const_int 4)
5450             (if_then_else
5451                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5452                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5453                 (const_int 6)
5454                 (const_int 8))))]
5455 )
5456
5457 (define_insn "*negated_cbranchsi4"
5458   [(set (pc)
5459         (if_then_else
5460          (match_operator             0 "arm_comparison_operator"
5461           [(match_operand:SI         1 "register_operand"  "l")
5462            (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5463          (label_ref (match_operand   3 "" ""))
5464          (pc)))]
5465   "TARGET_THUMB"
5466   "*
5467   output_asm_insn (\"cmn\\t%1, %2\", operands);
5468   switch (get_attr_length (insn))
5469     {
5470     case 4:  return \"b%d0\\t%l3\";
5471     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5472     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5473     }
5474   "
5475   [(set (attr "far_jump")
5476         (if_then_else
5477             (eq_attr "length" "8")
5478             (const_string "yes")
5479             (const_string "no")))
5480    (set (attr "length") 
5481         (if_then_else
5482             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5483                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5484             (const_int 4)
5485             (if_then_else
5486                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5487                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5488                 (const_int 6)
5489                 (const_int 8))))]
5490 )
5491
5492
5493 ;; Comparison and test insns
5494
5495 (define_expand "cmpsi"
5496   [(match_operand:SI 0 "s_register_operand" "")
5497    (match_operand:SI 1 "arm_add_operand" "")]
5498   "TARGET_ARM"
5499   "{
5500     arm_compare_op0 = operands[0];
5501     arm_compare_op1 = operands[1];
5502     DONE;
5503   }"
5504 )
5505
5506 (define_expand "cmpsf"
5507   [(match_operand:SF 0 "s_register_operand" "")
5508    (match_operand:SF 1 "fpu_rhs_operand" "")]
5509   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5510   "
5511   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5512     operands[1] = force_reg (SFmode, operands[1]);
5513
5514   arm_compare_op0 = operands[0];
5515   arm_compare_op1 = operands[1];
5516   DONE;
5517   "
5518 )
5519
5520 (define_expand "cmpdf"
5521   [(match_operand:DF 0 "s_register_operand" "")
5522    (match_operand:DF 1 "fpu_rhs_operand" "")]
5523   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5524   "
5525   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5526     operands[1] = force_reg (DFmode, operands[1]);
5527
5528   arm_compare_op0 = operands[0];
5529   arm_compare_op1 = operands[1];
5530   DONE;
5531   "
5532 )
5533
5534 (define_insn "*arm_cmpsi_insn"
5535   [(set (reg:CC CC_REGNUM)
5536         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5537                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5538   "TARGET_ARM"
5539   "@
5540    cmp%?\\t%0, %1
5541    cmn%?\\t%0, #%n1"
5542   [(set_attr "conds" "set")]
5543 )
5544
5545 (define_insn "*cmpsi_shiftsi"
5546   [(set (reg:CC CC_REGNUM)
5547         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
5548                     (match_operator:SI  3 "shift_operator"
5549                      [(match_operand:SI 1 "s_register_operand" "r")
5550                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5551   "TARGET_ARM"
5552   "cmp%?\\t%0, %1%S3"
5553   [(set_attr "conds" "set")
5554    (set_attr "shift" "1")
5555    ]
5556 )
5557
5558 (define_insn "*cmpsi_shiftsi_swp"
5559   [(set (reg:CC_SWP CC_REGNUM)
5560         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5561                          [(match_operand:SI 1 "s_register_operand" "r")
5562                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
5563                         (match_operand:SI 0 "s_register_operand" "r")))]
5564   "TARGET_ARM"
5565   "cmp%?\\t%0, %1%S3"
5566   [(set_attr "conds" "set")
5567    (set_attr "shift" "1")
5568    ]
5569 )
5570
5571 (define_insn "*cmpsi_neg_shiftsi"
5572   [(set (reg:CC CC_REGNUM)
5573         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5574                     (neg:SI (match_operator:SI 3 "shift_operator"
5575                              [(match_operand:SI 1 "s_register_operand" "r")
5576                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5577   "TARGET_ARM"
5578   "cmn%?\\t%0, %1%S3"
5579   [(set_attr "conds" "set")
5580    (set_attr "shift" "1")
5581    ]
5582 )
5583
5584 (define_insn "*cmpsf_insn"
5585   [(set (reg:CCFP CC_REGNUM)
5586         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5587                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5588   "TARGET_ARM && TARGET_HARD_FLOAT"
5589   "@
5590    cmf%?\\t%0, %1
5591    cnf%?\\t%0, #%N1"
5592   [(set_attr "conds" "set")
5593    (set_attr "type" "f_2_r")]
5594 )
5595
5596 (define_insn "*cmpdf_insn"
5597   [(set (reg:CCFP CC_REGNUM)
5598         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5599                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5600   "TARGET_ARM && TARGET_HARD_FLOAT"
5601   "@
5602    cmf%?\\t%0, %1
5603    cnf%?\\t%0, #%N1"
5604   [(set_attr "conds" "set")
5605    (set_attr "type" "f_2_r")]
5606 )
5607
5608 (define_insn "*cmpesfdf_df"
5609   [(set (reg:CCFP CC_REGNUM)
5610         (compare:CCFP (float_extend:DF
5611                        (match_operand:SF 0 "s_register_operand" "f,f"))
5612                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5613   "TARGET_ARM && TARGET_HARD_FLOAT"
5614   "@
5615    cmf%?\\t%0, %1
5616    cnf%?\\t%0, #%N1"
5617   [(set_attr "conds" "set")
5618    (set_attr "type" "f_2_r")]
5619 )
5620
5621 (define_insn "*cmpdf_esfdf"
5622   [(set (reg:CCFP CC_REGNUM)
5623         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5624                       (float_extend:DF
5625                        (match_operand:SF 1 "s_register_operand" "f"))))]
5626   "TARGET_ARM && TARGET_HARD_FLOAT"
5627   "cmf%?\\t%0, %1"
5628   [(set_attr "conds" "set")
5629    (set_attr "type" "f_2_r")]
5630 )
5631
5632 ;; Cirrus SF compare instruction
5633 (define_insn "*cirrus_cmpsf"
5634   [(set (reg:CCFP CC_REGNUM)
5635         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5636                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
5637   "TARGET_ARM && TARGET_CIRRUS"
5638   "cfcmps%?\\tr15, %V0, %V1"
5639   [(set_attr "type"   "mav_farith")
5640    (set_attr "cirrus" "compare")]
5641 )
5642
5643 ;; Cirrus DF compare instruction
5644 (define_insn "*cirrus_cmpdf"
5645   [(set (reg:CCFP CC_REGNUM)
5646         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5647                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
5648   "TARGET_ARM && TARGET_CIRRUS"
5649   "cfcmpd%?\\tr15, %V0, %V1"
5650   [(set_attr "type"   "mav_farith")
5651    (set_attr "cirrus" "compare")]
5652 )
5653
5654 ;; Cirrus DI compare instruction
5655 (define_expand "cmpdi"
5656   [(match_operand:DI 0 "cirrus_fp_register" "")
5657    (match_operand:DI 1 "cirrus_fp_register" "")]
5658   "TARGET_ARM && TARGET_CIRRUS"
5659   "{
5660      arm_compare_op0 = operands[0];
5661      arm_compare_op1 = operands[1];
5662      DONE;
5663    }")
5664
5665 (define_insn "*cirrus_cmpdi"
5666   [(set (reg:CC CC_REGNUM)
5667         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5668                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
5669   "TARGET_ARM && TARGET_CIRRUS"
5670   "cfcmp64%?\\tr15, %V0, %V1"
5671   [(set_attr "type"   "mav_farith")
5672    (set_attr "cirrus" "compare")]
5673 )
5674
5675 (define_insn "*cmpsf_trap"
5676   [(set (reg:CCFPE CC_REGNUM)
5677         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5678                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5679   "TARGET_ARM && TARGET_HARD_FLOAT"
5680   "@
5681    cmf%?e\\t%0, %1
5682    cnf%?e\\t%0, #%N1"
5683   [(set_attr "conds" "set")
5684    (set_attr "type" "f_2_r")]
5685 )
5686
5687 (define_insn "*cmpdf_trap"
5688   [(set (reg:CCFPE CC_REGNUM)
5689         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5690                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5691   "TARGET_ARM && TARGET_HARD_FLOAT"
5692   "@
5693    cmf%?e\\t%0, %1
5694    cnf%?e\\t%0, #%N1"
5695   [(set_attr "conds" "set")
5696    (set_attr "type" "f_2_r")]
5697 )
5698
5699 (define_insn "*cmp_esfdf_df_trap"
5700   [(set (reg:CCFPE CC_REGNUM)
5701         (compare:CCFPE (float_extend:DF
5702                         (match_operand:SF 0 "s_register_operand" "f,f"))
5703                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5704   "TARGET_ARM && TARGET_HARD_FLOAT"
5705   "@
5706    cmf%?e\\t%0, %1
5707    cnf%?e\\t%0, #%N1"
5708   [(set_attr "conds" "set")
5709    (set_attr "type" "f_2_r")]
5710 )
5711
5712 (define_insn "*cmp_df_esfdf_trap"
5713   [(set (reg:CCFPE CC_REGNUM)
5714         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5715                        (float_extend:DF
5716                         (match_operand:SF 1 "s_register_operand" "f"))))]
5717   "TARGET_ARM && TARGET_HARD_FLOAT"
5718   "cmf%?e\\t%0, %1"
5719   [(set_attr "conds" "set")
5720    (set_attr "type" "f_2_r")]
5721 )
5722
5723 ; This insn allows redundant compares to be removed by cse, nothing should
5724 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5725 ; is deleted later on. The match_dup will match the mode here, so that
5726 ; mode changes of the condition codes aren't lost by this even though we don't
5727 ; specify what they are.
5728
5729 (define_insn "*deleted_compare"
5730   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5731   "TARGET_ARM"
5732   "\\t%@ deleted compare"
5733   [(set_attr "conds" "set")
5734    (set_attr "length" "0")]
5735 )
5736
5737 \f
5738 ;; Conditional branch insns
5739
5740 (define_expand "beq"
5741   [(set (pc)
5742         (if_then_else (eq (match_dup 1) (const_int 0))
5743                       (label_ref (match_operand 0 "" ""))
5744                       (pc)))]
5745   "TARGET_ARM"
5746   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5747 )
5748
5749 (define_expand "bne"
5750   [(set (pc)
5751         (if_then_else (ne (match_dup 1) (const_int 0))
5752                       (label_ref (match_operand 0 "" ""))
5753                       (pc)))]
5754   "TARGET_ARM"
5755   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5756 )
5757
5758 (define_expand "bgt"
5759   [(set (pc)
5760         (if_then_else (gt (match_dup 1) (const_int 0))
5761                       (label_ref (match_operand 0 "" ""))
5762                       (pc)))]
5763   "TARGET_ARM"
5764   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5765 )
5766
5767 (define_expand "ble"
5768   [(set (pc)
5769         (if_then_else (le (match_dup 1) (const_int 0))
5770                       (label_ref (match_operand 0 "" ""))
5771                       (pc)))]
5772   "TARGET_ARM"
5773   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5774 )
5775
5776 (define_expand "bge"
5777   [(set (pc)
5778         (if_then_else (ge (match_dup 1) (const_int 0))
5779                       (label_ref (match_operand 0 "" ""))
5780                       (pc)))]
5781   "TARGET_ARM"
5782   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5783 )
5784
5785 (define_expand "blt"
5786   [(set (pc)
5787         (if_then_else (lt (match_dup 1) (const_int 0))
5788                       (label_ref (match_operand 0 "" ""))
5789                       (pc)))]
5790   "TARGET_ARM"
5791   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5792 )
5793
5794 (define_expand "bgtu"
5795   [(set (pc)
5796         (if_then_else (gtu (match_dup 1) (const_int 0))
5797                       (label_ref (match_operand 0 "" ""))
5798                       (pc)))]
5799   "TARGET_ARM"
5800   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5801 )
5802
5803 (define_expand "bleu"
5804   [(set (pc)
5805         (if_then_else (leu (match_dup 1) (const_int 0))
5806                       (label_ref (match_operand 0 "" ""))
5807                       (pc)))]
5808   "TARGET_ARM"
5809   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5810 )
5811
5812 (define_expand "bgeu"
5813   [(set (pc)
5814         (if_then_else (geu (match_dup 1) (const_int 0))
5815                       (label_ref (match_operand 0 "" ""))
5816                       (pc)))]
5817   "TARGET_ARM"
5818   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5819 )
5820
5821 (define_expand "bltu"
5822   [(set (pc)
5823         (if_then_else (ltu (match_dup 1) (const_int 0))
5824                       (label_ref (match_operand 0 "" ""))
5825                       (pc)))]
5826   "TARGET_ARM"
5827   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5828 )
5829
5830 (define_expand "bunordered"
5831   [(set (pc)
5832         (if_then_else (unordered (match_dup 1) (const_int 0))
5833                       (label_ref (match_operand 0 "" ""))
5834                       (pc)))]
5835   "TARGET_ARM && TARGET_HARD_FLOAT"
5836   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5837                                       arm_compare_op1);"
5838 )
5839
5840 (define_expand "bordered"
5841   [(set (pc)
5842         (if_then_else (ordered (match_dup 1) (const_int 0))
5843                       (label_ref (match_operand 0 "" ""))
5844                       (pc)))]
5845   "TARGET_ARM && TARGET_HARD_FLOAT"
5846   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5847                                       arm_compare_op1);"
5848 )
5849
5850 (define_expand "bungt"
5851   [(set (pc)
5852         (if_then_else (ungt (match_dup 1) (const_int 0))
5853                       (label_ref (match_operand 0 "" ""))
5854                       (pc)))]
5855   "TARGET_ARM && TARGET_HARD_FLOAT"
5856   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5857 )
5858
5859 (define_expand "bunlt"
5860   [(set (pc)
5861         (if_then_else (unlt (match_dup 1) (const_int 0))
5862                       (label_ref (match_operand 0 "" ""))
5863                       (pc)))]
5864   "TARGET_ARM && TARGET_HARD_FLOAT"
5865   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5866 )
5867
5868 (define_expand "bunge"
5869   [(set (pc)
5870         (if_then_else (unge (match_dup 1) (const_int 0))
5871                       (label_ref (match_operand 0 "" ""))
5872                       (pc)))]
5873   "TARGET_ARM && TARGET_HARD_FLOAT"
5874   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5875 )
5876
5877 (define_expand "bunle"
5878   [(set (pc)
5879         (if_then_else (unle (match_dup 1) (const_int 0))
5880                       (label_ref (match_operand 0 "" ""))
5881                       (pc)))]
5882   "TARGET_ARM && TARGET_HARD_FLOAT"
5883   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5884 )
5885
5886 ;; The following two patterns need two branch instructions, since there is
5887 ;; no single instruction that will handle all cases.
5888 (define_expand "buneq"
5889   [(set (pc)
5890         (if_then_else (uneq (match_dup 1) (const_int 0))
5891                       (label_ref (match_operand 0 "" ""))
5892                       (pc)))]
5893   "TARGET_ARM && TARGET_HARD_FLOAT"
5894   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5895 )
5896
5897 (define_expand "bltgt"
5898   [(set (pc)
5899         (if_then_else (ltgt (match_dup 1) (const_int 0))
5900                       (label_ref (match_operand 0 "" ""))
5901                       (pc)))]
5902   "TARGET_ARM && TARGET_HARD_FLOAT"
5903   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5904 )
5905
5906 ;;
5907 ;; Patterns to match conditional branch insns.
5908 ;;
5909
5910 ; Special pattern to match UNEQ.
5911 (define_insn "*arm_buneq"
5912   [(set (pc)
5913         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5914                       (label_ref (match_operand 0 "" ""))
5915                       (pc)))]
5916   "TARGET_ARM && TARGET_HARD_FLOAT"
5917   "*
5918   if (arm_ccfsm_state != 0)
5919     abort ();
5920
5921   return \"bvs\\t%l0\;beq\\t%l0\";
5922   "
5923   [(set_attr "conds" "jump_clob")
5924    (set_attr "length" "8")]
5925 )
5926
5927 ; Special pattern to match LTGT.
5928 (define_insn "*arm_bltgt"
5929   [(set (pc)
5930         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5931                       (label_ref (match_operand 0 "" ""))
5932                       (pc)))]
5933   "TARGET_ARM && TARGET_HARD_FLOAT"
5934   "*
5935   if (arm_ccfsm_state != 0)
5936     abort ();
5937
5938   return \"bmi\\t%l0\;bgt\\t%l0\";
5939   "
5940   [(set_attr "conds" "jump_clob")
5941    (set_attr "length" "8")]
5942 )
5943
5944 (define_insn "*arm_cond_branch"
5945   [(set (pc)
5946         (if_then_else (match_operator 1 "arm_comparison_operator"
5947                        [(match_operand 2 "cc_register" "") (const_int 0)])
5948                       (label_ref (match_operand 0 "" ""))
5949                       (pc)))]
5950   "TARGET_ARM"
5951   "*
5952   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5953     {
5954       arm_ccfsm_state += 2;
5955       return \"\";
5956     }
5957   return \"b%d1\\t%l0\";
5958   "
5959   [(set_attr "conds" "use")]
5960 )
5961
5962 ; Special pattern to match reversed UNEQ.
5963 (define_insn "*arm_buneq_reversed"
5964   [(set (pc)
5965         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5966                       (pc)
5967                       (label_ref (match_operand 0 "" ""))))]
5968   "TARGET_ARM && TARGET_HARD_FLOAT"
5969   "*
5970   if (arm_ccfsm_state != 0)
5971     abort ();
5972
5973   return \"bmi\\t%l0\;bgt\\t%l0\";
5974   "
5975   [(set_attr "conds" "jump_clob")
5976    (set_attr "length" "8")]
5977 )
5978
5979 ; Special pattern to match reversed LTGT.
5980 (define_insn "*arm_bltgt_reversed"
5981   [(set (pc)
5982         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5983                       (pc)
5984                       (label_ref (match_operand 0 "" ""))))]
5985   "TARGET_ARM && TARGET_HARD_FLOAT"
5986   "*
5987   if (arm_ccfsm_state != 0)
5988     abort ();
5989
5990   return \"bvs\\t%l0\;beq\\t%l0\";
5991   "
5992   [(set_attr "conds" "jump_clob")
5993    (set_attr "length" "8")]
5994 )
5995
5996 (define_insn "*arm_cond_branch_reversed"
5997   [(set (pc)
5998         (if_then_else (match_operator 1 "arm_comparison_operator"
5999                        [(match_operand 2 "cc_register" "") (const_int 0)])
6000                       (pc)
6001                       (label_ref (match_operand 0 "" ""))))]
6002   "TARGET_ARM"
6003   "*
6004   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6005     {
6006       arm_ccfsm_state += 2;
6007       return \"\";
6008     }
6009   return \"b%D1\\t%l0\";
6010   "
6011   [(set_attr "conds" "use")]
6012 )
6013
6014 \f
6015
6016 ; scc insns
6017
6018 (define_expand "seq"
6019   [(set (match_operand:SI 0 "s_register_operand" "=r")
6020         (eq:SI (match_dup 1) (const_int 0)))]
6021   "TARGET_ARM"
6022   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6023 )
6024
6025 (define_expand "sne"
6026   [(set (match_operand:SI 0 "s_register_operand" "=r")
6027         (ne:SI (match_dup 1) (const_int 0)))]
6028   "TARGET_ARM"
6029   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6030 )
6031
6032 (define_expand "sgt"
6033   [(set (match_operand:SI 0 "s_register_operand" "=r")
6034         (gt:SI (match_dup 1) (const_int 0)))]
6035   "TARGET_ARM"
6036   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6037 )
6038
6039 (define_expand "sle"
6040   [(set (match_operand:SI 0 "s_register_operand" "=r")
6041         (le:SI (match_dup 1) (const_int 0)))]
6042   "TARGET_ARM"
6043   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6044 )
6045
6046 (define_expand "sge"
6047   [(set (match_operand:SI 0 "s_register_operand" "=r")
6048         (ge:SI (match_dup 1) (const_int 0)))]
6049   "TARGET_ARM"
6050   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6051 )
6052
6053 (define_expand "slt"
6054   [(set (match_operand:SI 0 "s_register_operand" "=r")
6055         (lt:SI (match_dup 1) (const_int 0)))]
6056   "TARGET_ARM"
6057   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6058 )
6059
6060 (define_expand "sgtu"
6061   [(set (match_operand:SI 0 "s_register_operand" "=r")
6062         (gtu:SI (match_dup 1) (const_int 0)))]
6063   "TARGET_ARM"
6064   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6065 )
6066
6067 (define_expand "sleu"
6068   [(set (match_operand:SI 0 "s_register_operand" "=r")
6069         (leu:SI (match_dup 1) (const_int 0)))]
6070   "TARGET_ARM"
6071   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6072 )
6073
6074 (define_expand "sgeu"
6075   [(set (match_operand:SI 0 "s_register_operand" "=r")
6076         (geu:SI (match_dup 1) (const_int 0)))]
6077   "TARGET_ARM"
6078   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6079 )
6080
6081 (define_expand "sltu"
6082   [(set (match_operand:SI 0 "s_register_operand" "=r")
6083         (ltu:SI (match_dup 1) (const_int 0)))]
6084   "TARGET_ARM"
6085   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6086 )
6087
6088 (define_expand "sunordered"
6089   [(set (match_operand:SI 0 "s_register_operand" "=r")
6090         (unordered:SI (match_dup 1) (const_int 0)))]
6091   "TARGET_ARM && TARGET_HARD_FLOAT"
6092   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6093                                       arm_compare_op1);"
6094 )
6095
6096 (define_expand "sordered"
6097   [(set (match_operand:SI 0 "s_register_operand" "=r")
6098         (ordered:SI (match_dup 1) (const_int 0)))]
6099   "TARGET_ARM && TARGET_HARD_FLOAT"
6100   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6101                                       arm_compare_op1);"
6102 )
6103
6104 (define_expand "sungt"
6105   [(set (match_operand:SI 0 "s_register_operand" "=r")
6106         (ungt:SI (match_dup 1) (const_int 0)))]
6107   "TARGET_ARM && TARGET_HARD_FLOAT"
6108   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6109                                       arm_compare_op1);"
6110 )
6111
6112 (define_expand "sunge"
6113   [(set (match_operand:SI 0 "s_register_operand" "=r")
6114         (unge:SI (match_dup 1) (const_int 0)))]
6115   "TARGET_ARM && TARGET_HARD_FLOAT"
6116   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6117                                       arm_compare_op1);"
6118 )
6119
6120 (define_expand "sunlt"
6121   [(set (match_operand:SI 0 "s_register_operand" "=r")
6122         (unlt:SI (match_dup 1) (const_int 0)))]
6123   "TARGET_ARM && TARGET_HARD_FLOAT"
6124   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6125                                       arm_compare_op1);"
6126 )
6127
6128 (define_expand "sunle"
6129   [(set (match_operand:SI 0 "s_register_operand" "=r")
6130         (unle:SI (match_dup 1) (const_int 0)))]
6131   "TARGET_ARM && TARGET_HARD_FLOAT"
6132   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6133                                       arm_compare_op1);"
6134 )
6135
6136 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6137 ;;; simple ARM instructions. 
6138 ;
6139 ; (define_expand "suneq"
6140 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6141 ;       (uneq:SI (match_dup 1) (const_int 0)))]
6142 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6143 ;   "abort ();"
6144 ; )
6145 ;
6146 ; (define_expand "sltgt"
6147 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6148 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
6149 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6150 ;   "abort ();"
6151 ; )
6152
6153 (define_insn "*mov_scc"
6154   [(set (match_operand:SI 0 "s_register_operand" "=r")
6155         (match_operator:SI 1 "arm_comparison_operator"
6156          [(match_operand 2 "cc_register" "") (const_int 0)]))]
6157   "TARGET_ARM"
6158   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6159   [(set_attr "conds" "use")
6160    (set_attr "length" "8")]
6161 )
6162
6163 (define_insn "*mov_negscc"
6164   [(set (match_operand:SI 0 "s_register_operand" "=r")
6165         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6166                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6167   "TARGET_ARM"
6168   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6169   [(set_attr "conds" "use")
6170    (set_attr "length" "8")]
6171 )
6172
6173 (define_insn "*mov_notscc"
6174   [(set (match_operand:SI 0 "s_register_operand" "=r")
6175         (not:SI (match_operator:SI 1 "arm_comparison_operator"
6176                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6177   "TARGET_ARM"
6178   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6179   [(set_attr "conds" "use")
6180    (set_attr "length" "8")]
6181 )
6182
6183 \f
6184 ;; Conditional move insns
6185
6186 (define_expand "movsicc"
6187   [(set (match_operand:SI 0 "s_register_operand" "")
6188         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6189                          (match_operand:SI 2 "arm_not_operand" "")
6190                          (match_operand:SI 3 "arm_not_operand" "")))]
6191   "TARGET_ARM"
6192   "
6193   {
6194     enum rtx_code code = GET_CODE (operands[1]);
6195     rtx ccreg;
6196
6197     if (code == UNEQ || code == LTGT)
6198       FAIL;
6199
6200     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6201     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6202   }"
6203 )
6204
6205 (define_expand "movsfcc"
6206   [(set (match_operand:SF 0 "s_register_operand" "")
6207         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6208                          (match_operand:SF 2 "s_register_operand" "")
6209                          (match_operand:SF 3 "nonmemory_operand" "")))]
6210   "TARGET_ARM"
6211   "
6212   {
6213     enum rtx_code code = GET_CODE (operands[1]);
6214     rtx ccreg;
6215
6216     if (code == UNEQ || code == LTGT)
6217       FAIL;
6218
6219     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6220        Otherwise, ensure it is a valid FP add operand */
6221     if ((!TARGET_HARD_FLOAT)
6222         || (!fpu_add_operand (operands[3], SFmode)))
6223       operands[3] = force_reg (SFmode, operands[3]);
6224
6225     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6226     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6227   }"
6228 )
6229
6230 (define_expand "movdfcc"
6231   [(set (match_operand:DF 0 "s_register_operand" "")
6232         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6233                          (match_operand:DF 2 "s_register_operand" "")
6234                          (match_operand:DF 3 "fpu_add_operand" "")))]
6235   "TARGET_ARM && TARGET_HARD_FLOAT"
6236   "
6237   {
6238     enum rtx_code code = GET_CODE (operands[1]);
6239     rtx ccreg;
6240
6241     if (code == UNEQ || code == LTGT)
6242       FAIL;
6243
6244     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6245     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6246   }"
6247 )
6248
6249 (define_insn "*movsicc_insn"
6250   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6251         (if_then_else:SI
6252          (match_operator 3 "arm_comparison_operator"
6253           [(match_operand 4 "cc_register" "") (const_int 0)])
6254          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6255          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6256   "TARGET_ARM"
6257   "@
6258    mov%D3\\t%0, %2
6259    mvn%D3\\t%0, #%B2
6260    mov%d3\\t%0, %1
6261    mvn%d3\\t%0, #%B1
6262    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6263    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6264    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6265    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6266   [(set_attr "length" "4,4,4,4,8,8,8,8")
6267    (set_attr "conds" "use")]
6268 )
6269
6270 (define_insn "*movsfcc_hard_insn"
6271   [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6272         (if_then_else:SF
6273          (match_operator 3 "arm_comparison_operator" 
6274           [(match_operand 4 "cc_register" "") (const_int 0)])
6275          (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6276          (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6277   "TARGET_ARM && TARGET_HARD_FLOAT"
6278   "@
6279    mvf%D3s\\t%0, %2
6280    mnf%D3s\\t%0, #%N2
6281    mvf%d3s\\t%0, %1
6282    mnf%d3s\\t%0, #%N1
6283    mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6284    mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6285    mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6286    mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6287   [(set_attr "length" "4,4,4,4,8,8,8,8")
6288    (set_attr "type" "ffarith")
6289    (set_attr "conds" "use")]
6290 )
6291
6292 (define_insn "*movsfcc_soft_insn"
6293   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6294         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6295                           [(match_operand 4 "cc_register" "") (const_int 0)])
6296                          (match_operand:SF 1 "s_register_operand" "0,r")
6297                          (match_operand:SF 2 "s_register_operand" "r,0")))]
6298   "TARGET_ARM && TARGET_SOFT_FLOAT"
6299   "@
6300    mov%D3\\t%0, %2
6301    mov%d3\\t%0, %1"
6302   [(set_attr "conds" "use")]
6303 )
6304
6305 (define_insn "*movdfcc_insn"
6306   [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6307         (if_then_else:DF
6308          (match_operator 3 "arm_comparison_operator"
6309           [(match_operand 4 "cc_register" "") (const_int 0)])
6310          (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6311          (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6312   "TARGET_ARM && TARGET_HARD_FLOAT"
6313   "@
6314    mvf%D3d\\t%0, %2
6315    mnf%D3d\\t%0, #%N2
6316    mvf%d3d\\t%0, %1
6317    mnf%d3d\\t%0, #%N1
6318    mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6319    mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6320    mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6321    mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6322   [(set_attr "length" "4,4,4,4,8,8,8,8")
6323    (set_attr "type" "ffarith")
6324    (set_attr "conds" "use")]
6325 )
6326
6327 \f
6328 ;; Jump and linkage insns
6329
6330 (define_expand "jump"
6331   [(set (pc)
6332         (label_ref (match_operand 0 "" "")))]
6333   "TARGET_EITHER"
6334   ""
6335 )
6336
6337 (define_insn "*arm_jump"
6338   [(set (pc)
6339         (label_ref (match_operand 0 "" "")))]
6340   "TARGET_ARM"
6341   "*
6342   {
6343     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6344       {
6345         arm_ccfsm_state += 2;
6346         return \"\";
6347       }
6348     return \"b%?\\t%l0\";
6349   }
6350   "
6351   [(set_attr "predicable" "yes")]
6352 )
6353
6354 (define_insn "*thumb_jump"
6355   [(set (pc)
6356         (label_ref (match_operand 0 "" "")))]
6357   "TARGET_THUMB"
6358   "*
6359   if (get_attr_length (insn) == 2)
6360     return \"b\\t%l0\";
6361   return \"bl\\t%l0\\t%@ far jump\";
6362   "
6363   [(set (attr "far_jump")
6364         (if_then_else
6365             (eq_attr "length" "4")
6366             (const_string "yes")
6367             (const_string "no")))
6368    (set (attr "length") 
6369         (if_then_else
6370             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6371                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
6372             (const_int 2)
6373             (const_int 4)))]
6374 )
6375
6376 (define_expand "call"
6377   [(parallel [(call (match_operand 0 "memory_operand" "")
6378                     (match_operand 1 "general_operand" ""))
6379               (use (match_operand 2 "" ""))
6380               (clobber (reg:SI LR_REGNUM))])]
6381   "TARGET_EITHER"
6382   "
6383   {
6384     rtx callee;
6385     
6386     /* In an untyped call, we can get NULL for operand 2.  */
6387     if (operands[2] == NULL_RTX)
6388       operands[2] = const0_rtx;
6389       
6390     /* This is to decide if we should generate indirect calls by loading the
6391        32 bit address of the callee into a register before performing the
6392        branch and link.  operand[2] encodes the long_call/short_call
6393        attribute of the function being called.  This attribute is set whenever
6394        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6395        is used, and the short_call attribute can also be set if function is
6396        declared as static or if it has already been defined in the current
6397        compilation unit.  See arm.c and arm.h for info about this.  The third
6398        parameter to arm_is_longcall_p is used to tell it which pattern
6399        invoked it.  */
6400     callee  = XEXP (operands[0], 0);
6401     
6402     if (GET_CODE (callee) != REG
6403        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6404       XEXP (operands[0], 0) = force_reg (Pmode, callee);
6405   }"
6406 )
6407
6408 (define_insn "*call_reg"
6409   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6410          (match_operand 1 "" ""))
6411    (use (match_operand 2 "" ""))
6412    (clobber (reg:SI LR_REGNUM))]
6413   "TARGET_ARM"
6414   "*
6415   return output_call (operands);
6416   "
6417   ;; length is worst case, normally it is only two
6418   [(set_attr "length" "12")
6419    (set_attr "type" "call")]
6420 )
6421
6422 (define_insn "*call_mem"
6423   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6424          (match_operand 1 "" ""))
6425    (use (match_operand 2 "" ""))
6426    (clobber (reg:SI LR_REGNUM))]
6427   "TARGET_ARM"
6428   "*
6429   return output_call_mem (operands);
6430   "
6431   [(set_attr "length" "12")
6432    (set_attr "type" "call")]
6433 )
6434
6435 (define_insn "*call_indirect"
6436   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6437          (match_operand 1 "" ""))
6438    (use (match_operand 2 "" ""))
6439    (clobber (reg:SI LR_REGNUM))]
6440   "TARGET_THUMB"
6441   "*
6442   {
6443     if (TARGET_CALLER_INTERWORKING)
6444       return \"bl\\t%__interwork_call_via_%0\";
6445     else
6446       return \"bl\\t%__call_via_%0\";
6447   }"
6448   [(set_attr "type" "call")]
6449 )
6450
6451 (define_insn "*call_value_indirect"
6452   [(set (match_operand 0 "" "=l")
6453         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6454               (match_operand 2 "" "")))
6455    (use (match_operand 3 "" ""))
6456    (clobber (reg:SI LR_REGNUM))]
6457   "TARGET_THUMB"
6458   "*
6459   {
6460     if (TARGET_CALLER_INTERWORKING)
6461       return \"bl\\t%__interwork_call_via_%1\";
6462     else
6463       return \"bl\\t%__call_via_%1\";
6464   }"
6465   [(set_attr "type" "call")]
6466 )
6467
6468 (define_expand "call_value"
6469   [(parallel [(set (match_operand       0 "" "")
6470                    (call (match_operand 1 "memory_operand" "")
6471                          (match_operand 2 "general_operand" "")))
6472               (use (match_operand 3 "" ""))
6473               (clobber (reg:SI LR_REGNUM))])]
6474   "TARGET_EITHER"
6475   "
6476   {
6477     rtx callee = XEXP (operands[1], 0);
6478     
6479     /* In an untyped call, we can get NULL for operand 2.  */
6480     if (operands[3] == 0)
6481       operands[3] = const0_rtx;
6482       
6483     /* See the comment in define_expand \"call\".  */
6484     if (GET_CODE (callee) != REG
6485         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6486       XEXP (operands[1], 0) = force_reg (Pmode, callee);
6487   }"
6488 )
6489
6490 (define_insn "*call_value_reg"
6491   [(set (match_operand 0 "" "=r,f,v")
6492         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
6493               (match_operand 2 "" "")))
6494    (use (match_operand 3 "" ""))
6495    (clobber (reg:SI LR_REGNUM))]
6496   "TARGET_ARM"
6497   "*
6498   return output_call (&operands[1]);
6499   "
6500   [(set_attr "length" "12")
6501    (set_attr "type" "call")]
6502 )
6503
6504 (define_insn "*call_value_mem"
6505   [(set (match_operand 0 "" "=r,f,v")
6506         (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
6507               (match_operand 2 "" "")))
6508    (use (match_operand 3 "" ""))
6509    (clobber (reg:SI LR_REGNUM))]
6510   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6511   "*
6512   return output_call_mem (&operands[1]);
6513   "
6514   [(set_attr "length" "12")
6515    (set_attr "type" "call")]
6516 )
6517
6518 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6519 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6520
6521 (define_insn "*call_symbol"
6522   [(call (mem:SI (match_operand:SI 0 "" "X"))
6523          (match_operand 1 "" ""))
6524    (use (match_operand 2 "" ""))
6525    (clobber (reg:SI LR_REGNUM))]
6526   "TARGET_ARM
6527    && (GET_CODE (operands[0]) == SYMBOL_REF)
6528    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6529   "*
6530   {
6531     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6532   }"
6533   [(set_attr "type" "call")]
6534 )
6535
6536 (define_insn "*call_value_symbol"
6537   [(set (match_operand 0 "s_register_operand" "=r,f,v")
6538         (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6539         (match_operand:SI 2 "" "")))
6540    (use (match_operand 3 "" ""))
6541    (clobber (reg:SI LR_REGNUM))]
6542   "TARGET_ARM
6543    && (GET_CODE (operands[1]) == SYMBOL_REF)
6544    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6545   "*
6546   {
6547     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6548   }"
6549   [(set_attr "type" "call")]
6550 )
6551
6552 (define_insn "*call_insn"
6553   [(call (mem:SI (match_operand:SI 0 "" "X"))
6554          (match_operand:SI 1 "" ""))
6555    (use (match_operand 2 "" ""))
6556    (clobber (reg:SI LR_REGNUM))]
6557   "TARGET_THUMB
6558    && GET_CODE (operands[0]) == SYMBOL_REF
6559    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6560   "bl\\t%a0"
6561   [(set_attr "length" "4")
6562    (set_attr "type" "call")]
6563 )
6564
6565 (define_insn "*call_value_insn"
6566   [(set (match_operand 0 "register_operand" "=l")
6567         (call (mem:SI (match_operand 1 "" "X"))
6568               (match_operand 2 "" "")))
6569    (use (match_operand 3 "" ""))
6570    (clobber (reg:SI LR_REGNUM))]
6571   "TARGET_THUMB
6572    && GET_CODE (operands[1]) == SYMBOL_REF
6573    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6574   "bl\\t%a1"
6575   [(set_attr "length" "4")
6576    (set_attr "type" "call")]
6577 )
6578
6579 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6580 (define_expand "sibcall"
6581   [(parallel [(call (match_operand 0 "memory_operand" "")
6582                     (match_operand 1 "general_operand" ""))
6583               (return)
6584               (use (match_operand 2 "" ""))])]
6585   "TARGET_ARM"
6586   "
6587   {
6588     if (operands[2] == NULL_RTX)
6589       operands[2] = const0_rtx;
6590   }"
6591 )
6592
6593 (define_expand "sibcall_value"
6594   [(parallel [(set (match_operand 0 "register_operand" "")
6595                    (call (match_operand 1 "memory_operand" "")
6596                          (match_operand 2 "general_operand" "")))
6597               (return)
6598               (use (match_operand 3 "" ""))])]
6599   "TARGET_ARM"
6600   "
6601   {
6602     if (operands[3] == NULL_RTX)
6603       operands[3] = const0_rtx;
6604   }"
6605 )
6606
6607 (define_insn "*sibcall_insn"
6608  [(call (mem:SI (match_operand:SI 0 "" "X"))
6609         (match_operand 1 "" ""))
6610   (return)
6611   (use (match_operand 2 "" ""))]
6612   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6613   "*
6614   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6615   "
6616   [(set_attr "type" "call")]
6617 )
6618
6619 (define_insn "*sibcall_value_insn"
6620  [(set (match_operand 0 "s_register_operand" "=r,f,v")
6621        (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6622              (match_operand 2 "" "")))
6623   (return)
6624   (use (match_operand 3 "" ""))]
6625   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6626   "*
6627   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6628   "
6629   [(set_attr "type" "call")]
6630 )
6631
6632 ;; Often the return insn will be the same as loading from memory, so set attr
6633 (define_insn "return"
6634   [(return)]
6635   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6636   "*
6637   {
6638     if (arm_ccfsm_state == 2)
6639       {
6640         arm_ccfsm_state += 2;
6641         return \"\";
6642       }
6643     return output_return_instruction (const_true_rtx, TRUE, FALSE);
6644   }"
6645   [(set_attr "type" "load")
6646    (set_attr "predicable" "yes")]
6647 )
6648
6649 (define_insn "*cond_return"
6650   [(set (pc)
6651         (if_then_else (match_operator 0 "arm_comparison_operator"
6652                        [(match_operand 1 "cc_register" "") (const_int 0)])
6653                       (return)
6654                       (pc)))]
6655   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6656   "*
6657   {
6658     if (arm_ccfsm_state == 2)
6659       {
6660         arm_ccfsm_state += 2;
6661         return \"\";
6662       }
6663     return output_return_instruction (operands[0], TRUE, FALSE);
6664   }"
6665   [(set_attr "conds" "use")
6666    (set_attr "type" "load")]
6667 )
6668
6669 (define_insn "*cond_return_inverted"
6670   [(set (pc)
6671         (if_then_else (match_operator 0 "arm_comparison_operator"
6672                        [(match_operand 1 "cc_register" "") (const_int 0)])
6673                       (pc)
6674                       (return)))]
6675   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6676   "*
6677   {
6678     if (arm_ccfsm_state == 2)
6679       {
6680         arm_ccfsm_state += 2;
6681         return \"\";
6682       }
6683     return output_return_instruction (operands[0], TRUE, TRUE);
6684   }"
6685   [(set_attr "conds" "use")
6686    (set_attr "type" "load")]
6687 )
6688
6689 ;; Generate a sequence of instructions to determine if the processor is
6690 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6691 ;; mask.
6692
6693 (define_expand "return_addr_mask"
6694   [(set (match_dup 1)
6695       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6696                        (const_int 0)))
6697    (set (match_operand:SI 0 "s_register_operand" "")
6698       (if_then_else:SI (eq (match_dup 1) (const_int 0))
6699                        (const_int -1)
6700                        (const_int 67108860)))] ; 0x03fffffc
6701   "TARGET_ARM"
6702   "
6703   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6704   ")
6705
6706 (define_insn "*check_arch2"
6707   [(set (match_operand:CC_NOOV 0 "cc_register" "")
6708       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6709                        (const_int 0)))]
6710   "TARGET_ARM"
6711   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6712   [(set_attr "length" "8")
6713    (set_attr "conds" "set")]
6714 )
6715
6716 ;; Call subroutine returning any type.
6717
6718 (define_expand "untyped_call"
6719   [(parallel [(call (match_operand 0 "" "")
6720                     (const_int 0))
6721               (match_operand 1 "" "")
6722               (match_operand 2 "" "")])]
6723   "TARGET_ARM"
6724   "
6725   {
6726     int i;
6727
6728     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6729
6730     for (i = 0; i < XVECLEN (operands[2], 0); i++)
6731       {
6732         rtx set = XVECEXP (operands[2], 0, i);
6733
6734         emit_move_insn (SET_DEST (set), SET_SRC (set));
6735       }
6736
6737     /* The optimizer does not know that the call sets the function value
6738        registers we stored in the result block.  We avoid problems by
6739        claiming that all hard registers are used and clobbered at this
6740        point.  */
6741     emit_insn (gen_blockage ());
6742
6743     DONE;
6744   }"
6745 )
6746
6747 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6748 ;; all of memory.  This blocks insns from being moved across this point.
6749
6750 (define_insn "blockage"
6751   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6752   "TARGET_EITHER"
6753   ""
6754   [(set_attr "length" "0")
6755    (set_attr "type" "block")]
6756 )
6757
6758 (define_expand "casesi"
6759   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6760    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
6761    (match_operand:SI 2 "const_int_operand" "")  ; total range
6762    (match_operand:SI 3 "" "")                   ; table label
6763    (match_operand:SI 4 "" "")]                  ; Out of range label
6764   "TARGET_ARM"
6765   "
6766   {
6767     rtx reg;
6768     if (operands[1] != const0_rtx)
6769       {
6770         reg = gen_reg_rtx (SImode);
6771
6772         emit_insn (gen_addsi3 (reg, operands[0],
6773                                GEN_INT (-INTVAL (operands[1]))));
6774         operands[0] = reg;
6775       }
6776
6777     if (!const_ok_for_arm (INTVAL (operands[2])))
6778       operands[2] = force_reg (SImode, operands[2]);
6779
6780     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6781                                          operands[4]));
6782     DONE;
6783   }"
6784 )
6785
6786 ;; The USE in this pattern is needed to tell flow analysis that this is
6787 ;; a CASESI insn.  It has no other purpose.
6788 (define_insn "casesi_internal"
6789   [(parallel [(set (pc)
6790                (if_then_else
6791                 (leu (match_operand:SI 0 "s_register_operand" "r")
6792                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
6793                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6794                                  (label_ref (match_operand 2 "" ""))))
6795                 (label_ref (match_operand 3 "" ""))))
6796               (clobber (reg:CC CC_REGNUM))
6797               (use (label_ref (match_dup 2)))])]
6798   "TARGET_ARM"
6799   "*
6800     if (flag_pic)
6801       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6802     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6803   "
6804   [(set_attr "conds" "clob")
6805    (set_attr "length" "12")]
6806 )
6807
6808 (define_expand "indirect_jump"
6809   [(set (pc)
6810         (match_operand:SI 0 "s_register_operand" ""))]
6811   "TARGET_EITHER"
6812   ""
6813 )
6814
6815 (define_insn "*arm_indirect_jump"
6816   [(set (pc)
6817         (match_operand:SI 0 "s_register_operand" "r"))]
6818   "TARGET_ARM"
6819   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6820   [(set_attr "predicable" "yes")]
6821 )
6822
6823 ;; Although not supported by the define_expand above,
6824 ;; cse/combine may generate this form.
6825 (define_insn "*load_indirect_jump"
6826   [(set (pc)
6827         (match_operand:SI 0 "memory_operand" "m"))]
6828   "TARGET_ARM"
6829   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6830   [(set_attr "type" "load")
6831    (set_attr "pool_range" "4096")
6832    (set_attr "neg_pool_range" "4084")
6833    (set_attr "predicable" "yes")]
6834 )
6835
6836 (define_insn "*thumb_indirect_jump"
6837   [(set (pc)
6838         (match_operand:SI 0 "register_operand" "l*r"))]
6839   "TARGET_THUMB"
6840   "mov\\tpc, %0"
6841   [(set_attr "conds" "clob")
6842    (set_attr "length" "2")]
6843 )
6844
6845 \f
6846 ;; Misc insns
6847
6848 (define_insn "nop"
6849   [(const_int 0)]
6850   "TARGET_EITHER"
6851   "*
6852   if (TARGET_ARM)
6853     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6854   return  \"mov\\tr8, r8\";
6855   "
6856   [(set (attr "length")
6857         (if_then_else (eq_attr "is_thumb" "yes")
6858                       (const_int 2)
6859                       (const_int 4)))]
6860 )
6861
6862 \f
6863 ;; Patterns to allow combination of arithmetic, cond code and shifts
6864
6865 (define_insn "*arith_shiftsi"
6866   [(set (match_operand:SI 0 "s_register_operand" "=r")
6867         (match_operator:SI 1 "shiftable_operator"
6868           [(match_operator:SI 3 "shift_operator"
6869              [(match_operand:SI 4 "s_register_operand" "r")
6870               (match_operand:SI 5 "reg_or_int_operand" "rI")])
6871            (match_operand:SI 2 "s_register_operand" "r")]))]
6872   "TARGET_ARM"
6873   "%i1%?\\t%0, %2, %4%S3"
6874   [(set_attr "predicable" "yes")
6875    (set_attr "shift" "4")
6876    ]
6877 )
6878
6879 (define_insn "*arith_shiftsi_compare0"
6880   [(set (reg:CC_NOOV CC_REGNUM)
6881         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6882                           [(match_operator:SI 3 "shift_operator"
6883                             [(match_operand:SI 4 "s_register_operand" "r")
6884                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6885                            (match_operand:SI 2 "s_register_operand" "r")])
6886                          (const_int 0)))
6887    (set (match_operand:SI 0 "s_register_operand" "=r")
6888         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6889                          (match_dup 2)]))]
6890   "TARGET_ARM"
6891   "%i1%?s\\t%0, %2, %4%S3"
6892   [(set_attr "conds" "set")
6893    (set_attr "shift" "4")
6894    ]
6895 )
6896
6897 (define_insn "*arith_shiftsi_compare0_scratch"
6898   [(set (reg:CC_NOOV CC_REGNUM)
6899         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6900                           [(match_operator:SI 3 "shift_operator"
6901                             [(match_operand:SI 4 "s_register_operand" "r")
6902                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6903                            (match_operand:SI 2 "s_register_operand" "r")])
6904                          (const_int 0)))
6905    (clobber (match_scratch:SI 0 "=r"))]
6906   "TARGET_ARM"
6907   "%i1%?s\\t%0, %2, %4%S3"
6908   [(set_attr "conds" "set")
6909    (set_attr "shift" "4")
6910    ]
6911 )
6912
6913 (define_insn "*sub_shiftsi"
6914   [(set (match_operand:SI 0 "s_register_operand" "=r")
6915         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6916                   (match_operator:SI 2 "shift_operator"
6917                    [(match_operand:SI 3 "s_register_operand" "r")
6918                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6919   "TARGET_ARM"
6920   "sub%?\\t%0, %1, %3%S2"
6921   [(set_attr "predicable" "yes")
6922    (set_attr "shift" "3")
6923    ]
6924 )
6925
6926 (define_insn "*sub_shiftsi_compare0"
6927   [(set (reg:CC_NOOV CC_REGNUM)
6928         (compare:CC_NOOV
6929          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6930                    (match_operator:SI 2 "shift_operator"
6931                     [(match_operand:SI 3 "s_register_operand" "r")
6932                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6933          (const_int 0)))
6934    (set (match_operand:SI 0 "s_register_operand" "=r")
6935         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6936                                                  (match_dup 4)])))]
6937   "TARGET_ARM"
6938   "sub%?s\\t%0, %1, %3%S2"
6939   [(set_attr "conds" "set")
6940    (set_attr "shift" "3") 
6941    ]
6942 )
6943
6944 (define_insn "*sub_shiftsi_compare0_scratch"
6945   [(set (reg:CC_NOOV CC_REGNUM)
6946         (compare:CC_NOOV
6947          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6948                    (match_operator:SI 2 "shift_operator"
6949                     [(match_operand:SI 3 "s_register_operand" "r")
6950                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6951          (const_int 0)))
6952    (clobber (match_scratch:SI 0 "=r"))]
6953   "TARGET_ARM"
6954   "sub%?s\\t%0, %1, %3%S2"
6955   [(set_attr "conds" "set")
6956    (set_attr "shift" "3") 
6957    ]
6958 )
6959
6960 \f
6961
6962 (define_insn "*and_scc"
6963   [(set (match_operand:SI 0 "s_register_operand" "=r")
6964         (and:SI (match_operator:SI 1 "arm_comparison_operator"
6965                  [(match_operand 3 "cc_register" "") (const_int 0)])
6966                 (match_operand:SI 2 "s_register_operand" "r")))]
6967   "TARGET_ARM"
6968   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6969   [(set_attr "conds" "use")
6970    (set_attr "length" "8")]
6971 )
6972
6973 (define_insn "*ior_scc"
6974   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6975         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6976                  [(match_operand 3 "cc_register" "") (const_int 0)])
6977                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6978   "TARGET_ARM"
6979   "@
6980    orr%d2\\t%0, %1, #1
6981    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6982   [(set_attr "conds" "use")
6983    (set_attr "length" "4,8")]
6984 )
6985
6986 (define_insn "*compare_scc"
6987   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6988         (match_operator:SI 1 "arm_comparison_operator"
6989          [(match_operand:SI 2 "s_register_operand" "r,r")
6990           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6991    (clobber (reg:CC CC_REGNUM))]
6992   "TARGET_ARM"
6993   "*
6994     if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
6995       return \"mov\\t%0, %2, lsr #31\";
6996
6997     if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
6998       return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6999
7000     if (GET_CODE (operands[1]) == NE)
7001       {
7002         if (which_alternative == 1)
7003           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7004         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7005       }
7006     if (which_alternative == 1)
7007       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7008     else
7009       output_asm_insn (\"cmp\\t%2, %3\", operands);
7010     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7011   "
7012   [(set_attr "conds" "clob")
7013    (set_attr "length" "12")]
7014 )
7015
7016 (define_insn "*cond_move"
7017   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7018         (if_then_else:SI (match_operator 3 "equality_operator"
7019                           [(match_operator 4 "arm_comparison_operator"
7020                             [(match_operand 5 "cc_register" "") (const_int 0)])
7021                            (const_int 0)])
7022                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7023                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7024   "TARGET_ARM"
7025   "*
7026     if (GET_CODE (operands[3]) == NE)
7027       {
7028         if (which_alternative != 1)
7029           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7030         if (which_alternative != 0)
7031           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7032         return \"\";
7033       }
7034     if (which_alternative != 0)
7035       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7036     if (which_alternative != 1)
7037       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7038     return \"\";
7039   "
7040   [(set_attr "conds" "use")
7041    (set_attr "length" "4,4,8")]
7042 )
7043
7044 (define_insn "*cond_arith"
7045   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7046         (match_operator:SI 5 "shiftable_operator" 
7047          [(match_operator:SI 4 "arm_comparison_operator"
7048            [(match_operand:SI 2 "s_register_operand" "r,r")
7049             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7050           (match_operand:SI 1 "s_register_operand" "0,?r")]))
7051    (clobber (reg:CC CC_REGNUM))]
7052   "TARGET_ARM"
7053   "*
7054     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7055       return \"%i5\\t%0, %1, %2, lsr #31\";
7056
7057     output_asm_insn (\"cmp\\t%2, %3\", operands);
7058     if (GET_CODE (operands[5]) == AND)
7059       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7060     else if (GET_CODE (operands[5]) == MINUS)
7061       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7062     else if (which_alternative != 0)
7063       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7064     return \"%i5%d4\\t%0, %1, #1\";
7065   "
7066   [(set_attr "conds" "clob")
7067    (set_attr "length" "12")]
7068 )
7069
7070 (define_insn "*cond_sub"
7071   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7072         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7073                   (match_operator:SI 4 "arm_comparison_operator"
7074                    [(match_operand:SI 2 "s_register_operand" "r,r")
7075                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7076    (clobber (reg:CC CC_REGNUM))]
7077   "TARGET_ARM"
7078   "*
7079     output_asm_insn (\"cmp\\t%2, %3\", operands);
7080     if (which_alternative != 0)
7081       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7082     return \"sub%d4\\t%0, %1, #1\";
7083   "
7084   [(set_attr "conds" "clob")
7085    (set_attr "length" "8,12")]
7086 )
7087
7088 (define_insn "*cmp_ite0"
7089   [(set (match_operand 6 "dominant_cc_register" "")
7090         (compare
7091          (if_then_else:SI
7092           (match_operator 4 "arm_comparison_operator"
7093            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7094             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7095           (match_operator:SI 5 "arm_comparison_operator"
7096            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7097             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7098           (const_int 0))
7099          (const_int 0)))]
7100   "TARGET_ARM"
7101   "*
7102   {
7103     static const char * const opcodes[4][2] =
7104     {
7105       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7106        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7107       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7108        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7109       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7110        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7111       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7112        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7113     };
7114     int swap =
7115       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7116
7117     return opcodes[which_alternative][swap];
7118   }"
7119   [(set_attr "conds" "set")
7120    (set_attr "length" "8")]
7121 )
7122
7123 (define_insn "*cmp_ite1"
7124   [(set (match_operand 6 "dominant_cc_register" "")
7125         (compare
7126          (if_then_else:SI
7127           (match_operator 4 "arm_comparison_operator"
7128            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7129             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7130           (match_operator:SI 5 "arm_comparison_operator"
7131            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7132             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7133           (const_int 1))
7134          (const_int 0)))]
7135   "TARGET_ARM"
7136   "*
7137   {
7138     static const char * const opcodes[4][2] =
7139     {
7140       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7141        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7142       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7143        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7144       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7145        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7146       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7147        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7148     };
7149     int swap =
7150       comparison_dominates_p (GET_CODE (operands[5]),
7151                               reverse_condition (GET_CODE (operands[4])));
7152
7153     return opcodes[which_alternative][swap];
7154   }"
7155   [(set_attr "conds" "set")
7156    (set_attr "length" "8")]
7157 )
7158
7159 (define_insn "*cmp_and"
7160   [(set (match_operand 6 "dominant_cc_register" "")
7161         (compare
7162          (and:SI
7163           (match_operator 4 "arm_comparison_operator"
7164            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7165             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7166           (match_operator:SI 5 "arm_comparison_operator"
7167            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7168             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7169          (const_int 0)))]
7170   "TARGET_ARM"
7171   "*
7172   {
7173     static const char *const opcodes[4][2] =
7174     {
7175       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7176        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7177       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7178        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7179       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7180        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7181       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7182        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7183     };
7184     int swap =
7185       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7186
7187     return opcodes[which_alternative][swap];
7188   }"
7189   [(set_attr "conds" "set")
7190    (set_attr "predicable" "no")
7191    (set_attr "length" "8")]
7192 )
7193
7194 (define_insn "*cmp_ior"
7195   [(set (match_operand 6 "dominant_cc_register" "")
7196         (compare
7197          (ior:SI
7198           (match_operator 4 "arm_comparison_operator"
7199            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7200             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7201           (match_operator:SI 5 "arm_comparison_operator"
7202            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7203             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7204          (const_int 0)))]
7205   "TARGET_ARM"
7206   "*
7207 {
7208   static const char *const opcodes[4][2] =
7209   {
7210     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7211      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7212     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7213      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7214     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7215      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7216     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7217      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7218   };
7219   int swap =
7220     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7221
7222   return opcodes[which_alternative][swap];
7223 }
7224 "
7225   [(set_attr "conds" "set")
7226    (set_attr "length" "8")]
7227 )
7228
7229 (define_insn "*negscc"
7230   [(set (match_operand:SI 0 "s_register_operand" "=r")
7231         (neg:SI (match_operator 3 "arm_comparison_operator"
7232                  [(match_operand:SI 1 "s_register_operand" "r")
7233                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7234    (clobber (reg:CC CC_REGNUM))]
7235   "TARGET_ARM"
7236   "*
7237   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7238     return \"mov\\t%0, %1, asr #31\";
7239
7240   if (GET_CODE (operands[3]) == NE)
7241     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7242
7243   if (GET_CODE (operands[3]) == GT)
7244     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7245
7246   output_asm_insn (\"cmp\\t%1, %2\", operands);
7247   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7248   return \"mvn%d3\\t%0, #0\";
7249   "
7250   [(set_attr "conds" "clob")
7251    (set_attr "length" "12")]
7252 )
7253
7254 (define_insn "movcond"
7255   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7256         (if_then_else:SI
7257          (match_operator 5 "arm_comparison_operator"
7258           [(match_operand:SI 3 "s_register_operand" "r,r,r")
7259            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7260          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7261          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7262    (clobber (reg:CC CC_REGNUM))]
7263   "TARGET_ARM"
7264   "*
7265   if (GET_CODE (operands[5]) == LT
7266       && (operands[4] == const0_rtx))
7267     {
7268       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7269         {
7270           if (operands[2] == const0_rtx)
7271             return \"and\\t%0, %1, %3, asr #31\";
7272           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7273         }
7274       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7275         {
7276           if (operands[1] == const0_rtx)
7277             return \"bic\\t%0, %2, %3, asr #31\";
7278           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7279         }
7280       /* The only case that falls through to here is when both ops 1 & 2
7281          are constants */
7282     }
7283
7284   if (GET_CODE (operands[5]) == GE
7285       && (operands[4] == const0_rtx))
7286     {
7287       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7288         {
7289           if (operands[2] == const0_rtx)
7290             return \"bic\\t%0, %1, %3, asr #31\";
7291           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7292         }
7293       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7294         {
7295           if (operands[1] == const0_rtx)
7296             return \"and\\t%0, %2, %3, asr #31\";
7297           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7298         }
7299       /* The only case that falls through to here is when both ops 1 & 2
7300          are constants */
7301     }
7302   if (GET_CODE (operands[4]) == CONST_INT
7303       && !const_ok_for_arm (INTVAL (operands[4])))
7304     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7305   else
7306     output_asm_insn (\"cmp\\t%3, %4\", operands);
7307   if (which_alternative != 0)
7308     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7309   if (which_alternative != 1)
7310     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7311   return \"\";
7312   "
7313   [(set_attr "conds" "clob")
7314    (set_attr "length" "8,8,12")]
7315 )
7316
7317 (define_insn "*ifcompare_plus_move"
7318   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7319         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7320                           [(match_operand:SI 4 "s_register_operand" "r,r")
7321                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7322                          (plus:SI
7323                           (match_operand:SI 2 "s_register_operand" "r,r")
7324                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7325                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7326    (clobber (reg:CC CC_REGNUM))]
7327   "TARGET_ARM"
7328   "#"
7329   [(set_attr "conds" "clob")
7330    (set_attr "length" "8,12")]
7331 )
7332
7333 (define_insn "*if_plus_move"
7334   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7335         (if_then_else:SI
7336          (match_operator 4 "arm_comparison_operator"
7337           [(match_operand 5 "cc_register" "") (const_int 0)])
7338          (plus:SI
7339           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7340           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7341          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7342   "TARGET_ARM"
7343   "@
7344    add%d4\\t%0, %2, %3
7345    sub%d4\\t%0, %2, #%n3
7346    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7347    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7348   [(set_attr "conds" "use")
7349    (set_attr "length" "4,4,8,8")
7350    (set_attr "type" "*,*,*,*")]
7351 )
7352
7353 (define_insn "*ifcompare_move_plus"
7354   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7355         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7356                           [(match_operand:SI 4 "s_register_operand" "r,r")
7357                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7358                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7359                          (plus:SI
7360                           (match_operand:SI 2 "s_register_operand" "r,r")
7361                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7362    (clobber (reg:CC CC_REGNUM))]
7363   "TARGET_ARM"
7364   "#"
7365   [(set_attr "conds" "clob")
7366    (set_attr "length" "8,12")]
7367 )
7368
7369 (define_insn "*if_move_plus"
7370   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7371         (if_then_else:SI
7372          (match_operator 4 "arm_comparison_operator"
7373           [(match_operand 5 "cc_register" "") (const_int 0)])
7374          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7375          (plus:SI
7376           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7377           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7378   "TARGET_ARM"
7379   "@
7380    add%D4\\t%0, %2, %3
7381    sub%D4\\t%0, %2, #%n3
7382    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7383    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7384   [(set_attr "conds" "use")
7385    (set_attr "length" "4,4,8,8")
7386    (set_attr "type" "*,*,*,*")]
7387 )
7388
7389 (define_insn "*ifcompare_arith_arith"
7390   [(set (match_operand:SI 0 "s_register_operand" "=r")
7391         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7392                           [(match_operand:SI 5 "s_register_operand" "r")
7393                            (match_operand:SI 6 "arm_add_operand" "rIL")])
7394                          (match_operator:SI 8 "shiftable_operator"
7395                           [(match_operand:SI 1 "s_register_operand" "r")
7396                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7397                          (match_operator:SI 7 "shiftable_operator"
7398                           [(match_operand:SI 3 "s_register_operand" "r")
7399                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7400    (clobber (reg:CC CC_REGNUM))]
7401   "TARGET_ARM"
7402   "#"
7403   [(set_attr "conds" "clob")
7404    (set_attr "length" "12")]
7405 )
7406
7407 (define_insn "*if_arith_arith"
7408   [(set (match_operand:SI 0 "s_register_operand" "=r")
7409         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7410                           [(match_operand 8 "cc_register" "") (const_int 0)])
7411                          (match_operator:SI 6 "shiftable_operator"
7412                           [(match_operand:SI 1 "s_register_operand" "r")
7413                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7414                          (match_operator:SI 7 "shiftable_operator"
7415                           [(match_operand:SI 3 "s_register_operand" "r")
7416                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7417   "TARGET_ARM"
7418   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7419   [(set_attr "conds" "use")
7420    (set_attr "length" "8")]
7421 )
7422
7423 (define_insn "*ifcompare_arith_move"
7424   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7425         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7426                           [(match_operand:SI 2 "s_register_operand" "r,r")
7427                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7428                          (match_operator:SI 7 "shiftable_operator"
7429                           [(match_operand:SI 4 "s_register_operand" "r,r")
7430                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7431                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7432    (clobber (reg:CC CC_REGNUM))]
7433   "TARGET_ARM"
7434   "*
7435   /* If we have an operation where (op x 0) is the identity operation and
7436      the conditional operator is LT or GE and we are comparing against zero and
7437      everything is in registers then we can do this in two instructions */
7438   if (operands[3] == const0_rtx
7439       && GET_CODE (operands[7]) != AND
7440       && GET_CODE (operands[5]) == REG
7441       && GET_CODE (operands[1]) == REG 
7442       && REGNO (operands[1]) == REGNO (operands[4])
7443       && REGNO (operands[4]) != REGNO (operands[0]))
7444     {
7445       if (GET_CODE (operands[6]) == LT)
7446         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7447       else if (GET_CODE (operands[6]) == GE)
7448         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7449     }
7450   if (GET_CODE (operands[3]) == CONST_INT
7451       && !const_ok_for_arm (INTVAL (operands[3])))
7452     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7453   else
7454     output_asm_insn (\"cmp\\t%2, %3\", operands);
7455   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7456   if (which_alternative != 0)
7457     return \"mov%D6\\t%0, %1\";
7458   return \"\";
7459   "
7460   [(set_attr "conds" "clob")
7461    (set_attr "length" "8,12")]
7462 )
7463
7464 (define_insn "*if_arith_move"
7465   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7466         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7467                           [(match_operand 6 "cc_register" "") (const_int 0)])
7468                          (match_operator:SI 5 "shiftable_operator"
7469                           [(match_operand:SI 2 "s_register_operand" "r,r")
7470                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7471                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7472   "TARGET_ARM"
7473   "@
7474    %I5%d4\\t%0, %2, %3
7475    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7476   [(set_attr "conds" "use")
7477    (set_attr "length" "4,8")
7478    (set_attr "type" "*,*")]
7479 )
7480
7481 (define_insn "*ifcompare_move_arith"
7482   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7483         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7484                           [(match_operand:SI 4 "s_register_operand" "r,r")
7485                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7486                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7487                          (match_operator:SI 7 "shiftable_operator"
7488                           [(match_operand:SI 2 "s_register_operand" "r,r")
7489                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7490    (clobber (reg:CC CC_REGNUM))]
7491   "TARGET_ARM"
7492   "*
7493   /* If we have an operation where (op x 0) is the identity operation and
7494      the conditional operator is LT or GE and we are comparing against zero and
7495      everything is in registers then we can do this in two instructions */
7496   if (operands[5] == const0_rtx
7497       && GET_CODE (operands[7]) != AND
7498       && GET_CODE (operands[3]) == REG
7499       && GET_CODE (operands[1]) == REG 
7500       && REGNO (operands[1]) == REGNO (operands[2])
7501       && REGNO (operands[2]) != REGNO (operands[0]))
7502     {
7503       if (GET_CODE (operands[6]) == GE)
7504         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7505       else if (GET_CODE (operands[6]) == LT)
7506         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7507     }
7508
7509   if (GET_CODE (operands[5]) == CONST_INT
7510       && !const_ok_for_arm (INTVAL (operands[5])))
7511     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7512   else
7513     output_asm_insn (\"cmp\\t%4, %5\", operands);
7514
7515   if (which_alternative != 0)
7516     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7517   return \"%I7%D6\\t%0, %2, %3\";
7518   "
7519   [(set_attr "conds" "clob")
7520    (set_attr "length" "8,12")]
7521 )
7522
7523 (define_insn "*if_move_arith"
7524   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7525         (if_then_else:SI
7526          (match_operator 4 "arm_comparison_operator"
7527           [(match_operand 6 "cc_register" "") (const_int 0)])
7528          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7529          (match_operator:SI 5 "shiftable_operator"
7530           [(match_operand:SI 2 "s_register_operand" "r,r")
7531            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7532   "TARGET_ARM"
7533   "@
7534    %I5%D4\\t%0, %2, %3
7535    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7536   [(set_attr "conds" "use")
7537    (set_attr "length" "4,8")
7538    (set_attr "type" "*,*")]
7539 )
7540
7541 (define_insn "*ifcompare_move_not"
7542   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7543         (if_then_else:SI
7544          (match_operator 5 "arm_comparison_operator"
7545           [(match_operand:SI 3 "s_register_operand" "r,r")
7546            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7547          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7548          (not:SI
7549           (match_operand:SI 2 "s_register_operand" "r,r"))))
7550    (clobber (reg:CC CC_REGNUM))]
7551   "TARGET_ARM"
7552   "#"
7553   [(set_attr "conds" "clob")
7554    (set_attr "length" "8,12")]
7555 )
7556
7557 (define_insn "*if_move_not"
7558   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7559         (if_then_else:SI
7560          (match_operator 4 "arm_comparison_operator"
7561           [(match_operand 3 "cc_register" "") (const_int 0)])
7562          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7563          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7564   "TARGET_ARM"
7565   "@
7566    mvn%D4\\t%0, %2
7567    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7568    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7569   [(set_attr "conds" "use")
7570    (set_attr "length" "4,8,8")]
7571 )
7572
7573 (define_insn "*ifcompare_not_move"
7574   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7575         (if_then_else:SI 
7576          (match_operator 5 "arm_comparison_operator"
7577           [(match_operand:SI 3 "s_register_operand" "r,r")
7578            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7579          (not:SI
7580           (match_operand:SI 2 "s_register_operand" "r,r"))
7581          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7582    (clobber (reg:CC CC_REGNUM))]
7583   "TARGET_ARM"
7584   "#"
7585   [(set_attr "conds" "clob")
7586    (set_attr "length" "8,12")]
7587 )
7588
7589 (define_insn "*if_not_move"
7590   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7591         (if_then_else:SI
7592          (match_operator 4 "arm_comparison_operator"
7593           [(match_operand 3 "cc_register" "") (const_int 0)])
7594          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7595          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7596   "TARGET_ARM"
7597   "@
7598    mvn%d4\\t%0, %2
7599    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7600    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7601   [(set_attr "conds" "use")
7602    (set_attr "length" "4,8,8")]
7603 )
7604
7605 (define_insn "*ifcompare_shift_move"
7606   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7607         (if_then_else:SI
7608          (match_operator 6 "arm_comparison_operator"
7609           [(match_operand:SI 4 "s_register_operand" "r,r")
7610            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7611          (match_operator:SI 7 "shift_operator"
7612           [(match_operand:SI 2 "s_register_operand" "r,r")
7613            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7614          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7615    (clobber (reg:CC CC_REGNUM))]
7616   "TARGET_ARM"
7617   "#"
7618   [(set_attr "conds" "clob")
7619    (set_attr "length" "8,12")]
7620 )
7621
7622 (define_insn "*if_shift_move"
7623   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7624         (if_then_else:SI
7625          (match_operator 5 "arm_comparison_operator"
7626           [(match_operand 6 "cc_register" "") (const_int 0)])
7627          (match_operator:SI 4 "shift_operator"
7628           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7629            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7630          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7631   "TARGET_ARM"
7632   "@
7633    mov%d5\\t%0, %2%S4
7634    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7635    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7636   [(set_attr "conds" "use")
7637    (set_attr "shift" "2")
7638    (set_attr "length" "4,8,8")]
7639 )
7640
7641 (define_insn "*ifcompare_move_shift"
7642   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7643         (if_then_else:SI
7644          (match_operator 6 "arm_comparison_operator"
7645           [(match_operand:SI 4 "s_register_operand" "r,r")
7646            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7647          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7648          (match_operator:SI 7 "shift_operator"
7649           [(match_operand:SI 2 "s_register_operand" "r,r")
7650            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7651    (clobber (reg:CC CC_REGNUM))]
7652   "TARGET_ARM"
7653   "#"
7654   [(set_attr "conds" "clob")
7655    (set_attr "length" "8,12")]
7656 )
7657
7658 (define_insn "*if_move_shift"
7659   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7660         (if_then_else:SI
7661          (match_operator 5 "arm_comparison_operator"
7662           [(match_operand 6 "cc_register" "") (const_int 0)])
7663          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7664          (match_operator:SI 4 "shift_operator"
7665           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7666            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7667   "TARGET_ARM"
7668   "@
7669    mov%D5\\t%0, %2%S4
7670    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7671    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7672   [(set_attr "conds" "use")
7673    (set_attr "shift" "2")
7674    (set_attr "length" "4,8,8")]
7675 )
7676
7677 (define_insn "*ifcompare_shift_shift"
7678   [(set (match_operand:SI 0 "s_register_operand" "=r")
7679         (if_then_else:SI
7680          (match_operator 7 "arm_comparison_operator"
7681           [(match_operand:SI 5 "s_register_operand" "r")
7682            (match_operand:SI 6 "arm_add_operand" "rIL")])
7683          (match_operator:SI 8 "shift_operator"
7684           [(match_operand:SI 1 "s_register_operand" "r")
7685            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7686          (match_operator:SI 9 "shift_operator"
7687           [(match_operand:SI 3 "s_register_operand" "r")
7688            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7689    (clobber (reg:CC CC_REGNUM))]
7690   "TARGET_ARM"
7691   "#"
7692   [(set_attr "conds" "clob")
7693    (set_attr "length" "12")]
7694 )
7695
7696 (define_insn "*if_shift_shift"
7697   [(set (match_operand:SI 0 "s_register_operand" "=r")
7698         (if_then_else:SI
7699          (match_operator 5 "arm_comparison_operator"
7700           [(match_operand 8 "cc_register" "") (const_int 0)])
7701          (match_operator:SI 6 "shift_operator"
7702           [(match_operand:SI 1 "s_register_operand" "r")
7703            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7704          (match_operator:SI 7 "shift_operator"
7705           [(match_operand:SI 3 "s_register_operand" "r")
7706            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7707   "TARGET_ARM"
7708   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7709   [(set_attr "conds" "use")
7710    (set_attr "shift" "1")
7711    (set_attr "length" "8")]
7712 )
7713
7714 (define_insn "*ifcompare_not_arith"
7715   [(set (match_operand:SI 0 "s_register_operand" "=r")
7716         (if_then_else:SI
7717          (match_operator 6 "arm_comparison_operator"
7718           [(match_operand:SI 4 "s_register_operand" "r")
7719            (match_operand:SI 5 "arm_add_operand" "rIL")])
7720          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7721          (match_operator:SI 7 "shiftable_operator"
7722           [(match_operand:SI 2 "s_register_operand" "r")
7723            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7724    (clobber (reg:CC CC_REGNUM))]
7725   "TARGET_ARM"
7726   "#"
7727   [(set_attr "conds" "clob")
7728    (set_attr "length" "12")]
7729 )
7730
7731 (define_insn "*if_not_arith"
7732   [(set (match_operand:SI 0 "s_register_operand" "=r")
7733         (if_then_else:SI
7734          (match_operator 5 "arm_comparison_operator"
7735           [(match_operand 4 "cc_register" "") (const_int 0)])
7736          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7737          (match_operator:SI 6 "shiftable_operator"
7738           [(match_operand:SI 2 "s_register_operand" "r")
7739            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7740   "TARGET_ARM"
7741   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7742   [(set_attr "conds" "use")
7743    (set_attr "length" "8")]
7744 )
7745
7746 (define_insn "*ifcompare_arith_not"
7747   [(set (match_operand:SI 0 "s_register_operand" "=r")
7748         (if_then_else:SI
7749          (match_operator 6 "arm_comparison_operator"
7750           [(match_operand:SI 4 "s_register_operand" "r")
7751            (match_operand:SI 5 "arm_add_operand" "rIL")])
7752          (match_operator:SI 7 "shiftable_operator"
7753           [(match_operand:SI 2 "s_register_operand" "r")
7754            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7755          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7756    (clobber (reg:CC CC_REGNUM))]
7757   "TARGET_ARM"
7758   "#"
7759   [(set_attr "conds" "clob")
7760    (set_attr "length" "12")]
7761 )
7762
7763 (define_insn "*if_arith_not"
7764   [(set (match_operand:SI 0 "s_register_operand" "=r")
7765         (if_then_else:SI
7766          (match_operator 5 "arm_comparison_operator"
7767           [(match_operand 4 "cc_register" "") (const_int 0)])
7768          (match_operator:SI 6 "shiftable_operator"
7769           [(match_operand:SI 2 "s_register_operand" "r")
7770            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7771          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7772   "TARGET_ARM"
7773   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7774   [(set_attr "conds" "use")
7775    (set_attr "length" "8")]
7776 )
7777
7778 (define_insn "*ifcompare_neg_move"
7779   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7780         (if_then_else:SI
7781          (match_operator 5 "arm_comparison_operator"
7782           [(match_operand:SI 3 "s_register_operand" "r,r")
7783            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7784          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7785          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7786    (clobber (reg:CC CC_REGNUM))]
7787   "TARGET_ARM"
7788   "#"
7789   [(set_attr "conds" "clob")
7790    (set_attr "length" "8,12")]
7791 )
7792
7793 (define_insn "*if_neg_move"
7794   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7795         (if_then_else:SI
7796          (match_operator 4 "arm_comparison_operator"
7797           [(match_operand 3 "cc_register" "") (const_int 0)])
7798          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7799          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7800   "TARGET_ARM"
7801   "@
7802    rsb%d4\\t%0, %2, #0
7803    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7804    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7805   [(set_attr "conds" "use")
7806    (set_attr "length" "4,8,8")]
7807 )
7808
7809 (define_insn "*ifcompare_move_neg"
7810   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7811         (if_then_else:SI
7812          (match_operator 5 "arm_comparison_operator"
7813           [(match_operand:SI 3 "s_register_operand" "r,r")
7814            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7815          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7816          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7817    (clobber (reg:CC CC_REGNUM))]
7818   "TARGET_ARM"
7819   "#"
7820   [(set_attr "conds" "clob")
7821    (set_attr "length" "8,12")]
7822 )
7823
7824 (define_insn "*if_move_neg"
7825   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7826         (if_then_else:SI
7827          (match_operator 4 "arm_comparison_operator"
7828           [(match_operand 3 "cc_register" "") (const_int 0)])
7829          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7830          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7831   "TARGET_ARM"
7832   "@
7833    rsb%D4\\t%0, %2, #0
7834    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7835    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7836   [(set_attr "conds" "use")
7837    (set_attr "length" "4,8,8")]
7838 )
7839
7840 (define_insn "*arith_adjacentmem"
7841   [(set (match_operand:SI 0 "s_register_operand" "=r")
7842         (match_operator:SI 1 "shiftable_operator"
7843          [(match_operand:SI 2 "memory_operand" "m")
7844           (match_operand:SI 3 "memory_operand" "m")]))
7845    (clobber (match_scratch:SI 4 "=r"))]
7846   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7847   "*
7848   {
7849     rtx ldm[3];
7850     rtx arith[4];
7851     int val1 = 0, val2 = 0;
7852
7853     if (REGNO (operands[0]) > REGNO (operands[4]))
7854       {
7855         ldm[1] = operands[4];
7856         ldm[2] = operands[0];
7857       }
7858     else
7859       {
7860         ldm[1] = operands[0];
7861         ldm[2] = operands[4];
7862       }
7863     if (GET_CODE (XEXP (operands[2], 0)) != REG)
7864       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7865     if (GET_CODE (XEXP (operands[3], 0)) != REG)
7866       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7867     arith[0] = operands[0];
7868     arith[3] = operands[1];
7869     if (val1 < val2)
7870       {
7871         arith[1] = ldm[1];
7872         arith[2] = ldm[2];
7873       }
7874     else
7875       {
7876         arith[1] = ldm[2];
7877         arith[2] = ldm[1];
7878       }
7879    if (val1 && val2)
7880       {
7881         rtx ops[3];
7882         ldm[0] = ops[0] = operands[4];
7883         ops[1] = XEXP (XEXP (operands[2], 0), 0);
7884         ops[2] = XEXP (XEXP (operands[2], 0), 1);
7885         output_add_immediate (ops);
7886         if (val1 < val2)
7887           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7888         else
7889           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7890       }
7891     else if (val1)
7892       {
7893         ldm[0] = XEXP (operands[3], 0);
7894         if (val1 < val2)
7895           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7896         else
7897           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7898       }
7899     else
7900       {
7901         ldm[0] = XEXP (operands[2], 0);
7902         if (val1 < val2)
7903           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7904         else
7905           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7906       }
7907     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7908     return \"\";
7909   }"
7910   [(set_attr "length" "12")
7911    (set_attr "predicable" "yes")
7912    (set_attr "type" "load")]
7913 )
7914
7915 ;; the arm can support extended pre-inc instructions
7916
7917 ;; In all these cases, we use operands 0 and 1 for the register being
7918 ;; incremented because those are the operands that local-alloc will
7919 ;; tie and these are the pair most likely to be tieable (and the ones
7920 ;; that will benefit the most).
7921
7922 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7923 ;; elimination will cause too many headaches.
7924
7925 (define_insn "*strqi_preinc"
7926   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7927                          (match_operand:SI 2 "index_operand" "rJ")))
7928         (match_operand:QI 3 "s_register_operand" "r"))
7929    (set (match_operand:SI 0 "s_register_operand" "=r")
7930         (plus:SI (match_dup 1) (match_dup 2)))]
7931   "TARGET_ARM
7932    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7933    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7934    && (GET_CODE (operands[2]) != REG
7935        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7936   "str%?b\\t%3, [%0, %2]!"
7937   [(set_attr "type" "store1")
7938    (set_attr "predicable" "yes")]
7939 )
7940
7941 (define_insn "*strqi_predec"
7942   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7943                           (match_operand:SI 2 "s_register_operand" "r")))
7944         (match_operand:QI 3 "s_register_operand" "r"))
7945    (set (match_operand:SI 0 "s_register_operand" "=r")
7946         (minus:SI (match_dup 1) (match_dup 2)))]
7947   "TARGET_ARM
7948    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7949    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7950    && (GET_CODE (operands[2]) != REG
7951        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7952   "str%?b\\t%3, [%0, -%2]!"
7953   [(set_attr "type" "store1")
7954    (set_attr "predicable" "yes")]
7955 )
7956
7957 (define_insn "*loadqi_preinc"
7958   [(set (match_operand:QI 3 "s_register_operand" "=r")
7959         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7960                          (match_operand:SI 2 "index_operand" "rJ"))))
7961    (set (match_operand:SI 0 "s_register_operand" "=r")
7962         (plus:SI (match_dup 1) (match_dup 2)))]
7963   "TARGET_ARM
7964    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7965    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7966    && (GET_CODE (operands[2]) != REG
7967        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7968   "ldr%?b\\t%3, [%0, %2]!"
7969   [(set_attr "type" "load")
7970    (set_attr "predicable" "yes")]
7971 )
7972
7973 (define_insn "*loadqi_predec"
7974   [(set (match_operand:QI 3 "s_register_operand" "=r")
7975         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7976                           (match_operand:SI 2 "s_register_operand" "r"))))
7977    (set (match_operand:SI 0 "s_register_operand" "=r")
7978         (minus:SI (match_dup 1) (match_dup 2)))]
7979   "TARGET_ARM
7980    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7981    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7982    && (GET_CODE (operands[2]) != REG
7983        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7984   "ldr%?b\\t%3, [%0, -%2]!"
7985   [(set_attr "type" "load")
7986    (set_attr "predicable" "yes")]
7987 )
7988
7989 (define_insn "*loadqisi_preinc"
7990   [(set (match_operand:SI 3 "s_register_operand" "=r")
7991         (zero_extend:SI
7992          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7993                           (match_operand:SI 2 "index_operand" "rJ")))))
7994    (set (match_operand:SI 0 "s_register_operand" "=r")
7995         (plus:SI (match_dup 1) (match_dup 2)))]
7996   "TARGET_ARM
7997    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7998    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7999    && (GET_CODE (operands[2]) != REG
8000        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8001   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8002   [(set_attr "type" "load")
8003    (set_attr "predicable" "yes")]
8004 )
8005
8006 (define_insn "*loadqisi_predec"
8007   [(set (match_operand:SI 3 "s_register_operand" "=r")
8008         (zero_extend:SI
8009          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8010                            (match_operand:SI 2 "s_register_operand" "r")))))
8011    (set (match_operand:SI 0 "s_register_operand" "=r")
8012         (minus:SI (match_dup 1) (match_dup 2)))]
8013   "TARGET_ARM
8014    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8015    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8016    && (GET_CODE (operands[2]) != REG
8017        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8018   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8019   [(set_attr "type" "load")
8020    (set_attr "predicable" "yes")]
8021 )
8022
8023 (define_insn "*strsi_preinc"
8024   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8025                          (match_operand:SI 2 "index_operand" "rJ")))
8026         (match_operand:SI 3 "s_register_operand" "r"))
8027    (set (match_operand:SI 0 "s_register_operand" "=r")
8028         (plus:SI (match_dup 1) (match_dup 2)))]
8029   "TARGET_ARM
8030    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8031    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8032    && (GET_CODE (operands[2]) != REG
8033        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8034   "str%?\\t%3, [%0, %2]!"
8035   [(set_attr "type" "store1")
8036    (set_attr "predicable" "yes")]
8037 )
8038
8039 (define_insn "*strsi_predec"
8040   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8041                           (match_operand:SI 2 "s_register_operand" "r")))
8042         (match_operand:SI 3 "s_register_operand" "r"))
8043    (set (match_operand:SI 0 "s_register_operand" "=r")
8044         (minus:SI (match_dup 1) (match_dup 2)))]
8045   "TARGET_ARM
8046    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8047    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8048    && (GET_CODE (operands[2]) != REG
8049        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8050   "str%?\\t%3, [%0, -%2]!"
8051   [(set_attr "type" "store1")
8052    (set_attr "predicable" "yes")]
8053 )
8054
8055 (define_insn "*loadsi_preinc"
8056   [(set (match_operand:SI 3 "s_register_operand" "=r")
8057         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8058                          (match_operand:SI 2 "index_operand" "rJ"))))
8059    (set (match_operand:SI 0 "s_register_operand" "=r")
8060         (plus:SI (match_dup 1) (match_dup 2)))]
8061   "TARGET_ARM
8062    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8063    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8064    && (GET_CODE (operands[2]) != REG
8065        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8066   "ldr%?\\t%3, [%0, %2]!"
8067   [(set_attr "type" "load")
8068    (set_attr "predicable" "yes")]
8069 )
8070
8071 (define_insn "*loadsi_predec"
8072   [(set (match_operand:SI 3 "s_register_operand" "=r")
8073         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8074                           (match_operand:SI 2 "s_register_operand" "r"))))
8075    (set (match_operand:SI 0 "s_register_operand" "=r")
8076         (minus:SI (match_dup 1) (match_dup 2)))]
8077   "TARGET_ARM
8078    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8079    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8080    && (GET_CODE (operands[2]) != REG
8081        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8082   "ldr%?\\t%3, [%0, -%2]!"
8083   [(set_attr "type" "load")
8084    (set_attr "predicable" "yes")]
8085 )
8086
8087 (define_insn "*loadhi_preinc"
8088   [(set (match_operand:HI 3 "s_register_operand" "=r")
8089         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8090                          (match_operand:SI 2 "index_operand" "rJ"))))
8091    (set (match_operand:SI 0 "s_register_operand" "=r")
8092         (plus:SI (match_dup 1) (match_dup 2)))]
8093   "TARGET_ARM
8094    && !BYTES_BIG_ENDIAN
8095    && !TARGET_MMU_TRAPS
8096    && !arm_arch4
8097    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8098    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8099    && (GET_CODE (operands[2]) != REG
8100        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8101   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8102   [(set_attr "type" "load")
8103    (set_attr "predicable" "yes")]
8104 )
8105
8106 (define_insn "*loadhi_predec"
8107   [(set (match_operand:HI 3 "s_register_operand" "=r")
8108         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8109                           (match_operand:SI 2 "s_register_operand" "r"))))
8110    (set (match_operand:SI 0 "s_register_operand" "=r")
8111         (minus:SI (match_dup 1) (match_dup 2)))]
8112   "TARGET_ARM
8113    && !BYTES_BIG_ENDIAN
8114    && !TARGET_MMU_TRAPS
8115    && !arm_arch4
8116    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8117    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8118    && (GET_CODE (operands[2]) != REG
8119        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8120   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8121   [(set_attr "type" "load")
8122    (set_attr "predicable" "yes")]
8123 )
8124
8125 (define_insn "*strqi_shiftpreinc"
8126   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8127                           [(match_operand:SI 3 "s_register_operand" "r")
8128                            (match_operand:SI 4 "const_shift_operand" "n")])
8129                          (match_operand:SI 1 "s_register_operand" "0")))
8130         (match_operand:QI 5 "s_register_operand" "r"))
8131    (set (match_operand:SI 0 "s_register_operand" "=r")
8132         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8133                  (match_dup 1)))]
8134   "TARGET_ARM
8135    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8136    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8137    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8138   "str%?b\\t%5, [%0, %3%S2]!"
8139   [(set_attr "type" "store1")
8140    (set_attr "predicable" "yes")]
8141 )
8142
8143 (define_insn "*strqi_shiftpredec"
8144   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8145                           (match_operator:SI 2 "shift_operator"
8146                            [(match_operand:SI 3 "s_register_operand" "r")
8147                             (match_operand:SI 4 "const_shift_operand" "n")])))
8148         (match_operand:QI 5 "s_register_operand" "r"))
8149    (set (match_operand:SI 0 "s_register_operand" "=r")
8150         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8151                                                  (match_dup 4)])))]
8152   "TARGET_ARM
8153    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8154    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8155    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8156   "str%?b\\t%5, [%0, -%3%S2]!"
8157   [(set_attr "type" "store1")
8158    (set_attr "predicable" "yes")]
8159 )
8160
8161 (define_insn "*loadqi_shiftpreinc"
8162   [(set (match_operand:QI 5 "s_register_operand" "=r")
8163         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8164                           [(match_operand:SI 3 "s_register_operand" "r")
8165                            (match_operand:SI 4 "const_shift_operand" "n")])
8166                          (match_operand:SI 1 "s_register_operand" "0"))))
8167    (set (match_operand:SI 0 "s_register_operand" "=r")
8168         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8169                  (match_dup 1)))]
8170   "TARGET_ARM
8171    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8172    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8173    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8174   "ldr%?b\\t%5, [%0, %3%S2]!"
8175   [(set_attr "type" "load")
8176    (set_attr "predicable" "yes")]
8177 )
8178
8179 (define_insn "*loadqi_shiftpredec"
8180   [(set (match_operand:QI 5 "s_register_operand" "=r")
8181         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8182                           (match_operator:SI 2 "shift_operator"
8183                            [(match_operand:SI 3 "s_register_operand" "r")
8184                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8185    (set (match_operand:SI 0 "s_register_operand" "=r")
8186         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8187                                                  (match_dup 4)])))]
8188   "TARGET_ARM
8189    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8190    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8191    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8192   "ldr%?b\\t%5, [%0, -%3%S2]!"
8193   [(set_attr "type" "load")
8194    (set_attr "predicable" "yes")]
8195 )
8196
8197 (define_insn "*strsi_shiftpreinc"
8198   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8199                           [(match_operand:SI 3 "s_register_operand" "r")
8200                            (match_operand:SI 4 "const_shift_operand" "n")])
8201                          (match_operand:SI 1 "s_register_operand" "0")))
8202         (match_operand:SI 5 "s_register_operand" "r"))
8203    (set (match_operand:SI 0 "s_register_operand" "=r")
8204         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8205                  (match_dup 1)))]
8206   "TARGET_ARM
8207    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8208    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8209    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8210   "str%?\\t%5, [%0, %3%S2]!"
8211   [(set_attr "type" "store1")
8212    (set_attr "predicable" "yes")]
8213 )
8214
8215 (define_insn "*strsi_shiftpredec"
8216   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8217                           (match_operator:SI 2 "shift_operator"
8218                            [(match_operand:SI 3 "s_register_operand" "r")
8219                             (match_operand:SI 4 "const_shift_operand" "n")])))
8220         (match_operand:SI 5 "s_register_operand" "r"))
8221    (set (match_operand:SI 0 "s_register_operand" "=r")
8222         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8223                                                  (match_dup 4)])))]
8224   "TARGET_ARM
8225    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8226    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8227    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8228   "str%?\\t%5, [%0, -%3%S2]!"
8229   [(set_attr "type" "store1")
8230    (set_attr "predicable" "yes")]
8231 )
8232
8233 (define_insn "*loadsi_shiftpreinc"
8234   [(set (match_operand:SI 5 "s_register_operand" "=r")
8235         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8236                           [(match_operand:SI 3 "s_register_operand" "r")
8237                            (match_operand:SI 4 "const_shift_operand" "n")])
8238                          (match_operand:SI 1 "s_register_operand" "0"))))
8239    (set (match_operand:SI 0 "s_register_operand" "=r")
8240         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8241                  (match_dup 1)))]
8242   "TARGET_ARM
8243    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8244    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8245    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8246   "ldr%?\\t%5, [%0, %3%S2]!"
8247   [(set_attr "type" "load")
8248    (set_attr "predicable" "yes")]
8249 )
8250
8251 (define_insn "*loadsi_shiftpredec"
8252   [(set (match_operand:SI 5 "s_register_operand" "=r")
8253         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8254                           (match_operator:SI 2 "shift_operator"
8255                            [(match_operand:SI 3 "s_register_operand" "r")
8256                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8257    (set (match_operand:SI 0 "s_register_operand" "=r")
8258         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8259                                                  (match_dup 4)])))]
8260   "TARGET_ARM
8261    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8262    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8263    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8264   "ldr%?\\t%5, [%0, -%3%S2]!"
8265   [(set_attr "type" "load")
8266    (set_attr "predicable" "yes")])
8267
8268 (define_insn "*loadhi_shiftpreinc"
8269   [(set (match_operand:HI 5 "s_register_operand" "=r")
8270         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8271                           [(match_operand:SI 3 "s_register_operand" "r")
8272                            (match_operand:SI 4 "const_shift_operand" "n")])
8273                          (match_operand:SI 1 "s_register_operand" "0"))))
8274    (set (match_operand:SI 0 "s_register_operand" "=r")
8275         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8276                  (match_dup 1)))]
8277   "TARGET_ARM
8278    && !BYTES_BIG_ENDIAN
8279    && !TARGET_MMU_TRAPS
8280    && !arm_arch4
8281    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8282    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8283    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8284   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8285   [(set_attr "type" "load")
8286    (set_attr "predicable" "yes")]
8287 )
8288
8289 (define_insn "*loadhi_shiftpredec"
8290   [(set (match_operand:HI 5 "s_register_operand" "=r")
8291         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8292                           (match_operator:SI 2 "shift_operator"
8293                            [(match_operand:SI 3 "s_register_operand" "r")
8294                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8295    (set (match_operand:SI 0 "s_register_operand" "=r")
8296         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8297                                                  (match_dup 4)])))]
8298   "TARGET_ARM
8299    && !BYTES_BIG_ENDIAN
8300    && !TARGET_MMU_TRAPS
8301    && !arm_arch4
8302    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8303    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8304    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8305   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8306   [(set_attr "type" "load")
8307    (set_attr "predicable" "yes")]
8308 )
8309
8310 ; It can also support extended post-inc expressions, but combine doesn't
8311 ; try these....
8312 ; It doesn't seem worth adding peepholes for anything but the most common
8313 ; cases since, unlike combine, the increment must immediately follow the load
8314 ; for this pattern to match.
8315 ; We must watch to see that the source/destination register isn't also the
8316 ; same as the base address register, and that if the index is a register,
8317 ; that it is not the same as the base address register.  In such cases the
8318 ; instruction that we would generate would have UNPREDICTABLE behavior so 
8319 ; we cannot use it.
8320
8321 (define_peephole
8322   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8323         (match_operand:QI 2 "s_register_operand" "r"))
8324    (set (match_dup 0)
8325         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8326   "TARGET_ARM
8327    && (REGNO (operands[2]) != REGNO (operands[0]))
8328    && (GET_CODE (operands[1]) != REG
8329        || (REGNO (operands[1]) != REGNO (operands[0])))"
8330   "str%?b\\t%2, [%0], %1"
8331 )
8332
8333 (define_peephole
8334   [(set (match_operand:QI 0 "s_register_operand" "=r")
8335         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8336    (set (match_dup 1)
8337         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8338   "TARGET_ARM
8339    && REGNO (operands[0]) != REGNO(operands[1])
8340    && (GET_CODE (operands[2]) != REG
8341        || REGNO(operands[0]) != REGNO (operands[2]))"
8342   "ldr%?b\\t%0, [%1], %2"
8343 )
8344
8345 (define_peephole
8346   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8347         (match_operand:SI 2 "s_register_operand" "r"))
8348    (set (match_dup 0)
8349         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8350   "TARGET_ARM
8351    && (REGNO (operands[2]) != REGNO (operands[0]))
8352    && (GET_CODE (operands[1]) != REG
8353        || (REGNO (operands[1]) != REGNO (operands[0])))"
8354   "str%?\\t%2, [%0], %1"
8355 )
8356
8357 (define_peephole
8358   [(set (match_operand:HI 0 "s_register_operand" "=r")
8359         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8360    (set (match_dup 1)
8361         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8362   "TARGET_ARM
8363    && !BYTES_BIG_ENDIAN
8364    && !TARGET_MMU_TRAPS
8365    && !arm_arch4
8366    && REGNO (operands[0]) != REGNO(operands[1])
8367    && (GET_CODE (operands[2]) != REG
8368        || REGNO(operands[0]) != REGNO (operands[2]))"
8369   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8370 )
8371
8372 (define_peephole
8373   [(set (match_operand:SI 0 "s_register_operand" "=r")
8374         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8375    (set (match_dup 1)
8376         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8377   "TARGET_ARM
8378    && REGNO (operands[0]) != REGNO(operands[1])
8379    && (GET_CODE (operands[2]) != REG
8380        || REGNO(operands[0]) != REGNO (operands[2]))"
8381   "ldr%?\\t%0, [%1], %2"
8382 )
8383
8384 (define_peephole
8385   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8386                          (match_operand:SI 1 "index_operand" "rJ")))
8387         (match_operand:QI 2 "s_register_operand" "r"))
8388    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8389   "TARGET_ARM
8390    && (REGNO (operands[2]) != REGNO (operands[0]))
8391    && (GET_CODE (operands[1]) != REG
8392        || (REGNO (operands[1]) != REGNO (operands[0])))"
8393   "str%?b\\t%2, [%0, %1]!"
8394 )
8395
8396 (define_peephole
8397   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8398                           [(match_operand:SI 0 "s_register_operand" "r")
8399                            (match_operand:SI 1 "const_int_operand" "n")])
8400                          (match_operand:SI 2 "s_register_operand" "+r")))
8401         (match_operand:QI 3 "s_register_operand" "r"))
8402    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8403                                (match_dup 2)))]
8404   "TARGET_ARM
8405    && (REGNO (operands[3]) != REGNO (operands[2]))
8406    && (REGNO (operands[0]) != REGNO (operands[2]))"
8407   "str%?b\\t%3, [%2, %0%S4]!"
8408 )
8409
8410 ; This pattern is never tried by combine, so do it as a peephole
8411
8412 (define_peephole2
8413   [(set (match_operand:SI 0 "s_register_operand" "")
8414         (match_operand:SI 1 "s_register_operand" ""))
8415    (set (reg:CC CC_REGNUM)
8416         (compare:CC (match_dup 1) (const_int 0)))]
8417   "TARGET_ARM
8418    && (!TARGET_CIRRUS
8419        || (!cirrus_fp_register (operands[0], SImode)
8420            && !cirrus_fp_register (operands[1], SImode)))
8421   "
8422   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8423               (set (match_dup 0) (match_dup 1))])]
8424   ""
8425 )
8426
8427 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8428 ; reversed, check that the memory references aren't volatile.
8429
8430 (define_peephole
8431   [(set (match_operand:SI 0 "s_register_operand" "=r")
8432         (match_operand:SI 4 "memory_operand" "m"))
8433    (set (match_operand:SI 1 "s_register_operand" "=r")
8434         (match_operand:SI 5 "memory_operand" "m"))
8435    (set (match_operand:SI 2 "s_register_operand" "=r")
8436         (match_operand:SI 6 "memory_operand" "m"))
8437    (set (match_operand:SI 3 "s_register_operand" "=r")
8438         (match_operand:SI 7 "memory_operand" "m"))]
8439   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8440   "*
8441   return emit_ldm_seq (operands, 4);
8442   "
8443 )
8444
8445 (define_peephole
8446   [(set (match_operand:SI 0 "s_register_operand" "=r")
8447         (match_operand:SI 3 "memory_operand" "m"))
8448    (set (match_operand:SI 1 "s_register_operand" "=r")
8449         (match_operand:SI 4 "memory_operand" "m"))
8450    (set (match_operand:SI 2 "s_register_operand" "=r")
8451         (match_operand:SI 5 "memory_operand" "m"))]
8452   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8453   "*
8454   return emit_ldm_seq (operands, 3);
8455   "
8456 )
8457
8458 (define_peephole
8459   [(set (match_operand:SI 0 "s_register_operand" "=r")
8460         (match_operand:SI 2 "memory_operand" "m"))
8461    (set (match_operand:SI 1 "s_register_operand" "=r")
8462         (match_operand:SI 3 "memory_operand" "m"))]
8463   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8464   "*
8465   return emit_ldm_seq (operands, 2);
8466   "
8467 )
8468
8469 (define_peephole
8470   [(set (match_operand:SI 4 "memory_operand" "=m")
8471         (match_operand:SI 0 "s_register_operand" "r"))
8472    (set (match_operand:SI 5 "memory_operand" "=m")
8473         (match_operand:SI 1 "s_register_operand" "r"))
8474    (set (match_operand:SI 6 "memory_operand" "=m")
8475         (match_operand:SI 2 "s_register_operand" "r"))
8476    (set (match_operand:SI 7 "memory_operand" "=m")
8477         (match_operand:SI 3 "s_register_operand" "r"))]
8478   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8479   "*
8480   return emit_stm_seq (operands, 4);
8481   "
8482 )
8483
8484 (define_peephole
8485   [(set (match_operand:SI 3 "memory_operand" "=m")
8486         (match_operand:SI 0 "s_register_operand" "r"))
8487    (set (match_operand:SI 4 "memory_operand" "=m")
8488         (match_operand:SI 1 "s_register_operand" "r"))
8489    (set (match_operand:SI 5 "memory_operand" "=m")
8490         (match_operand:SI 2 "s_register_operand" "r"))]
8491   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8492   "*
8493   return emit_stm_seq (operands, 3);
8494   "
8495 )
8496
8497 (define_peephole
8498   [(set (match_operand:SI 2 "memory_operand" "=m")
8499         (match_operand:SI 0 "s_register_operand" "r"))
8500    (set (match_operand:SI 3 "memory_operand" "=m")
8501         (match_operand:SI 1 "s_register_operand" "r"))]
8502   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8503   "*
8504   return emit_stm_seq (operands, 2);
8505   "
8506 )
8507
8508 (define_split
8509   [(set (match_operand:SI 0 "s_register_operand" "")
8510         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8511                        (const_int 0))
8512                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8513                          [(match_operand:SI 3 "s_register_operand" "")
8514                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
8515    (clobber (match_operand:SI 5 "s_register_operand" ""))]
8516   "TARGET_ARM"
8517   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8518    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8519                               (match_dup 5)))]
8520   ""
8521 )
8522
8523 ;; This split can be used because CC_Z mode implies that the following
8524 ;; branch will be an equality, or an unsigned inequality, so the sign
8525 ;; extension is not needed.
8526
8527 (define_split
8528   [(set (reg:CC_Z CC_REGNUM)
8529         (compare:CC_Z
8530          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8531                     (const_int 24))
8532          (match_operand 1 "const_int_operand" "")))
8533    (clobber (match_scratch:SI 2 ""))]
8534   "TARGET_ARM
8535    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8536        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8537   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8538    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8539   "
8540   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8541   "
8542 )
8543
8544 (define_expand "prologue"
8545   [(clobber (const_int 0))]
8546   "TARGET_EITHER"
8547   "if (TARGET_ARM)
8548      arm_expand_prologue ();
8549    else
8550      thumb_expand_prologue ();
8551   DONE;
8552   "
8553 )
8554
8555 (define_expand "epilogue"
8556   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8557   "TARGET_EITHER"
8558   "
8559   if (TARGET_THUMB)
8560     thumb_expand_epilogue ();
8561   else if (USE_RETURN_INSN (FALSE))
8562     {
8563       emit_jump_insn (gen_return ());
8564       DONE;
8565     }
8566   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8567         gen_rtvec (1,
8568                 gen_rtx_RETURN (VOIDmode)),
8569         VUNSPEC_EPILOGUE));
8570   DONE;
8571   "
8572 )
8573
8574 ;; Note - although unspec_volatile's USE all hard registers,
8575 ;; USEs are ignored after relaod has completed.  Thus we need
8576 ;; to add an unspec of the link register to ensure that flow
8577 ;; does not think that it is unused by the sibcall branch that
8578 ;; will replace the standard function epilogue.
8579 (define_insn "sibcall_epilogue"
8580   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8581               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8582   "TARGET_ARM"
8583   "*
8584   if (USE_RETURN_INSN (FALSE))
8585     return output_return_instruction (const_true_rtx, FALSE, FALSE);
8586   return arm_output_epilogue (FALSE);
8587   "
8588 ;; Length is absolute worst case
8589   [(set_attr "length" "44")
8590    (set_attr "type" "block")
8591    ;; We don't clobber the conditions, but the potential length of this
8592    ;; operation is sufficient to make conditionalizing the sequence 
8593    ;; unlikely to be profitable.
8594    (set_attr "conds" "clob")]
8595 )
8596
8597 (define_insn "*epilogue_insns"
8598   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8599   "TARGET_EITHER"
8600   "*
8601   if (TARGET_ARM)
8602     return arm_output_epilogue (TRUE);
8603   else /* TARGET_THUMB */
8604     return thumb_unexpanded_epilogue ();
8605   "
8606   ; Length is absolute worst case
8607   [(set_attr "length" "44")
8608    (set_attr "type" "block")
8609    ;; We don't clobber the conditions, but the potential length of this
8610    ;; operation is sufficient to make conditionalizing the sequence 
8611    ;; unlikely to be profitable.
8612    (set_attr "conds" "clob")]
8613 )
8614
8615 (define_expand "eh_epilogue"
8616   [(use (match_operand:SI 0 "register_operand" "r"))
8617    (use (match_operand:SI 1 "register_operand" "r"))
8618    (use (match_operand:SI 2 "register_operand" "r"))]
8619   "TARGET_EITHER"
8620   "
8621   {
8622     cfun->machine->eh_epilogue_sp_ofs = operands[1];
8623     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8624       {
8625         rtx ra = gen_rtx_REG (Pmode, 2);
8626
8627         emit_move_insn (ra, operands[2]);
8628         operands[2] = ra;
8629       }
8630     /* This is a hack -- we may have crystalized the function type too
8631        early.  */
8632     cfun->machine->func_type = 0;
8633   }"
8634 )
8635
8636 ;; This split is only used during output to reduce the number of patterns
8637 ;; that need assembler instructions adding to them.  We allowed the setting
8638 ;; of the conditions to be implicit during rtl generation so that
8639 ;; the conditional compare patterns would work.  However this conflicts to
8640 ;; some extent with the conditional data operations, so we have to split them
8641 ;; up again here.
8642
8643 (define_split
8644   [(set (match_operand:SI 0 "s_register_operand" "")
8645         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8646                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8647                          (match_dup 0)
8648                          (match_operand 4 "" "")))
8649    (clobber (reg:CC CC_REGNUM))]
8650   "TARGET_ARM && reload_completed"
8651   [(set (match_dup 5) (match_dup 6))
8652    (cond_exec (match_dup 7)
8653               (set (match_dup 0) (match_dup 4)))]
8654   "
8655   {
8656     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8657                                              operands[2], operands[3]);
8658     enum rtx_code rc = GET_CODE (operands[1]);
8659
8660     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8661     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8662     if (mode == CCFPmode || mode == CCFPEmode)
8663       rc = reverse_condition_maybe_unordered (rc);
8664     else
8665       rc = reverse_condition (rc);
8666
8667     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8668   }"
8669 )
8670
8671 (define_split
8672   [(set (match_operand:SI 0 "s_register_operand" "")
8673         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8674                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8675                          (match_operand 4 "" "")
8676                          (match_dup 0)))
8677    (clobber (reg:CC CC_REGNUM))]
8678   "TARGET_ARM && reload_completed"
8679   [(set (match_dup 5) (match_dup 6))
8680    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8681               (set (match_dup 0) (match_dup 4)))]
8682   "
8683   {
8684     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8685                                              operands[2], operands[3]);
8686
8687     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8688     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8689   }"
8690 )
8691
8692 (define_split
8693   [(set (match_operand:SI 0 "s_register_operand" "")
8694         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8695                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8696                          (match_operand 4 "" "")
8697                          (match_operand 5 "" "")))
8698    (clobber (reg:CC CC_REGNUM))]
8699   "TARGET_ARM && reload_completed"
8700   [(set (match_dup 6) (match_dup 7))
8701    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8702               (set (match_dup 0) (match_dup 4)))
8703    (cond_exec (match_dup 8)
8704               (set (match_dup 0) (match_dup 5)))]
8705   "
8706   {
8707     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8708                                              operands[2], operands[3]);
8709     enum rtx_code rc = GET_CODE (operands[1]);
8710
8711     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8712     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8713     if (mode == CCFPmode || mode == CCFPEmode)
8714       rc = reverse_condition_maybe_unordered (rc);
8715     else
8716       rc = reverse_condition (rc);
8717
8718     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8719   }"
8720 )
8721
8722 (define_split
8723   [(set (match_operand:SI 0 "s_register_operand" "")
8724         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8725                           [(match_operand:SI 2 "s_register_operand" "")
8726                            (match_operand:SI 3 "arm_add_operand" "")])
8727                          (match_operand:SI 4 "arm_rhs_operand" "")
8728                          (not:SI
8729                           (match_operand:SI 5 "s_register_operand" ""))))
8730    (clobber (reg:CC CC_REGNUM))]
8731   "TARGET_ARM && reload_completed"
8732   [(set (match_dup 6) (match_dup 7))
8733    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8734               (set (match_dup 0) (match_dup 4)))
8735    (cond_exec (match_dup 8)
8736               (set (match_dup 0) (not:SI (match_dup 5))))]
8737   "
8738   {
8739     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8740                                              operands[2], operands[3]);
8741     enum rtx_code rc = GET_CODE (operands[1]);
8742
8743     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8744     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8745     if (mode == CCFPmode || mode == CCFPEmode)
8746       rc = reverse_condition_maybe_unordered (rc);
8747     else
8748       rc = reverse_condition (rc);
8749
8750     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8751   }"
8752 )
8753
8754 (define_insn "*cond_move_not"
8755   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8756         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8757                           [(match_operand 3 "cc_register" "") (const_int 0)])
8758                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8759                          (not:SI
8760                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
8761   "TARGET_ARM"
8762   "@
8763    mvn%D4\\t%0, %2
8764    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8765   [(set_attr "conds" "use")
8766    (set_attr "length" "4,8")]
8767 )
8768
8769 ;; The next two patterns occur when an AND operation is followed by a
8770 ;; scc insn sequence 
8771
8772 (define_insn "*sign_extract_onebit"
8773   [(set (match_operand:SI 0 "s_register_operand" "=r")
8774         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8775                          (const_int 1)
8776                          (match_operand:SI 2 "const_int_operand" "n")))
8777     (clobber (reg:CC CC_REGNUM))]
8778   "TARGET_ARM"
8779   "*
8780     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8781     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8782     return \"mvnne\\t%0, #0\";
8783   "
8784   [(set_attr "conds" "clob")
8785    (set_attr "length" "8")]
8786 )
8787
8788 (define_insn "*not_signextract_onebit"
8789   [(set (match_operand:SI 0 "s_register_operand" "=r")
8790         (not:SI
8791          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8792                           (const_int 1)
8793                           (match_operand:SI 2 "const_int_operand" "n"))))
8794    (clobber (reg:CC CC_REGNUM))]
8795   "TARGET_ARM"
8796   "*
8797     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8798     output_asm_insn (\"tst\\t%1, %2\", operands);
8799     output_asm_insn (\"mvneq\\t%0, #0\", operands);
8800     return \"movne\\t%0, #0\";
8801   "
8802   [(set_attr "conds" "clob")
8803    (set_attr "length" "12")]
8804 )
8805
8806 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8807 ;; expressions.  For simplicity, the first register is also in the unspec
8808 ;; part.
8809 (define_insn "*push_multi"
8810   [(match_parallel 2 "multi_register_push"
8811     [(set (match_operand:BLK 0 "memory_operand" "=m")
8812           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8813                       UNSPEC_PUSH_MULT))])]
8814   "TARGET_ARM"
8815   "*
8816   {
8817     int num_saves = XVECLEN (operands[2], 0);
8818      
8819     /* For the StrongARM at least it is faster to
8820        use STR to store only a single register.  */
8821     if (num_saves == 1)
8822       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8823     else
8824       {
8825         int i;
8826         char pattern[100];
8827
8828         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8829
8830         for (i = 1; i < num_saves; i++)
8831           {
8832             strcat (pattern, \", %|\");
8833             strcat (pattern,
8834                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8835           }
8836
8837         strcat (pattern, \"}\");
8838         output_asm_insn (pattern, operands);
8839       }
8840
8841     return \"\";
8842   }"
8843   [(set_attr "type" "store4")]
8844 )
8845
8846 (define_insn "stack_tie"
8847   [(set (mem:BLK (scratch))
8848         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8849                      (match_operand:SI 1 "s_register_operand" "r")]
8850                     UNSPEC_PRLG_STK))]
8851   ""
8852   ""
8853   [(set_attr "length" "0")]
8854 )
8855
8856 ;; Similarly for the floating point registers
8857 (define_insn "*push_fp_multi"
8858   [(match_parallel 2 "multi_register_push"
8859     [(set (match_operand:BLK 0 "memory_operand" "=m")
8860           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8861                       UNSPEC_PUSH_MULT))])]
8862   "TARGET_ARM"
8863   "*
8864   {
8865     char pattern[100];
8866
8867     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8868     output_asm_insn (pattern, operands);
8869     return \"\";
8870   }"
8871   [(set_attr "type" "f_store")]
8872 )
8873
8874 ;; Special patterns for dealing with the constant pool
8875
8876 (define_insn "align_4"
8877   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8878   "TARGET_EITHER"
8879   "*
8880   assemble_align (32);
8881   return \"\";
8882   "
8883 )
8884
8885 (define_insn "consttable_end"
8886   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8887   "TARGET_EITHER"
8888   "*
8889   making_const_table = FALSE;
8890   return \"\";
8891   "
8892 )
8893
8894 (define_insn "consttable_1"
8895   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8896   "TARGET_THUMB"
8897   "*
8898   making_const_table = TRUE;
8899   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8900   assemble_zeros (3);
8901   return \"\";
8902   "
8903   [(set_attr "length" "4")]
8904 )
8905
8906 (define_insn "consttable_2"
8907   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8908   "TARGET_THUMB"
8909   "*
8910   making_const_table = TRUE;
8911   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8912   assemble_zeros (2);
8913   return \"\";
8914   "
8915   [(set_attr "length" "4")]
8916 )
8917
8918 (define_insn "consttable_4"
8919   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8920   "TARGET_EITHER"
8921   "*
8922   {
8923     making_const_table = TRUE;
8924     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8925       {
8926       case MODE_FLOAT:
8927       {
8928         REAL_VALUE_TYPE r;
8929         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8930         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8931         break;
8932       }
8933       default:
8934         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8935         break;
8936       }
8937     return \"\";
8938   }"
8939   [(set_attr "length" "4")]
8940 )
8941
8942 (define_insn "consttable_8"
8943   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8944   "TARGET_EITHER"
8945   "*
8946   {
8947     making_const_table = TRUE;
8948     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8949       {
8950        case MODE_FLOAT:
8951         {
8952           REAL_VALUE_TYPE r;
8953           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8954           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8955           break;
8956         }
8957       default:
8958         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8959         break;
8960       }
8961     return \"\";
8962   }"
8963   [(set_attr "length" "8")]
8964 )
8965
8966 ;; Miscellaneous Thumb patterns
8967
8968 (define_expand "tablejump"
8969   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8970               (use (label_ref (match_operand 1 "" "")))])]
8971   "TARGET_THUMB"
8972   "
8973   if (flag_pic)
8974     {
8975       /* Hopefully, CSE will eliminate this copy.  */
8976       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8977       rtx reg2 = gen_reg_rtx (SImode);
8978
8979       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8980       operands[0] = reg2;
8981     }
8982   "
8983 )
8984
8985 (define_insn "*thumb_tablejump"
8986   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8987    (use (label_ref (match_operand 1 "" "")))]
8988   "TARGET_THUMB"
8989   "mov\\t%|pc, %0"
8990   [(set_attr "length" "2")]
8991 )
8992
8993 ;; V5 Instructions,
8994
8995 (define_insn "clzsi2"
8996   [(set (match_operand:SI 0 "s_register_operand" "=r")
8997         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8998   "TARGET_ARM && arm_arch5"
8999   "clz\\t%0, %1")
9000
9001 (define_expand "ffssi2"
9002   [(set (match_operand:SI 0 "s_register_operand" "")
9003         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9004   "TARGET_ARM && arm_arch5"
9005   "
9006   {
9007     rtx t1, t2, t3;
9008
9009     t1 = gen_reg_rtx (SImode);
9010     t2 = gen_reg_rtx (SImode);
9011     t3 = gen_reg_rtx (SImode);
9012
9013     emit_insn (gen_negsi2 (t1, operands[1]));
9014     emit_insn (gen_andsi3 (t2, operands[1], t1));
9015     emit_insn (gen_clzsi2 (t3, t2));
9016     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9017     DONE;
9018   }"
9019 )
9020
9021 (define_expand "ctzsi2"
9022   [(set (match_operand:SI 0 "s_register_operand" "")
9023         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
9024   "TARGET_ARM && arm_arch5"
9025   "
9026   {
9027     rtx t1, t2, t3;
9028
9029     t1 = gen_reg_rtx (SImode);
9030     t2 = gen_reg_rtx (SImode);
9031     t3 = gen_reg_rtx (SImode);
9032
9033     emit_insn (gen_negsi2 (t1, operands[1]));
9034     emit_insn (gen_andsi3 (t2, operands[1], t1));
9035     emit_insn (gen_clzsi2 (t3, t2));
9036     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
9037     DONE;
9038   }"
9039 )
9040
9041 ;; V5E instructions.
9042
9043 (define_insn "prefetch"
9044   [(prefetch (match_operand:SI 0 "address_operand" "p")
9045              (match_operand:SI 1 "" "")
9046              (match_operand:SI 2 "" ""))]
9047   "TARGET_ARM && arm_arch5e"
9048   "pld\\t%a0")
9049
9050 ;; General predication pattern
9051
9052 (define_cond_exec
9053   [(match_operator 0 "arm_comparison_operator"
9054     [(match_operand 1 "cc_register" "")
9055      (const_int 0)])]
9056   "TARGET_ARM"
9057   ""
9058 )
9059
9060 (define_insn "prologue_use"
9061   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9062   ""
9063   "%@ %0 needed for prologue"
9064 )