OSDN Git Service

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