OSDN Git Service

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