OSDN Git Service

* arm.md: Include predicates.md.
[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 2004  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    (VUNSPEC_EH_RETURN 20); Use to overrite the return address for exception
121                          ; handling.
122   ]
123 )
124 \f
125 ;;---------------------------------------------------------------------------
126 ;; Attributes
127
128 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
129 ; generating ARM code.  This is used to control the length of some insn
130 ; patterns that share the same RTL in both ARM and Thumb code.
131 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
132
133 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
134 ; scheduling decisions for the load unit and the multiplier.
135 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
136
137 ; IS_XSCALE is set to 'yes' when compiling for XScale.
138 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
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 "shift" "" (const_int 0))
143
144 ; Floating Point Unit.  If we only have floating point emulation, then there
145 ; is no point in scheduling the floating point insns.  (Well, for best
146 ; performance we should try and group them together).
147 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
148   (const (symbol_ref "arm_fpu_attr")))
149
150 ; LENGTH of an instruction (in bytes)
151 (define_attr "length" "" (const_int 4))
152
153 ; POOL_RANGE is how far away from a constant pool entry that this insn
154 ; can be placed.  If the distance is zero, then this insn will never
155 ; reference the pool.
156 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
157 ; before its address.
158 (define_attr "pool_range" "" (const_int 0))
159 (define_attr "neg_pool_range" "" (const_int 0))
160
161 ; An assembler sequence may clobber the condition codes without us knowing.
162 ; If such an insn references the pool, then we have no way of knowing how,
163 ; so use the most conservative value for pool_range.
164 (define_asm_attributes
165  [(set_attr "conds" "clob")
166   (set_attr "length" "4")
167   (set_attr "pool_range" "250")])
168
169 ;; The instruction used to implement a particular pattern.  This
170 ;; information is used by pipeline descriptions to provide accurate
171 ;; scheduling information.
172
173 (define_attr "insn"
174         "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
175         (const_string "other"))
176
177 ; TYPE attribute is used to detect floating point instructions which, if
178 ; running on a co-processor can run in parallel with other, basic instructions
179 ; If write-buffer scheduling is enabled then it can also be used in the
180 ; scheduling of writes.
181
182 ; Classification of each insn
183 ; alu           any alu  instruction that doesn't hit memory or fp
184 ;               regs or have a shifted source operand
185 ; alu_shift     any data instruction that doesn't hit memory or fp
186 ;               regs, but has a source operand shifted by a constant
187 ; alu_shift_reg any data instruction that doesn't hit memory or fp
188 ;               regs, but has a source operand shifted by a register value
189 ; mult          a multiply instruction
190 ; block         blockage insn, this blocks all functional units
191 ; float         a floating point arithmetic operation (subject to expansion)
192 ; fdivd         DFmode floating point division
193 ; fdivs         SFmode floating point division
194 ; fmul          Floating point multiply
195 ; ffmul         Fast floating point multiply
196 ; farith        Floating point arithmetic (4 cycle)
197 ; ffarith       Fast floating point arithmetic (2 cycle)
198 ; float_em      a floating point arithmetic operation that is normally emulated
199 ;               even on a machine with an fpa.
200 ; f_load        a floating point load from memory
201 ; f_store       a floating point store to memory
202 ; f_mem_r       a transfer of a floating point register to a real reg via mem
203 ; r_mem_f       the reverse of f_mem_r
204 ; f_2_r         fast transfer float to arm (no memory needed)
205 ; r_2_f         fast transfer arm to float
206 ; branch        a branch
207 ; call          a subroutine call
208 ; load_byte     load byte(s) from memory to arm registers
209 ; load1         load 1 word from memory to arm registers
210 ; load2         load 2 words from memory to arm registers
211 ; load3         load 3 words from memory to arm registers
212 ; load4         load 4 words from memory to arm registers
213 ; store         store 1 word to memory from arm registers
214 ; store2        store 2 words
215 ; store3        store 3 words
216 ; store4        store 4 (or more) words
217 ;  Additions for Cirrus Maverick co-processor:
218 ; mav_farith    Floating point arithmetic (4 cycle)
219 ; mav_dmult     Double multiplies (7 cycle)
220 ;
221 (define_attr "type"
222         "alu,alu_shift,alu_shift_reg,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,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
223         (if_then_else 
224          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
225          (const_string "mult")
226          (const_string "alu")))
227
228 ; Load scheduling, set from the arm_ld_sched variable
229 ; initialized by arm_override_options() 
230 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
231
232 ; condition codes: this one is used by final_prescan_insn to speed up
233 ; conditionalizing instructions.  It saves having to scan the rtl to see if
234 ; it uses or alters the condition codes.
235
236 ; USE means that the condition codes are used by the insn in the process of
237 ;   outputting code, this means (at present) that we can't use the insn in
238 ;   inlined branches
239 ;
240 ; SET means that the purpose of the insn is to set the condition codes in a
241 ;   well defined manner.
242 ;
243 ; CLOB means that the condition codes are altered in an undefined manner, if
244 ;   they are altered at all
245 ;
246 ; JUMP_CLOB is used when the condition cannot be represented by a single
247 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
248 ;
249 ; NOCOND means that the condition codes are neither altered nor affect the
250 ;   output of this insn
251
252 (define_attr "conds" "use,set,clob,jump_clob,nocond"
253         (if_then_else (eq_attr "type" "call")
254          (const_string "clob")
255          (const_string "nocond")))
256
257 ; Predicable means that the insn can be conditionally executed based on
258 ; an automatically added predicate (additional patterns are generated by 
259 ; gen...).  We default to 'no' because no Thumb patterns match this rule
260 ; and not all ARM patterns do.
261 (define_attr "predicable" "no,yes" (const_string "no"))
262
263 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
264 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
265 ; suffer blockages enough to warrant modelling this (and it can adversely
266 ; affect the schedule).
267 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
268
269 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
270 ; to stall the processor.  Used with model_wbuf above.
271 (define_attr "write_conflict" "no,yes"
272   (if_then_else (eq_attr "type"
273                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
274                 (const_string "yes")
275                 (const_string "no")))
276
277 ; Classify the insns into those that take one cycle and those that take more
278 ; than one on the main cpu execution unit.
279 (define_attr "core_cycles" "single,multi"
280   (if_then_else (eq_attr "type"
281                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
282                 (const_string "single")
283                 (const_string "multi")))
284
285 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
286 ;; distant label.  Only applicable to Thumb code.
287 (define_attr "far_jump" "yes,no" (const_string "no"))
288
289 (include "predicates.md")
290
291 ;;---------------------------------------------------------------------------
292 ;; Pipeline descriptions
293
294 ;; Processor type.  This is created automatically from arm-cores.def.
295 (include "arm-tune.md")
296
297 ;; True if the generic scheduling description should be used.
298
299 (define_attr "generic_sched" "yes,no"
300         (if_then_else 
301          (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
302          (const_string "no")
303          (const_string "yes")))
304         
305 (include "arm-generic.md")
306 (include "arm926ejs.md")
307 (include "arm1026ejs.md")
308 (include "arm1136jfs.md")
309
310 \f
311 ;;---------------------------------------------------------------------------
312 ;; Insn patterns
313 ;;
314 ;; Addition insns.
315
316 ;; Note: For DImode insns, there is normally no reason why operands should
317 ;; not be in the same register, what we don't want is for something being
318 ;; written to partially overlap something that is an input.
319 ;; Cirrus 64bit additions should not be split because we have a native
320 ;; 64bit addition instructions.
321
322 (define_expand "adddi3"
323  [(parallel
324    [(set (match_operand:DI           0 "s_register_operand" "")
325           (plus:DI (match_operand:DI 1 "s_register_operand" "")
326                    (match_operand:DI 2 "s_register_operand" "")))
327     (clobber (reg:CC CC_REGNUM))])]
328   "TARGET_EITHER"
329   "
330   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
331     {
332       if (!cirrus_fp_register (operands[0], DImode))
333         operands[0] = force_reg (DImode, operands[0]);
334       if (!cirrus_fp_register (operands[1], DImode))
335         operands[1] = force_reg (DImode, operands[1]);
336       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
337       DONE;
338     }
339
340   if (TARGET_THUMB)
341     {
342       if (GET_CODE (operands[1]) != REG)
343         operands[1] = force_reg (SImode, operands[1]);
344       if (GET_CODE (operands[2]) != REG)
345         operands[2] = force_reg (SImode, operands[2]);
346      }
347   "
348 )
349
350 (define_insn "*thumb_adddi3"
351   [(set (match_operand:DI          0 "register_operand" "=l")
352         (plus:DI (match_operand:DI 1 "register_operand" "%0")
353                  (match_operand:DI 2 "register_operand" "l")))
354    (clobber (reg:CC CC_REGNUM))
355   ]
356   "TARGET_THUMB"
357   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
358   [(set_attr "length" "4")]
359 )
360
361 (define_insn_and_split "*arm_adddi3"
362   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
363         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
364                  (match_operand:DI 2 "s_register_operand" "r,  0")))
365    (clobber (reg:CC CC_REGNUM))]
366   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
367   "#"
368   "TARGET_ARM && reload_completed"
369   [(parallel [(set (reg:CC_C CC_REGNUM)
370                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
371                                  (match_dup 1)))
372               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
373    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
374                                (plus:SI (match_dup 4) (match_dup 5))))]
375   "
376   {
377     operands[3] = gen_highpart (SImode, operands[0]);
378     operands[0] = gen_lowpart (SImode, operands[0]);
379     operands[4] = gen_highpart (SImode, operands[1]);
380     operands[1] = gen_lowpart (SImode, operands[1]);
381     operands[5] = gen_highpart (SImode, operands[2]);
382     operands[2] = gen_lowpart (SImode, operands[2]);
383   }"
384   [(set_attr "conds" "clob")
385    (set_attr "length" "8")]
386 )
387
388 (define_insn_and_split "*adddi_sesidi_di"
389   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
390         (plus:DI (sign_extend:DI
391                   (match_operand:SI 2 "s_register_operand" "r,r"))
392                  (match_operand:DI 1 "s_register_operand" "r,0")))
393    (clobber (reg:CC CC_REGNUM))]
394   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
395   "#"
396   "TARGET_ARM && reload_completed"
397   [(parallel [(set (reg:CC_C CC_REGNUM)
398                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
399                                  (match_dup 1)))
400               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
401    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
402                                (plus:SI (ashiftrt:SI (match_dup 2)
403                                                      (const_int 31))
404                                         (match_dup 4))))]
405   "
406   {
407     operands[3] = gen_highpart (SImode, operands[0]);
408     operands[0] = gen_lowpart (SImode, operands[0]);
409     operands[4] = gen_highpart (SImode, operands[1]);
410     operands[1] = gen_lowpart (SImode, operands[1]);
411     operands[2] = gen_lowpart (SImode, operands[2]);
412   }"
413   [(set_attr "conds" "clob")
414    (set_attr "length" "8")]
415 )
416
417 (define_insn_and_split "*adddi_zesidi_di"
418   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
419         (plus:DI (zero_extend:DI
420                   (match_operand:SI 2 "s_register_operand" "r,r"))
421                  (match_operand:DI 1 "s_register_operand" "r,0")))
422    (clobber (reg:CC CC_REGNUM))]
423   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
424   "#"
425   "TARGET_ARM && reload_completed"
426   [(parallel [(set (reg:CC_C CC_REGNUM)
427                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
428                                  (match_dup 1)))
429               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
430    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
431                                (plus:SI (match_dup 4) (const_int 0))))]
432   "
433   {
434     operands[3] = gen_highpart (SImode, operands[0]);
435     operands[0] = gen_lowpart (SImode, operands[0]);
436     operands[4] = gen_highpart (SImode, operands[1]);
437     operands[1] = gen_lowpart (SImode, operands[1]);
438     operands[2] = gen_lowpart (SImode, operands[2]);
439   }"
440   [(set_attr "conds" "clob")
441    (set_attr "length" "8")]
442 )
443
444 (define_expand "addsi3"
445   [(set (match_operand:SI          0 "s_register_operand" "")
446         (plus:SI (match_operand:SI 1 "s_register_operand" "")
447                  (match_operand:SI 2 "reg_or_int_operand" "")))]
448   "TARGET_EITHER"
449   "
450   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
451     {
452       arm_split_constant (PLUS, SImode, NULL_RTX,
453                           INTVAL (operands[2]), operands[0], operands[1],
454                           optimize && !no_new_pseudos);
455       DONE;
456     }
457   "
458 )
459
460 ; If there is a scratch available, this will be faster than synthesizing the
461 ; addition.
462 (define_peephole2
463   [(match_scratch:SI 3 "r")
464    (set (match_operand:SI          0 "arm_general_register_operand" "")
465         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
466                  (match_operand:SI 2 "const_int_operand"  "")))]
467   "TARGET_ARM &&
468    !(const_ok_for_arm (INTVAL (operands[2]))
469      || const_ok_for_arm (-INTVAL (operands[2])))
470     && const_ok_for_arm (~INTVAL (operands[2]))"
471   [(set (match_dup 3) (match_dup 2))
472    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
473   ""
474 )
475
476 (define_insn_and_split "*arm_addsi3"
477   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
478         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
479                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
480   "TARGET_ARM"
481   "@
482    add%?\\t%0, %1, %2
483    sub%?\\t%0, %1, #%n2
484    #"
485   "TARGET_ARM &&
486    GET_CODE (operands[2]) == CONST_INT
487    && !(const_ok_for_arm (INTVAL (operands[2]))
488         || const_ok_for_arm (-INTVAL (operands[2])))"
489   [(clobber (const_int 0))]
490   "
491   arm_split_constant (PLUS, SImode, curr_insn,
492                       INTVAL (operands[2]), operands[0],
493                       operands[1], 0);
494   DONE;
495   "
496   [(set_attr "length" "4,4,16")
497    (set_attr "predicable" "yes")]
498 )
499
500 ;; Register group 'k' is a single register group containing only the stack
501 ;; register.  Trying to reload it will always fail catastrophically,
502 ;; so never allow those alternatives to match if reloading is needed.
503
504 (define_insn "*thumb_addsi3"
505   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
506         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
507                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
508   "TARGET_THUMB"
509   "*
510    static const char * const asms[] = 
511    {
512      \"add\\t%0, %0, %2\",
513      \"sub\\t%0, %0, #%n2\",
514      \"add\\t%0, %1, %2\",
515      \"add\\t%0, %0, %2\",
516      \"add\\t%0, %0, %2\",
517      \"add\\t%0, %1, %2\",
518      \"add\\t%0, %1, %2\"
519    };
520    if ((which_alternative == 2 || which_alternative == 6)
521        && GET_CODE (operands[2]) == CONST_INT
522        && INTVAL (operands[2]) < 0)
523      return \"sub\\t%0, %1, #%n2\";
524    return asms[which_alternative];
525   "
526   [(set_attr "length" "2")]
527 )
528
529 ;; Reloading and elimination of the frame pointer can
530 ;; sometimes cause this optimization to be missed.
531 (define_peephole2
532   [(set (match_operand:SI 0 "arm_general_register_operand" "")
533         (match_operand:SI 1 "const_int_operand" ""))
534    (set (match_dup 0)
535         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
536   "TARGET_THUMB
537    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
538    && (INTVAL (operands[1]) & 3) == 0"
539   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
540   ""
541 )
542
543 (define_insn "*addsi3_compare0"
544   [(set (reg:CC_NOOV CC_REGNUM)
545         (compare:CC_NOOV
546          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
547                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
548          (const_int 0)))
549    (set (match_operand:SI 0 "s_register_operand" "=r,r")
550         (plus:SI (match_dup 1) (match_dup 2)))]
551   "TARGET_ARM"
552   "@
553    add%?s\\t%0, %1, %2
554    sub%?s\\t%0, %1, #%n2"
555   [(set_attr "conds" "set")]
556 )
557
558 (define_insn "*addsi3_compare0_scratch"
559   [(set (reg:CC_NOOV CC_REGNUM)
560         (compare:CC_NOOV
561          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
562                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
563          (const_int 0)))]
564   "TARGET_ARM"
565   "@
566    cmn%?\\t%0, %1
567    cmp%?\\t%0, #%n1"
568   [(set_attr "conds" "set")]
569 )
570
571 ;; These patterns are the same ones as the two regular addsi3_compare0
572 ;; patterns, except we write them slightly different - the combiner
573 ;; tends to generate them this way.
574 (define_insn "*addsi3_compare0_for_combiner"
575   [(set (reg:CC CC_REGNUM)
576         (compare:CC
577          (match_operand:SI 1 "s_register_operand" "r,r")
578          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
579    (set (match_operand:SI 0 "s_register_operand" "=r,r")
580         (plus:SI (match_dup 1) (match_dup 2)))]
581   "TARGET_ARM"
582   "@
583    add%?s\\t%0, %1, %2
584    sub%?s\\t%0, %1, #%n2"
585   [(set_attr "conds" "set")]
586 )
587
588 (define_insn "*addsi3_compare0_scratch_for_combiner"
589   [(set (reg:CC CC_REGNUM)
590         (compare:CC
591          (match_operand:SI 0 "s_register_operand" "r,r")
592          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
593   "TARGET_ARM"
594   "@
595    cmn%?\\t%0, %1
596    cmp%?\\t%0, #%n1"
597   [(set_attr "conds" "set")]
598 )
599
600 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
601 ;; addend is a constant.
602 (define_insn "*cmpsi2_addneg"
603   [(set (reg:CC CC_REGNUM)
604         (compare:CC
605          (match_operand:SI 1 "s_register_operand" "r,r")
606          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
607    (set (match_operand:SI 0 "s_register_operand" "=r,r")
608         (plus:SI (match_dup 1)
609                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
610   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
611   "@
612    sub%?s\\t%0, %1, %2
613    add%?s\\t%0, %1, #%n2"
614   [(set_attr "conds" "set")]
615 )
616
617 ;; Convert the sequence
618 ;;  sub  rd, rn, #1
619 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
620 ;;  bne  dest
621 ;; into
622 ;;  subs rd, rn, #1
623 ;;  bcs  dest   ((unsigned)rn >= 1)
624 ;; similarly for the beq variant using bcc.
625 ;; This is a common looping idiom (while (n--))
626 (define_peephole2
627   [(set (match_operand:SI 0 "arm_general_register_operand" "")
628         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
629                  (const_int -1)))
630    (set (match_operand 2 "cc_register" "")
631         (compare (match_dup 0) (const_int -1)))
632    (set (pc)
633         (if_then_else (match_operator 3 "equality_operator"
634                        [(match_dup 2) (const_int 0)])
635                       (match_operand 4 "" "")
636                       (match_operand 5 "" "")))]
637   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
638   [(parallel[
639     (set (match_dup 2)
640          (compare:CC
641           (match_dup 1) (const_int 1)))
642     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
643    (set (pc)
644         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
645                       (match_dup 4)
646                       (match_dup 5)))]
647   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
648    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
649                                   ? GEU : LTU),
650                                  VOIDmode, 
651                                  operands[2], const0_rtx);"
652 )
653
654 ;; The next four insns work because they compare the result with one of
655 ;; the operands, and we know that the use of the condition code is
656 ;; either GEU or LTU, so we can use the carry flag from the addition
657 ;; instead of doing the compare a second time.
658 (define_insn "*addsi3_compare_op1"
659   [(set (reg:CC_C CC_REGNUM)
660         (compare:CC_C
661          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
662                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
663          (match_dup 1)))
664    (set (match_operand:SI 0 "s_register_operand" "=r,r")
665         (plus:SI (match_dup 1) (match_dup 2)))]
666   "TARGET_ARM"
667   "@
668    add%?s\\t%0, %1, %2
669    sub%?s\\t%0, %1, #%n2"
670   [(set_attr "conds" "set")]
671 )
672
673 (define_insn "*addsi3_compare_op2"
674   [(set (reg:CC_C CC_REGNUM)
675         (compare:CC_C
676          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
677                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
678          (match_dup 2)))
679    (set (match_operand:SI 0 "s_register_operand" "=r,r")
680         (plus:SI (match_dup 1) (match_dup 2)))]
681   "TARGET_ARM"
682   "@
683    add%?s\\t%0, %1, %2
684    sub%?s\\t%0, %1, #%n2"
685   [(set_attr "conds" "set")]
686 )
687
688 (define_insn "*compare_addsi2_op0"
689   [(set (reg:CC_C CC_REGNUM)
690         (compare:CC_C
691          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
692                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
693          (match_dup 0)))]
694   "TARGET_ARM"
695   "@
696    cmn%?\\t%0, %1
697    cmp%?\\t%0, #%n1"
698   [(set_attr "conds" "set")]
699 )
700
701 (define_insn "*compare_addsi2_op1"
702   [(set (reg:CC_C CC_REGNUM)
703         (compare:CC_C
704          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
705                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
706          (match_dup 1)))]
707   "TARGET_ARM"
708   "@
709    cmn%?\\t%0, %1
710    cmp%?\\t%0, #%n1"
711   [(set_attr "conds" "set")]
712 )
713
714 (define_insn "*addsi3_carryin"
715   [(set (match_operand:SI 0 "s_register_operand" "=r")
716         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
717                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
718                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
719   "TARGET_ARM"
720   "adc%?\\t%0, %1, %2"
721   [(set_attr "conds" "use")]
722 )
723
724 (define_insn "*addsi3_carryin_shift"
725   [(set (match_operand:SI 0 "s_register_operand" "=r")
726         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
727                  (plus:SI
728                    (match_operator:SI 2 "shift_operator"
729                       [(match_operand:SI 3 "s_register_operand" "r")
730                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
731                     (match_operand:SI 1 "s_register_operand" "r"))))]
732   "TARGET_ARM"
733   "adc%?\\t%0, %1, %3%S2"
734   [(set_attr "conds" "use")
735    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
736                       (const_string "alu_shift")
737                       (const_string "alu_shift_reg")))]
738 )
739
740 (define_insn "*addsi3_carryin_alt1"
741   [(set (match_operand:SI 0 "s_register_operand" "=r")
742         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
743                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
744                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
745   "TARGET_ARM"
746   "adc%?\\t%0, %1, %2"
747   [(set_attr "conds" "use")]
748 )
749
750 (define_insn "*addsi3_carryin_alt2"
751   [(set (match_operand:SI 0 "s_register_operand" "=r")
752         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
753                           (match_operand:SI 1 "s_register_operand" "r"))
754                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
755   "TARGET_ARM"
756   "adc%?\\t%0, %1, %2"
757   [(set_attr "conds" "use")]
758 )
759
760 (define_insn "*addsi3_carryin_alt3"
761   [(set (match_operand:SI 0 "s_register_operand" "=r")
762         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
763                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
764                  (match_operand:SI 1 "s_register_operand" "r")))]
765   "TARGET_ARM"
766   "adc%?\\t%0, %1, %2"
767   [(set_attr "conds" "use")]
768 )
769
770 (define_insn "incscc"
771   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
772         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
773                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
774                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
775   "TARGET_ARM"
776   "@
777   add%d2\\t%0, %1, #1
778   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
779   [(set_attr "conds" "use")
780    (set_attr "length" "4,8")]
781 )
782
783 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
784 (define_split
785   [(set (match_operand:SI 0 "s_register_operand" "")
786         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
787                             (match_operand:SI 2 "s_register_operand" ""))
788                  (const_int -1)))
789    (clobber (match_operand:SI 3 "s_register_operand" ""))]
790   "TARGET_ARM"
791   [(set (match_dup 3) (match_dup 1))
792    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
793   "
794   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
795 ")
796
797 (define_expand "addsf3"
798   [(set (match_operand:SF          0 "s_register_operand" "")
799         (plus:SF (match_operand:SF 1 "s_register_operand" "")
800                  (match_operand:SF 2 "arm_float_add_operand" "")))]
801   "TARGET_ARM && TARGET_HARD_FLOAT"
802   "
803   if (TARGET_MAVERICK
804       && !cirrus_fp_register (operands[2], SFmode))
805     operands[2] = force_reg (SFmode, operands[2]);
806 ")
807
808 (define_expand "adddf3"
809   [(set (match_operand:DF          0 "s_register_operand" "")
810         (plus:DF (match_operand:DF 1 "s_register_operand" "")
811                  (match_operand:DF 2 "arm_float_add_operand" "")))]
812   "TARGET_ARM && TARGET_HARD_FLOAT"
813   "
814   if (TARGET_MAVERICK
815       && !cirrus_fp_register (operands[2], DFmode))
816     operands[2] = force_reg (DFmode, operands[2]);
817 ")
818
819 (define_expand "subdi3"
820  [(parallel
821    [(set (match_operand:DI            0 "s_register_operand" "")
822           (minus:DI (match_operand:DI 1 "s_register_operand" "")
823                     (match_operand:DI 2 "s_register_operand" "")))
824     (clobber (reg:CC CC_REGNUM))])]
825   "TARGET_EITHER"
826   "
827   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
828       && TARGET_ARM
829       && cirrus_fp_register (operands[0], DImode)
830       && cirrus_fp_register (operands[1], DImode))
831     {
832       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
833       DONE;
834     }
835
836   if (TARGET_THUMB)
837     {
838       if (GET_CODE (operands[1]) != REG)
839         operands[1] = force_reg (SImode, operands[1]);
840       if (GET_CODE (operands[2]) != REG)
841         operands[2] = force_reg (SImode, operands[2]);
842      }  
843   "
844 )
845
846 (define_insn "*arm_subdi3"
847   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
848         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
849                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
850    (clobber (reg:CC CC_REGNUM))]
851   "TARGET_ARM"
852   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
853   [(set_attr "conds" "clob")
854    (set_attr "length" "8")]
855 )
856
857 (define_insn "*thumb_subdi3"
858   [(set (match_operand:DI           0 "register_operand" "=l")
859         (minus:DI (match_operand:DI 1 "register_operand"  "0")
860                   (match_operand:DI 2 "register_operand"  "l")))
861    (clobber (reg:CC CC_REGNUM))]
862   "TARGET_THUMB"
863   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
864   [(set_attr "length" "4")]
865 )
866
867 (define_insn "*subdi_di_zesidi"
868   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
869         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
870                   (zero_extend:DI
871                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
872    (clobber (reg:CC CC_REGNUM))]
873   "TARGET_ARM"
874   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
875   [(set_attr "conds" "clob")
876    (set_attr "length" "8")]
877 )
878
879 (define_insn "*subdi_di_sesidi"
880   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
881         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
882                   (sign_extend:DI
883                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
884    (clobber (reg:CC CC_REGNUM))]
885   "TARGET_ARM"
886   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
887   [(set_attr "conds" "clob")
888    (set_attr "length" "8")]
889 )
890
891 (define_insn "*subdi_zesidi_di"
892   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
893         (minus:DI (zero_extend:DI
894                    (match_operand:SI 2 "s_register_operand"  "r,r"))
895                   (match_operand:DI  1 "s_register_operand" "?r,0")))
896    (clobber (reg:CC CC_REGNUM))]
897   "TARGET_ARM"
898   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
899   [(set_attr "conds" "clob")
900    (set_attr "length" "8")]
901 )
902
903 (define_insn "*subdi_sesidi_di"
904   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
905         (minus:DI (sign_extend:DI
906                    (match_operand:SI 2 "s_register_operand"   "r,r"))
907                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
908    (clobber (reg:CC CC_REGNUM))]
909   "TARGET_ARM"
910   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
911   [(set_attr "conds" "clob")
912    (set_attr "length" "8")]
913 )
914
915 (define_insn "*subdi_zesidi_zesidi"
916   [(set (match_operand:DI            0 "s_register_operand" "=r")
917         (minus:DI (zero_extend:DI
918                    (match_operand:SI 1 "s_register_operand"  "r"))
919                   (zero_extend:DI
920                    (match_operand:SI 2 "s_register_operand"  "r"))))
921    (clobber (reg:CC CC_REGNUM))]
922   "TARGET_ARM"
923   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
924   [(set_attr "conds" "clob")
925    (set_attr "length" "8")]
926 )
927
928 (define_expand "subsi3"
929   [(set (match_operand:SI           0 "s_register_operand" "")
930         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
931                   (match_operand:SI 2 "s_register_operand" "")))]
932   "TARGET_EITHER"
933   "
934   if (GET_CODE (operands[1]) == CONST_INT)
935     {
936       if (TARGET_ARM)
937         {
938           arm_split_constant (MINUS, SImode, NULL_RTX,
939                               INTVAL (operands[1]), operands[0],
940                               operands[2], optimize && !no_new_pseudos);
941           DONE;
942         }
943       else /* TARGET_THUMB */
944         operands[1] = force_reg (SImode, operands[1]);
945     }
946   "
947 )
948
949 (define_insn "*thumb_subsi3_insn"
950   [(set (match_operand:SI           0 "register_operand" "=l")
951         (minus:SI (match_operand:SI 1 "register_operand" "l")
952                   (match_operand:SI 2 "register_operand" "l")))]
953   "TARGET_THUMB"
954   "sub\\t%0, %1, %2"
955   [(set_attr "length" "2")]
956 )
957
958 (define_insn_and_split "*arm_subsi3_insn"
959   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
960         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
961                   (match_operand:SI 2 "s_register_operand" "r,r")))]
962   "TARGET_ARM"
963   "@
964    rsb%?\\t%0, %2, %1
965    #"
966   "TARGET_ARM
967    && GET_CODE (operands[1]) == CONST_INT
968    && !const_ok_for_arm (INTVAL (operands[1]))"
969   [(clobber (const_int 0))]
970   "
971   arm_split_constant (MINUS, SImode, curr_insn,
972                       INTVAL (operands[1]), operands[0], operands[2], 0);
973   DONE;
974   "
975   [(set_attr "length" "4,16")
976    (set_attr "predicable" "yes")]
977 )
978
979 (define_peephole2
980   [(match_scratch:SI 3 "r")
981    (set (match_operand:SI 0 "arm_general_register_operand" "")
982         (minus:SI (match_operand:SI 1 "const_int_operand" "")
983                   (match_operand:SI 2 "arm_general_register_operand" "")))]
984   "TARGET_ARM
985    && !const_ok_for_arm (INTVAL (operands[1]))
986    && const_ok_for_arm (~INTVAL (operands[1]))"
987   [(set (match_dup 3) (match_dup 1))
988    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
989   ""
990 )
991
992 (define_insn "*subsi3_compare0"
993   [(set (reg:CC_NOOV CC_REGNUM)
994         (compare:CC_NOOV
995          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
996                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
997          (const_int 0)))
998    (set (match_operand:SI 0 "s_register_operand" "=r,r")
999         (minus:SI (match_dup 1) (match_dup 2)))]
1000   "TARGET_ARM"
1001   "@
1002    sub%?s\\t%0, %1, %2
1003    rsb%?s\\t%0, %2, %1"
1004   [(set_attr "conds" "set")]
1005 )
1006
1007 (define_insn "decscc"
1008   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1009         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1010                   (match_operator:SI 2 "arm_comparison_operator"
1011                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1012   "TARGET_ARM"
1013   "@
1014    sub%d2\\t%0, %1, #1
1015    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1016   [(set_attr "conds" "use")
1017    (set_attr "length" "*,8")]
1018 )
1019
1020 (define_expand "subsf3"
1021   [(set (match_operand:SF           0 "s_register_operand" "")
1022         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1023                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1024   "TARGET_ARM && TARGET_HARD_FLOAT"
1025   "
1026   if (TARGET_MAVERICK)
1027     {
1028       if (!cirrus_fp_register (operands[1], SFmode))
1029         operands[1] = force_reg (SFmode, operands[1]);
1030       if (!cirrus_fp_register (operands[2], SFmode))
1031         operands[2] = force_reg (SFmode, operands[2]);
1032     }
1033 ")
1034
1035 (define_expand "subdf3"
1036   [(set (match_operand:DF           0 "s_register_operand" "")
1037         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1038                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1039   "TARGET_ARM && TARGET_HARD_FLOAT"
1040   "
1041   if (TARGET_MAVERICK)
1042     {
1043        if (!cirrus_fp_register (operands[1], DFmode))
1044          operands[1] = force_reg (DFmode, operands[1]);
1045        if (!cirrus_fp_register (operands[2], DFmode))
1046          operands[2] = force_reg (DFmode, operands[2]);
1047     }
1048 ")
1049
1050 \f
1051 ;; Multiplication insns
1052
1053 (define_expand "mulsi3"
1054   [(set (match_operand:SI          0 "s_register_operand" "")
1055         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1056                  (match_operand:SI 1 "s_register_operand" "")))]
1057   "TARGET_EITHER"
1058   ""
1059 )
1060
1061 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1062 (define_insn "*arm_mulsi3"
1063   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1064         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1065                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1066   "TARGET_ARM"
1067   "mul%?\\t%0, %2, %1"
1068   [(set_attr "insn" "mul")
1069    (set_attr "predicable" "yes")]
1070 )
1071
1072 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1073 ; 1 and 2; are the same, because reload will make operand 0 match 
1074 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1075 ; this by adding another alternative to match this case, and then `reload' 
1076 ; it ourselves.  This alternative must come first.
1077 (define_insn "*thumb_mulsi3"
1078   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1079         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1080                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1081   "TARGET_THUMB"
1082   "*
1083   if (which_alternative < 2)
1084     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1085   else
1086     return \"mul\\t%0, %0, %2\";
1087   "
1088   [(set_attr "length" "4,4,2")
1089    (set_attr "insn" "mul")]
1090 )
1091
1092 (define_insn "*mulsi3_compare0"
1093   [(set (reg:CC_NOOV CC_REGNUM)
1094         (compare:CC_NOOV (mult:SI
1095                           (match_operand:SI 2 "s_register_operand" "r,r")
1096                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1097                          (const_int 0)))
1098    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1099         (mult:SI (match_dup 2) (match_dup 1)))]
1100   "TARGET_ARM && !arm_arch_xscale"
1101   "mul%?s\\t%0, %2, %1"
1102   [(set_attr "conds" "set")
1103    (set_attr "insn" "muls")]
1104 )
1105
1106 (define_insn "*mulsi_compare0_scratch"
1107   [(set (reg:CC_NOOV CC_REGNUM)
1108         (compare:CC_NOOV (mult:SI
1109                           (match_operand:SI 2 "s_register_operand" "r,r")
1110                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1111                          (const_int 0)))
1112    (clobber (match_scratch:SI 0 "=&r,&r"))]
1113   "TARGET_ARM && !arm_arch_xscale"
1114   "mul%?s\\t%0, %2, %1"
1115   [(set_attr "conds" "set")
1116    (set_attr "insn" "muls")]
1117 )
1118
1119 ;; Unnamed templates to match MLA instruction.
1120
1121 (define_insn "*mulsi3addsi"
1122   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1123         (plus:SI
1124           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1125                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1126           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1127   "TARGET_ARM"
1128   "mla%?\\t%0, %2, %1, %3"
1129   [(set_attr "insn" "mla")
1130    (set_attr "predicable" "yes")]
1131 )
1132
1133 (define_insn "*mulsi3addsi_compare0"
1134   [(set (reg:CC_NOOV CC_REGNUM)
1135         (compare:CC_NOOV
1136          (plus:SI (mult:SI
1137                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1138                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1139                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1140          (const_int 0)))
1141    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1142         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1143                  (match_dup 3)))]
1144   "TARGET_ARM && !arm_arch_xscale"
1145   "mla%?s\\t%0, %2, %1, %3"
1146   [(set_attr "conds" "set")
1147    (set_attr "insn" "mlas")]
1148 )
1149
1150 (define_insn "*mulsi3addsi_compare0_scratch"
1151   [(set (reg:CC_NOOV CC_REGNUM)
1152         (compare:CC_NOOV
1153          (plus:SI (mult:SI
1154                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1155                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1156                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1157          (const_int 0)))
1158    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1159   "TARGET_ARM && !arm_arch_xscale"
1160   "mla%?s\\t%0, %2, %1, %3"
1161   [(set_attr "conds" "set")
1162    (set_attr "insn" "mlas")]
1163 )
1164
1165 ;; Unnamed template to match long long multiply-accumulate (smlal)
1166
1167 (define_insn "*mulsidi3adddi"
1168   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1169         (plus:DI
1170          (mult:DI
1171           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1172           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1173          (match_operand:DI 1 "s_register_operand" "0")))]
1174   "TARGET_ARM && arm_arch3m"
1175   "smlal%?\\t%Q0, %R0, %3, %2"
1176   [(set_attr "insn" "smlal")
1177    (set_attr "predicable" "yes")]
1178 )
1179
1180 (define_insn "mulsidi3"
1181   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1182         (mult:DI
1183          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1184          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1185   "TARGET_ARM && arm_arch3m"
1186   "smull%?\\t%Q0, %R0, %1, %2"
1187   [(set_attr "insn" "smull")
1188    (set_attr "predicable" "yes")]
1189 )
1190
1191 (define_insn "umulsidi3"
1192   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1193         (mult:DI
1194          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196   "TARGET_ARM && arm_arch3m"
1197   "umull%?\\t%Q0, %R0, %1, %2"
1198   [(set_attr "insn" "umull")
1199    (set_attr "predicable" "yes")]
1200 )
1201
1202 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1203
1204 (define_insn "*umulsidi3adddi"
1205   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1206         (plus:DI
1207          (mult:DI
1208           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1209           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1210          (match_operand:DI 1 "s_register_operand" "0")))]
1211   "TARGET_ARM && arm_arch3m"
1212   "umlal%?\\t%Q0, %R0, %3, %2"
1213   [(set_attr "insn" "umlal")
1214    (set_attr "predicable" "yes")]
1215 )
1216
1217 (define_insn "smulsi3_highpart"
1218   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1219         (truncate:SI
1220          (lshiftrt:DI
1221           (mult:DI
1222            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1223            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1224           (const_int 32))))
1225    (clobber (match_scratch:SI 3 "=&r,&r"))]
1226   "TARGET_ARM && arm_arch3m"
1227   "smull%?\\t%3, %0, %2, %1"
1228   [(set_attr "insn" "smull")
1229    (set_attr "predicable" "yes")]
1230 )
1231
1232 (define_insn "umulsi3_highpart"
1233   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1234         (truncate:SI
1235          (lshiftrt:DI
1236           (mult:DI
1237            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1238            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1239           (const_int 32))))
1240    (clobber (match_scratch:SI 3 "=&r,&r"))]
1241   "TARGET_ARM && arm_arch3m"
1242   "umull%?\\t%3, %0, %2, %1"
1243   [(set_attr "insn" "umull")
1244    (set_attr "predicable" "yes")]
1245 )
1246
1247 (define_insn "mulhisi3"
1248   [(set (match_operand:SI 0 "s_register_operand" "=r")
1249         (mult:SI (sign_extend:SI
1250                   (match_operand:HI 1 "s_register_operand" "%r"))
1251                  (sign_extend:SI
1252                   (match_operand:HI 2 "s_register_operand" "r"))))]
1253   "TARGET_ARM && arm_arch5e"
1254   "smulbb%?\\t%0, %1, %2"
1255   [(set_attr "insn" "smulxy")
1256    (set_attr "predicable" "yes")]
1257 )
1258
1259 (define_insn "*mulhisi3tb"
1260   [(set (match_operand:SI 0 "s_register_operand" "=r")
1261         (mult:SI (ashiftrt:SI
1262                   (match_operand:SI 1 "s_register_operand" "r")
1263                   (const_int 16))
1264                  (sign_extend:SI
1265                   (match_operand:HI 2 "s_register_operand" "r"))))]
1266   "TARGET_ARM && arm_arch5e"
1267   "smultb%?\\t%0, %1, %2"
1268   [(set_attr "insn" "smulxy")
1269    (set_attr "predicable" "yes")]
1270 )
1271
1272 (define_insn "*mulhisi3bt"
1273   [(set (match_operand:SI 0 "s_register_operand" "=r")
1274         (mult:SI (sign_extend:SI
1275                   (match_operand:HI 1 "s_register_operand" "r"))
1276                  (ashiftrt:SI
1277                   (match_operand:SI 2 "s_register_operand" "r")
1278                   (const_int 16))))]
1279   "TARGET_ARM && arm_arch5e"
1280   "smulbt%?\\t%0, %1, %2"
1281   [(set_attr "insn" "smulxy")
1282    (set_attr "predicable" "yes")]
1283 )
1284
1285 (define_insn "*mulhisi3tt"
1286   [(set (match_operand:SI 0 "s_register_operand" "=r")
1287         (mult:SI (ashiftrt:SI
1288                   (match_operand:SI 1 "s_register_operand" "r")
1289                   (const_int 16))
1290                  (ashiftrt:SI
1291                   (match_operand:SI 2 "s_register_operand" "r")
1292                   (const_int 16))))]
1293   "TARGET_ARM && arm_arch5e"
1294   "smultt%?\\t%0, %1, %2"
1295   [(set_attr "insn" "smulxy")
1296    (set_attr "predicable" "yes")]
1297 )
1298
1299 (define_insn "*mulhisi3addsi"
1300   [(set (match_operand:SI 0 "s_register_operand" "=r")
1301         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1302                  (mult:SI (sign_extend:SI
1303                            (match_operand:HI 2 "s_register_operand" "%r"))
1304                           (sign_extend:SI
1305                            (match_operand:HI 3 "s_register_operand" "r")))))]
1306   "TARGET_ARM && arm_arch5e"
1307   "smlabb%?\\t%0, %2, %3, %1"
1308   [(set_attr "insn" "smlaxy")
1309    (set_attr "predicable" "yes")]
1310 )
1311
1312 (define_insn "*mulhidi3adddi"
1313   [(set (match_operand:DI 0 "s_register_operand" "=r")
1314         (plus:DI
1315           (match_operand:DI 1 "s_register_operand" "0")
1316           (mult:DI (sign_extend:DI
1317                     (match_operand:HI 2 "s_register_operand" "%r"))
1318                    (sign_extend:DI
1319                     (match_operand:HI 3 "s_register_operand" "r")))))]
1320   "TARGET_ARM && arm_arch5e"
1321   "smlalbb%?\\t%Q0, %R0, %2, %3"
1322   [(set_attr "insn" "smlalxy")
1323    (set_attr "predicable" "yes")])
1324
1325 (define_expand "mulsf3"
1326   [(set (match_operand:SF          0 "s_register_operand" "")
1327         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1328                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1329   "TARGET_ARM && TARGET_HARD_FLOAT"
1330   "
1331   if (TARGET_MAVERICK
1332       && !cirrus_fp_register (operands[2], SFmode))
1333     operands[2] = force_reg (SFmode, operands[2]);
1334 ")
1335
1336 (define_expand "muldf3"
1337   [(set (match_operand:DF          0 "s_register_operand" "")
1338         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1339                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1340   "TARGET_ARM && TARGET_HARD_FLOAT"
1341   "
1342   if (TARGET_MAVERICK
1343       && !cirrus_fp_register (operands[2], DFmode))
1344     operands[2] = force_reg (DFmode, operands[2]);
1345 ")
1346 \f
1347 ;; Division insns
1348
1349 (define_expand "divsf3"
1350   [(set (match_operand:SF 0 "s_register_operand" "")
1351         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1352                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1353   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1354   "")
1355
1356 (define_expand "divdf3"
1357   [(set (match_operand:DF 0 "s_register_operand" "")
1358         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1359                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1360   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1361   "")
1362 \f
1363 ;; Modulo insns
1364
1365 (define_expand "modsf3"
1366   [(set (match_operand:SF 0 "s_register_operand" "")
1367         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1368                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1369   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1370   "")
1371
1372 (define_expand "moddf3"
1373   [(set (match_operand:DF 0 "s_register_operand" "")
1374         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1375                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1376   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1377   "")
1378 \f
1379 ;; Boolean and,ior,xor insns
1380
1381 ;; Split up double word logical operations
1382
1383 ;; Split up simple DImode logical operations.  Simply perform the logical
1384 ;; operation on the upper and lower halves of the registers.
1385 (define_split
1386   [(set (match_operand:DI 0 "s_register_operand" "")
1387         (match_operator:DI 6 "logical_binary_operator"
1388           [(match_operand:DI 1 "s_register_operand" "")
1389            (match_operand:DI 2 "s_register_operand" "")]))]
1390   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1391   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1392    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1393   "
1394   {
1395     operands[3] = gen_highpart (SImode, operands[0]);
1396     operands[0] = gen_lowpart (SImode, operands[0]);
1397     operands[4] = gen_highpart (SImode, operands[1]);
1398     operands[1] = gen_lowpart (SImode, operands[1]);
1399     operands[5] = gen_highpart (SImode, operands[2]);
1400     operands[2] = gen_lowpart (SImode, operands[2]);
1401   }"
1402 )
1403
1404 (define_split
1405   [(set (match_operand:DI 0 "s_register_operand" "")
1406         (match_operator:DI 6 "logical_binary_operator"
1407           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1408            (match_operand:DI 1 "s_register_operand" "")]))]
1409   "TARGET_ARM && reload_completed"
1410   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1411    (set (match_dup 3) (match_op_dup:SI 6
1412                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1413                          (match_dup 4)]))]
1414   "
1415   {
1416     operands[3] = gen_highpart (SImode, operands[0]);
1417     operands[0] = gen_lowpart (SImode, operands[0]);
1418     operands[4] = gen_highpart (SImode, operands[1]);
1419     operands[1] = gen_lowpart (SImode, operands[1]);
1420     operands[5] = gen_highpart (SImode, operands[2]);
1421     operands[2] = gen_lowpart (SImode, operands[2]);
1422   }"
1423 )
1424
1425 ;; The zero extend of operand 2 means we can just copy the high part of
1426 ;; operand1 into operand0.
1427 (define_split
1428   [(set (match_operand:DI 0 "s_register_operand" "")
1429         (ior:DI
1430           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1431           (match_operand:DI 1 "s_register_operand" "")))]
1432   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1433   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1434    (set (match_dup 3) (match_dup 4))]
1435   "
1436   {
1437     operands[4] = gen_highpart (SImode, operands[1]);
1438     operands[3] = gen_highpart (SImode, operands[0]);
1439     operands[0] = gen_lowpart (SImode, operands[0]);
1440     operands[1] = gen_lowpart (SImode, operands[1]);
1441   }"
1442 )
1443
1444 ;; The zero extend of operand 2 means we can just copy the high part of
1445 ;; operand1 into operand0.
1446 (define_split
1447   [(set (match_operand:DI 0 "s_register_operand" "")
1448         (xor:DI
1449           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1450           (match_operand:DI 1 "s_register_operand" "")))]
1451   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1452   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1453    (set (match_dup 3) (match_dup 4))]
1454   "
1455   {
1456     operands[4] = gen_highpart (SImode, operands[1]);
1457     operands[3] = gen_highpart (SImode, operands[0]);
1458     operands[0] = gen_lowpart (SImode, operands[0]);
1459     operands[1] = gen_lowpart (SImode, operands[1]);
1460   }"
1461 )
1462
1463 (define_insn "anddi3"
1464   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1465         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1466                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1467   "TARGET_ARM && ! TARGET_IWMMXT"
1468   "#"
1469   [(set_attr "length" "8")]
1470 )
1471
1472 (define_insn_and_split "*anddi_zesidi_di"
1473   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1474         (and:DI (zero_extend:DI
1475                  (match_operand:SI 2 "s_register_operand" "r,r"))
1476                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1477   "TARGET_ARM"
1478   "#"
1479   "TARGET_ARM && reload_completed"
1480   ; The zero extend of operand 2 clears the high word of the output
1481   ; operand.
1482   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1483    (set (match_dup 3) (const_int 0))]
1484   "
1485   {
1486     operands[3] = gen_highpart (SImode, operands[0]);
1487     operands[0] = gen_lowpart (SImode, operands[0]);
1488     operands[1] = gen_lowpart (SImode, operands[1]);
1489   }"
1490   [(set_attr "length" "8")]
1491 )
1492
1493 (define_insn "*anddi_sesdi_di"
1494   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1495         (and:DI (sign_extend:DI
1496                  (match_operand:SI 2 "s_register_operand" "r,r"))
1497                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1498   "TARGET_ARM"
1499   "#"
1500   [(set_attr "length" "8")]
1501 )
1502
1503 (define_expand "andsi3"
1504   [(set (match_operand:SI         0 "s_register_operand" "")
1505         (and:SI (match_operand:SI 1 "s_register_operand" "")
1506                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1507   "TARGET_EITHER"
1508   "
1509   if (TARGET_ARM)
1510     {
1511       if (GET_CODE (operands[2]) == CONST_INT)
1512         {
1513           arm_split_constant (AND, SImode, NULL_RTX,
1514                               INTVAL (operands[2]), operands[0],
1515                               operands[1], optimize && !no_new_pseudos);
1516
1517           DONE;
1518         }
1519     }
1520   else /* TARGET_THUMB */
1521     {
1522       if (GET_CODE (operands[2]) != CONST_INT)
1523         operands[2] = force_reg (SImode, operands[2]);
1524       else
1525         {
1526           int i;
1527           
1528           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1529             {
1530               operands[2] = force_reg (SImode,
1531                                        GEN_INT (~INTVAL (operands[2])));
1532               
1533               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1534               
1535               DONE;
1536             }
1537
1538           for (i = 9; i <= 31; i++)
1539             {
1540               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1541                 {
1542                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1543                                         const0_rtx));
1544                   DONE;
1545                 }
1546               else if ((((HOST_WIDE_INT) 1) << i) - 1
1547                        == ~INTVAL (operands[2]))
1548                 {
1549                   rtx shift = GEN_INT (i);
1550                   rtx reg = gen_reg_rtx (SImode);
1551                 
1552                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1553                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1554                   
1555                   DONE;
1556                 }
1557             }
1558
1559           operands[2] = force_reg (SImode, operands[2]);
1560         }
1561     }
1562   "
1563 )
1564
1565 (define_insn_and_split "*arm_andsi3_insn"
1566   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1567         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1568                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1569   "TARGET_ARM"
1570   "@
1571    and%?\\t%0, %1, %2
1572    bic%?\\t%0, %1, #%B2
1573    #"
1574   "TARGET_ARM
1575    && GET_CODE (operands[2]) == CONST_INT
1576    && !(const_ok_for_arm (INTVAL (operands[2]))
1577         || const_ok_for_arm (~INTVAL (operands[2])))"
1578   [(clobber (const_int 0))]
1579   "
1580   arm_split_constant  (AND, SImode, curr_insn, 
1581                        INTVAL (operands[2]), operands[0], operands[1], 0);
1582   DONE;
1583   "
1584   [(set_attr "length" "4,4,16")
1585    (set_attr "predicable" "yes")]
1586 )
1587
1588 (define_insn "*thumb_andsi3_insn"
1589   [(set (match_operand:SI         0 "register_operand" "=l")
1590         (and:SI (match_operand:SI 1 "register_operand" "%0")
1591                 (match_operand:SI 2 "register_operand" "l")))]
1592   "TARGET_THUMB"
1593   "and\\t%0, %0, %2"
1594   [(set_attr "length" "2")]
1595 )
1596
1597 (define_insn "*andsi3_compare0"
1598   [(set (reg:CC_NOOV CC_REGNUM)
1599         (compare:CC_NOOV
1600          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1601                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1602          (const_int 0)))
1603    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1604         (and:SI (match_dup 1) (match_dup 2)))]
1605   "TARGET_ARM"
1606   "@
1607    and%?s\\t%0, %1, %2
1608    bic%?s\\t%0, %1, #%B2"
1609   [(set_attr "conds" "set")]
1610 )
1611
1612 (define_insn "*andsi3_compare0_scratch"
1613   [(set (reg:CC_NOOV CC_REGNUM)
1614         (compare:CC_NOOV
1615          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1616                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1617          (const_int 0)))
1618    (clobber (match_scratch:SI 2 "=X,r"))]
1619   "TARGET_ARM"
1620   "@
1621    tst%?\\t%0, %1
1622    bic%?s\\t%2, %0, #%B1"
1623   [(set_attr "conds" "set")]
1624 )
1625
1626 (define_insn "*zeroextractsi_compare0_scratch"
1627   [(set (reg:CC_NOOV CC_REGNUM)
1628         (compare:CC_NOOV (zero_extract:SI
1629                           (match_operand:SI 0 "s_register_operand" "r")
1630                           (match_operand 1 "const_int_operand" "n")
1631                           (match_operand 2 "const_int_operand" "n"))
1632                          (const_int 0)))]
1633   "TARGET_ARM
1634   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1635       && INTVAL (operands[1]) > 0 
1636       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1637       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1638   "*
1639   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1640                          << INTVAL (operands[2]));
1641   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1642   return \"\";
1643   "
1644   [(set_attr "conds" "set")]
1645 )
1646
1647 (define_insn_and_split "*ne_zeroextractsi"
1648   [(set (match_operand:SI 0 "s_register_operand" "=r")
1649         (ne:SI (zero_extract:SI
1650                 (match_operand:SI 1 "s_register_operand" "r")
1651                 (match_operand:SI 2 "const_int_operand" "n")
1652                 (match_operand:SI 3 "const_int_operand" "n"))
1653                (const_int 0)))
1654    (clobber (reg:CC CC_REGNUM))]
1655   "TARGET_ARM
1656    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1657        && INTVAL (operands[2]) > 0 
1658        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1659        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1660   "#"
1661   "TARGET_ARM
1662    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1663        && INTVAL (operands[2]) > 0 
1664        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1665        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1666   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1667                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1668                                     (const_int 0)))
1669               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1670    (set (match_dup 0)
1671         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1672                          (match_dup 0) (const_int 1)))]
1673   "
1674   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1675                          << INTVAL (operands[3])); 
1676   "
1677   [(set_attr "conds" "clob")
1678    (set_attr "length" "8")]
1679 )
1680
1681 (define_insn_and_split "*ne_zeroextractsi_shifted"
1682   [(set (match_operand:SI 0 "s_register_operand" "=r")
1683         (ne:SI (zero_extract:SI
1684                 (match_operand:SI 1 "s_register_operand" "r")
1685                 (match_operand:SI 2 "const_int_operand" "n")
1686                 (const_int 0))
1687                (const_int 0)))
1688    (clobber (reg:CC CC_REGNUM))]
1689   "TARGET_ARM"
1690   "#"
1691   "TARGET_ARM"
1692   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1693                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1694                                     (const_int 0)))
1695               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1696    (set (match_dup 0)
1697         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1698                          (match_dup 0) (const_int 1)))]
1699   "
1700   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1701   "
1702   [(set_attr "conds" "clob")
1703    (set_attr "length" "8")]
1704 )
1705
1706 (define_insn_and_split "*ite_ne_zeroextractsi"
1707   [(set (match_operand:SI 0 "s_register_operand" "=r")
1708         (if_then_else:SI (ne (zero_extract:SI
1709                               (match_operand:SI 1 "s_register_operand" "r")
1710                               (match_operand:SI 2 "const_int_operand" "n")
1711                               (match_operand:SI 3 "const_int_operand" "n"))
1712                              (const_int 0))
1713                          (match_operand:SI 4 "arm_not_operand" "rIK")
1714                          (const_int 0)))
1715    (clobber (reg:CC CC_REGNUM))]
1716   "TARGET_ARM
1717    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1718        && INTVAL (operands[2]) > 0 
1719        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1720        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1721    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1722   "#"
1723   "TARGET_ARM
1724    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1725        && INTVAL (operands[2]) > 0 
1726        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1727        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1728    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1729   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1730                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1731                                     (const_int 0)))
1732               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1733    (set (match_dup 0)
1734         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1735                          (match_dup 0) (match_dup 4)))]
1736   "
1737   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1738                          << INTVAL (operands[3])); 
1739   "
1740   [(set_attr "conds" "clob")
1741    (set_attr "length" "8")]
1742 )
1743
1744 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1745   [(set (match_operand:SI 0 "s_register_operand" "=r")
1746         (if_then_else:SI (ne (zero_extract:SI
1747                               (match_operand:SI 1 "s_register_operand" "r")
1748                               (match_operand:SI 2 "const_int_operand" "n")
1749                               (const_int 0))
1750                              (const_int 0))
1751                          (match_operand:SI 3 "arm_not_operand" "rIK")
1752                          (const_int 0)))
1753    (clobber (reg:CC CC_REGNUM))]
1754   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1755   "#"
1756   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1757   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1758                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1759                                     (const_int 0)))
1760               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1761    (set (match_dup 0)
1762         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1763                          (match_dup 0) (match_dup 3)))]
1764   "
1765   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1766   "
1767   [(set_attr "conds" "clob")
1768    (set_attr "length" "8")]
1769 )
1770
1771 (define_split
1772   [(set (match_operand:SI 0 "s_register_operand" "")
1773         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1774                          (match_operand:SI 2 "const_int_operand" "")
1775                          (match_operand:SI 3 "const_int_operand" "")))
1776    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1777   "TARGET_THUMB"
1778   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1779    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1780   "{
1781      HOST_WIDE_INT temp = INTVAL (operands[2]);
1782
1783      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1784      operands[3] = GEN_INT (32 - temp);
1785    }"
1786 )
1787
1788 (define_split
1789   [(set (match_operand:SI 0 "s_register_operand" "")
1790         (match_operator:SI 1 "shiftable_operator"
1791          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1792                            (match_operand:SI 3 "const_int_operand" "")
1793                            (match_operand:SI 4 "const_int_operand" ""))
1794           (match_operand:SI 5 "s_register_operand" "")]))
1795    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1796   "TARGET_ARM"
1797   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1798    (set (match_dup 0)
1799         (match_op_dup 1
1800          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1801           (match_dup 5)]))]
1802   "{
1803      HOST_WIDE_INT temp = INTVAL (operands[3]);
1804
1805      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1806      operands[4] = GEN_INT (32 - temp);
1807    }"
1808 )
1809   
1810 (define_split
1811   [(set (match_operand:SI 0 "s_register_operand" "")
1812         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1813                          (match_operand:SI 2 "const_int_operand" "")
1814                          (match_operand:SI 3 "const_int_operand" "")))]
1815   "TARGET_THUMB"
1816   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1817    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1818   "{
1819      HOST_WIDE_INT temp = INTVAL (operands[2]);
1820
1821      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1822      operands[3] = GEN_INT (32 - temp);
1823    }"
1824 )
1825
1826 (define_split
1827   [(set (match_operand:SI 0 "s_register_operand" "")
1828         (match_operator:SI 1 "shiftable_operator"
1829          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1830                            (match_operand:SI 3 "const_int_operand" "")
1831                            (match_operand:SI 4 "const_int_operand" ""))
1832           (match_operand:SI 5 "s_register_operand" "")]))
1833    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1834   "TARGET_ARM"
1835   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1836    (set (match_dup 0)
1837         (match_op_dup 1
1838          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1839           (match_dup 5)]))]
1840   "{
1841      HOST_WIDE_INT temp = INTVAL (operands[3]);
1842
1843      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1844      operands[4] = GEN_INT (32 - temp);
1845    }"
1846 )
1847   
1848 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1849 ;;; represented by the bitfield, then this will produce incorrect results.
1850 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1851 ;;; which have a real bit-field insert instruction, the truncation happens
1852 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1853 ;;; bit-field insert instruction, we would have to emit code here to truncate
1854 ;;; the value before we insert.  This loses some of the advantage of having
1855 ;;; this insv pattern, so this pattern needs to be reevalutated.
1856
1857 (define_expand "insv"
1858   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1859                          (match_operand:SI 1 "general_operand" "")
1860                          (match_operand:SI 2 "general_operand" ""))
1861         (match_operand:SI 3 "reg_or_int_operand" ""))]
1862   "TARGET_ARM"
1863   "
1864   {
1865     int start_bit = INTVAL (operands[2]);
1866     int width = INTVAL (operands[1]);
1867     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1868     rtx target, subtarget;
1869
1870     target = operands[0];
1871     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1872        subreg as the final target.  */
1873     if (GET_CODE (target) == SUBREG)
1874       {
1875         subtarget = gen_reg_rtx (SImode);
1876         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1877             < GET_MODE_SIZE (SImode))
1878           target = SUBREG_REG (target);
1879       }
1880     else
1881       subtarget = target;    
1882
1883     if (GET_CODE (operands[3]) == CONST_INT)
1884       {
1885         /* Since we are inserting a known constant, we may be able to
1886            reduce the number of bits that we have to clear so that
1887            the mask becomes simple.  */
1888         /* ??? This code does not check to see if the new mask is actually
1889            simpler.  It may not be.  */
1890         rtx op1 = gen_reg_rtx (SImode);
1891         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1892            start of this pattern.  */
1893         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1894         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1895
1896         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1897         emit_insn (gen_iorsi3 (subtarget, op1,
1898                                GEN_INT (op3_value << start_bit)));
1899       }
1900     else if (start_bit == 0
1901              && !(const_ok_for_arm (mask)
1902                   || const_ok_for_arm (~mask)))
1903       {
1904         /* A Trick, since we are setting the bottom bits in the word,
1905            we can shift operand[3] up, operand[0] down, OR them together
1906            and rotate the result back again.  This takes 3 insns, and
1907            the third might be mergeable into another op.  */
1908         /* The shift up copes with the possibility that operand[3] is
1909            wider than the bitfield.  */
1910         rtx op0 = gen_reg_rtx (SImode);
1911         rtx op1 = gen_reg_rtx (SImode);
1912
1913         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1914         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1915         emit_insn (gen_iorsi3  (op1, op1, op0));
1916         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1917       }
1918     else if ((width + start_bit == 32)
1919              && !(const_ok_for_arm (mask)
1920                   || const_ok_for_arm (~mask)))
1921       {
1922         /* Similar trick, but slightly less efficient.  */
1923
1924         rtx op0 = gen_reg_rtx (SImode);
1925         rtx op1 = gen_reg_rtx (SImode);
1926
1927         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1928         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1929         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1930         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1931       }
1932     else
1933       {
1934         rtx op0 = GEN_INT (mask);
1935         rtx op1 = gen_reg_rtx (SImode);
1936         rtx op2 = gen_reg_rtx (SImode);
1937
1938         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1939           {
1940             rtx tmp = gen_reg_rtx (SImode);
1941
1942             emit_insn (gen_movsi (tmp, op0));
1943             op0 = tmp;
1944           }
1945
1946         /* Mask out any bits in operand[3] that are not needed.  */
1947            emit_insn (gen_andsi3 (op1, operands[3], op0));
1948
1949         if (GET_CODE (op0) == CONST_INT
1950             && (const_ok_for_arm (mask << start_bit)
1951                 || const_ok_for_arm (~(mask << start_bit))))
1952           {
1953             op0 = GEN_INT (~(mask << start_bit));
1954             emit_insn (gen_andsi3 (op2, operands[0], op0));
1955           }
1956         else
1957           {
1958             if (GET_CODE (op0) == CONST_INT)
1959               {
1960                 rtx tmp = gen_reg_rtx (SImode);
1961
1962                 emit_insn (gen_movsi (tmp, op0));
1963                 op0 = tmp;
1964               }
1965
1966             if (start_bit != 0)
1967               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1968             
1969             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1970           }
1971
1972         if (start_bit != 0)
1973           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1974
1975         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1976       }
1977
1978     if (subtarget != target)
1979       {
1980         /* If TARGET is still a SUBREG, then it must be wider than a word,
1981            so we must be careful only to set the subword we were asked to.  */
1982         if (GET_CODE (target) == SUBREG)
1983           emit_move_insn (target, subtarget);
1984         else
1985           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1986       }
1987
1988     DONE;
1989   }"
1990 )
1991
1992 ; constants for op 2 will never be given to these patterns.
1993 (define_insn_and_split "*anddi_notdi_di"
1994   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1995         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1996                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1997   "TARGET_ARM"
1998   "#"
1999   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2000   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2001    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2002   "
2003   {
2004     operands[3] = gen_highpart (SImode, operands[0]);
2005     operands[0] = gen_lowpart (SImode, operands[0]);
2006     operands[4] = gen_highpart (SImode, operands[1]);
2007     operands[1] = gen_lowpart (SImode, operands[1]);
2008     operands[5] = gen_highpart (SImode, operands[2]);
2009     operands[2] = gen_lowpart (SImode, operands[2]);
2010   }"
2011   [(set_attr "length" "8")
2012    (set_attr "predicable" "yes")]
2013 )
2014   
2015 (define_insn_and_split "*anddi_notzesidi_di"
2016   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2017         (and:DI (not:DI (zero_extend:DI
2018                          (match_operand:SI 2 "s_register_operand" "r,r")))
2019                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2020   "TARGET_ARM"
2021   "@
2022    bic%?\\t%Q0, %Q1, %2
2023    #"
2024   ; (not (zero_extend ...)) allows us to just copy the high word from
2025   ; operand1 to operand0.
2026   "TARGET_ARM
2027    && reload_completed
2028    && operands[0] != operands[1]"
2029   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2030    (set (match_dup 3) (match_dup 4))]
2031   "
2032   {
2033     operands[3] = gen_highpart (SImode, operands[0]);
2034     operands[0] = gen_lowpart (SImode, operands[0]);
2035     operands[4] = gen_highpart (SImode, operands[1]);
2036     operands[1] = gen_lowpart (SImode, operands[1]);
2037   }"
2038   [(set_attr "length" "4,8")
2039    (set_attr "predicable" "yes")]
2040 )
2041   
2042 (define_insn_and_split "*anddi_notsesidi_di"
2043   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2044         (and:DI (not:DI (sign_extend:DI
2045                          (match_operand:SI 2 "s_register_operand" "r,r")))
2046                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2047   "TARGET_ARM"
2048   "#"
2049   "TARGET_ARM && reload_completed"
2050   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2051    (set (match_dup 3) (and:SI (not:SI
2052                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2053                                (match_dup 4)))]
2054   "
2055   {
2056     operands[3] = gen_highpart (SImode, operands[0]);
2057     operands[0] = gen_lowpart (SImode, operands[0]);
2058     operands[4] = gen_highpart (SImode, operands[1]);
2059     operands[1] = gen_lowpart (SImode, operands[1]);
2060   }"
2061   [(set_attr "length" "8")
2062    (set_attr "predicable" "yes")]
2063 )
2064   
2065 (define_insn "andsi_notsi_si"
2066   [(set (match_operand:SI 0 "s_register_operand" "=r")
2067         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2068                 (match_operand:SI 1 "s_register_operand" "r")))]
2069   "TARGET_ARM"
2070   "bic%?\\t%0, %1, %2"
2071   [(set_attr "predicable" "yes")]
2072 )
2073
2074 (define_insn "bicsi3"
2075   [(set (match_operand:SI                 0 "register_operand" "=l")
2076         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2077                 (match_operand:SI         2 "register_operand" "0")))]
2078   "TARGET_THUMB"
2079   "bic\\t%0, %0, %1"
2080   [(set_attr "length" "2")]
2081 )
2082
2083 (define_insn "andsi_not_shiftsi_si"
2084   [(set (match_operand:SI 0 "s_register_operand" "=r")
2085         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2086                          [(match_operand:SI 2 "s_register_operand" "r")
2087                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2088                 (match_operand:SI 1 "s_register_operand" "r")))]
2089   "TARGET_ARM"
2090   "bic%?\\t%0, %1, %2%S4"
2091   [(set_attr "predicable" "yes")
2092    (set_attr "shift" "2")
2093    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2094                       (const_string "alu_shift")
2095                       (const_string "alu_shift_reg")))]
2096 )
2097
2098 (define_insn "*andsi_notsi_si_compare0"
2099   [(set (reg:CC_NOOV CC_REGNUM)
2100         (compare:CC_NOOV
2101          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2102                  (match_operand:SI 1 "s_register_operand" "r"))
2103          (const_int 0)))
2104    (set (match_operand:SI 0 "s_register_operand" "=r")
2105         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2106   "TARGET_ARM"
2107   "bic%?s\\t%0, %1, %2"
2108   [(set_attr "conds" "set")]
2109 )
2110
2111 (define_insn "*andsi_notsi_si_compare0_scratch"
2112   [(set (reg:CC_NOOV CC_REGNUM)
2113         (compare:CC_NOOV
2114          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2115                  (match_operand:SI 1 "s_register_operand" "r"))
2116          (const_int 0)))
2117    (clobber (match_scratch:SI 0 "=r"))]
2118   "TARGET_ARM"
2119   "bic%?s\\t%0, %1, %2"
2120   [(set_attr "conds" "set")]
2121 )
2122
2123 (define_insn "iordi3"
2124   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2125         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2126                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2127   "TARGET_ARM && ! TARGET_IWMMXT"
2128   "#"
2129   [(set_attr "length" "8")
2130    (set_attr "predicable" "yes")]
2131 )
2132
2133 (define_insn "*iordi_zesidi_di"
2134   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2135         (ior:DI (zero_extend:DI
2136                  (match_operand:SI 2 "s_register_operand" "r,r"))
2137                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2138   "TARGET_ARM"
2139   "@
2140    orr%?\\t%Q0, %Q1, %2
2141    #"
2142   [(set_attr "length" "4,8")
2143    (set_attr "predicable" "yes")]
2144 )
2145
2146 (define_insn "*iordi_sesidi_di"
2147   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2148         (ior:DI (sign_extend:DI
2149                  (match_operand:SI 2 "s_register_operand" "r,r"))
2150                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2151   "TARGET_ARM"
2152   "#"
2153   [(set_attr "length" "8")
2154    (set_attr "predicable" "yes")]
2155 )
2156
2157 (define_expand "iorsi3"
2158   [(set (match_operand:SI         0 "s_register_operand" "")
2159         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2160                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2161   "TARGET_EITHER"
2162   "
2163   if (GET_CODE (operands[2]) == CONST_INT)
2164     {
2165       if (TARGET_ARM)
2166         {
2167           arm_split_constant (IOR, SImode, NULL_RTX,
2168                               INTVAL (operands[2]), operands[0], operands[1],
2169                               optimize && !no_new_pseudos);
2170           DONE;
2171         }
2172       else /* TARGET_THUMB */
2173         operands [2] = force_reg (SImode, operands [2]);
2174     }
2175   "
2176 )
2177
2178 (define_insn_and_split "*arm_iorsi3"
2179   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2180         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2181                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2182   "TARGET_ARM"
2183   "@
2184    orr%?\\t%0, %1, %2
2185    #"
2186   "TARGET_ARM
2187    && GET_CODE (operands[2]) == CONST_INT
2188    && !const_ok_for_arm (INTVAL (operands[2]))"
2189   [(clobber (const_int 0))]
2190   "
2191   arm_split_constant (IOR, SImode, curr_insn, 
2192                       INTVAL (operands[2]), operands[0], operands[1], 0);
2193   DONE;
2194   "
2195   [(set_attr "length" "4,16")
2196    (set_attr "predicable" "yes")]
2197 )
2198
2199 (define_insn "*thumb_iorsi3"
2200   [(set (match_operand:SI         0 "register_operand" "=l")
2201         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2202                 (match_operand:SI 2 "register_operand" "l")))]
2203   "TARGET_THUMB"
2204   "orr\\t%0, %0, %2"
2205   [(set_attr "length" "2")]
2206 )
2207
2208 (define_peephole2
2209   [(match_scratch:SI 3 "r")
2210    (set (match_operand:SI 0 "arm_general_register_operand" "")
2211         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2212                 (match_operand:SI 2 "const_int_operand" "")))]
2213   "TARGET_ARM
2214    && !const_ok_for_arm (INTVAL (operands[2]))
2215    && const_ok_for_arm (~INTVAL (operands[2]))"
2216   [(set (match_dup 3) (match_dup 2))
2217    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2218   ""
2219 )
2220
2221 (define_insn "*iorsi3_compare0"
2222   [(set (reg:CC_NOOV CC_REGNUM)
2223         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2224                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2225                          (const_int 0)))
2226    (set (match_operand:SI 0 "s_register_operand" "=r")
2227         (ior:SI (match_dup 1) (match_dup 2)))]
2228   "TARGET_ARM"
2229   "orr%?s\\t%0, %1, %2"
2230   [(set_attr "conds" "set")]
2231 )
2232
2233 (define_insn "*iorsi3_compare0_scratch"
2234   [(set (reg:CC_NOOV CC_REGNUM)
2235         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2237                          (const_int 0)))
2238    (clobber (match_scratch:SI 0 "=r"))]
2239   "TARGET_ARM"
2240   "orr%?s\\t%0, %1, %2"
2241   [(set_attr "conds" "set")]
2242 )
2243
2244 (define_insn "xordi3"
2245   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2246         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2247                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2248   "TARGET_ARM && !TARGET_IWMMXT"
2249   "#"
2250   [(set_attr "length" "8")
2251    (set_attr "predicable" "yes")]
2252 )
2253
2254 (define_insn "*xordi_zesidi_di"
2255   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2256         (xor:DI (zero_extend:DI
2257                  (match_operand:SI 2 "s_register_operand" "r,r"))
2258                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2259   "TARGET_ARM"
2260   "@
2261    eor%?\\t%Q0, %Q1, %2
2262    #"
2263   [(set_attr "length" "4,8")
2264    (set_attr "predicable" "yes")]
2265 )
2266
2267 (define_insn "*xordi_sesidi_di"
2268   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2269         (xor:DI (sign_extend:DI
2270                  (match_operand:SI 2 "s_register_operand" "r,r"))
2271                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2272   "TARGET_ARM"
2273   "#"
2274   [(set_attr "length" "8")
2275    (set_attr "predicable" "yes")]
2276 )
2277
2278 (define_expand "xorsi3"
2279   [(set (match_operand:SI         0 "s_register_operand" "")
2280         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2281                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2282   "TARGET_EITHER"
2283   "if (TARGET_THUMB)
2284      if (GET_CODE (operands[2]) == CONST_INT)
2285        operands[2] = force_reg (SImode, operands[2]);
2286   "
2287 )
2288
2289 (define_insn "*arm_xorsi3"
2290   [(set (match_operand:SI         0 "s_register_operand" "=r")
2291         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2292                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2293   "TARGET_ARM"
2294   "eor%?\\t%0, %1, %2"
2295   [(set_attr "predicable" "yes")]
2296 )
2297
2298 (define_insn "*thumb_xorsi3"
2299   [(set (match_operand:SI         0 "register_operand" "=l")
2300         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2301                 (match_operand:SI 2 "register_operand" "l")))]
2302   "TARGET_THUMB"
2303   "eor\\t%0, %0, %2"
2304   [(set_attr "length" "2")]
2305 )
2306
2307 (define_insn "*xorsi3_compare0"
2308   [(set (reg:CC_NOOV CC_REGNUM)
2309         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2310                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2311                          (const_int 0)))
2312    (set (match_operand:SI 0 "s_register_operand" "=r")
2313         (xor:SI (match_dup 1) (match_dup 2)))]
2314   "TARGET_ARM"
2315   "eor%?s\\t%0, %1, %2"
2316   [(set_attr "conds" "set")]
2317 )
2318
2319 (define_insn "*xorsi3_compare0_scratch"
2320   [(set (reg:CC_NOOV CC_REGNUM)
2321         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2322                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2323                          (const_int 0)))]
2324   "TARGET_ARM"
2325   "teq%?\\t%0, %1"
2326   [(set_attr "conds" "set")]
2327 )
2328
2329 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2330 ; (NOT D) we can sometimes merge the final NOT into one of the following
2331 ; insns.
2332
2333 (define_split
2334   [(set (match_operand:SI 0 "s_register_operand" "")
2335         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2336                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2337                 (match_operand:SI 3 "arm_rhs_operand" "")))
2338    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2339   "TARGET_ARM"
2340   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2341                               (not:SI (match_dup 3))))
2342    (set (match_dup 0) (not:SI (match_dup 4)))]
2343   ""
2344 )
2345
2346 (define_insn "*andsi_iorsi3_notsi"
2347   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2348         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2349                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2350                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2351   "TARGET_ARM"
2352   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2353   [(set_attr "length" "8")
2354    (set_attr "predicable" "yes")]
2355 )
2356
2357 (define_split
2358   [(set (match_operand:SI 0 "s_register_operand" "")
2359         (match_operator:SI 1 "logical_binary_operator"
2360          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2361                            (match_operand:SI 3 "const_int_operand" "")
2362                            (match_operand:SI 4 "const_int_operand" ""))
2363           (match_operator:SI 9 "logical_binary_operator"
2364            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2365                          (match_operand:SI 6 "const_int_operand" ""))
2366             (match_operand:SI 7 "s_register_operand" "")])]))
2367    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2368   "TARGET_ARM
2369    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2370    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2371   [(set (match_dup 8)
2372         (match_op_dup 1
2373          [(ashift:SI (match_dup 2) (match_dup 4))
2374           (match_dup 5)]))
2375    (set (match_dup 0)
2376         (match_op_dup 1
2377          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2378           (match_dup 7)]))]
2379   "
2380   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2381 ")
2382
2383 (define_split
2384   [(set (match_operand:SI 0 "s_register_operand" "")
2385         (match_operator:SI 1 "logical_binary_operator"
2386          [(match_operator:SI 9 "logical_binary_operator"
2387            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2388                          (match_operand:SI 6 "const_int_operand" ""))
2389             (match_operand:SI 7 "s_register_operand" "")])
2390           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2391                            (match_operand:SI 3 "const_int_operand" "")
2392                            (match_operand:SI 4 "const_int_operand" ""))]))
2393    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2394   "TARGET_ARM
2395    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2396    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2397   [(set (match_dup 8)
2398         (match_op_dup 1
2399          [(ashift:SI (match_dup 2) (match_dup 4))
2400           (match_dup 5)]))
2401    (set (match_dup 0)
2402         (match_op_dup 1
2403          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2404           (match_dup 7)]))]
2405   "
2406   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2407 ")
2408
2409 (define_split
2410   [(set (match_operand:SI 0 "s_register_operand" "")
2411         (match_operator:SI 1 "logical_binary_operator"
2412          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2413                            (match_operand:SI 3 "const_int_operand" "")
2414                            (match_operand:SI 4 "const_int_operand" ""))
2415           (match_operator:SI 9 "logical_binary_operator"
2416            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2417                          (match_operand:SI 6 "const_int_operand" ""))
2418             (match_operand:SI 7 "s_register_operand" "")])]))
2419    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2420   "TARGET_ARM
2421    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2422    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2423   [(set (match_dup 8)
2424         (match_op_dup 1
2425          [(ashift:SI (match_dup 2) (match_dup 4))
2426           (match_dup 5)]))
2427    (set (match_dup 0)
2428         (match_op_dup 1
2429          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2430           (match_dup 7)]))]
2431   "
2432   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2433 ")
2434
2435 (define_split
2436   [(set (match_operand:SI 0 "s_register_operand" "")
2437         (match_operator:SI 1 "logical_binary_operator"
2438          [(match_operator:SI 9 "logical_binary_operator"
2439            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2440                          (match_operand:SI 6 "const_int_operand" ""))
2441             (match_operand:SI 7 "s_register_operand" "")])
2442           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2443                            (match_operand:SI 3 "const_int_operand" "")
2444                            (match_operand:SI 4 "const_int_operand" ""))]))
2445    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2446   "TARGET_ARM
2447    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2448    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2449   [(set (match_dup 8)
2450         (match_op_dup 1
2451          [(ashift:SI (match_dup 2) (match_dup 4))
2452           (match_dup 5)]))
2453    (set (match_dup 0)
2454         (match_op_dup 1
2455          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2456           (match_dup 7)]))]
2457   "
2458   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2459 ")
2460 \f
2461
2462 ;; Minimum and maximum insns
2463
2464 (define_insn "smaxsi3"
2465   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2466         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2467                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2468    (clobber (reg:CC CC_REGNUM))]
2469   "TARGET_ARM"
2470   "@
2471    cmp\\t%1, %2\;movlt\\t%0, %2
2472    cmp\\t%1, %2\;movge\\t%0, %1
2473    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2474   [(set_attr "conds" "clob")
2475    (set_attr "length" "8,8,12")]
2476 )
2477
2478 (define_insn "sminsi3"
2479   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2480         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2481                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2482    (clobber (reg:CC CC_REGNUM))]
2483   "TARGET_ARM"
2484   "@
2485    cmp\\t%1, %2\;movge\\t%0, %2
2486    cmp\\t%1, %2\;movlt\\t%0, %1
2487    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2488   [(set_attr "conds" "clob")
2489    (set_attr "length" "8,8,12")]
2490 )
2491
2492 (define_insn "umaxsi3"
2493   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2494         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2495                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2496    (clobber (reg:CC CC_REGNUM))]
2497   "TARGET_ARM"
2498   "@
2499    cmp\\t%1, %2\;movcc\\t%0, %2
2500    cmp\\t%1, %2\;movcs\\t%0, %1
2501    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2502   [(set_attr "conds" "clob")
2503    (set_attr "length" "8,8,12")]
2504 )
2505
2506 (define_insn "uminsi3"
2507   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2508         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2509                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2510    (clobber (reg:CC CC_REGNUM))]
2511   "TARGET_ARM"
2512   "@
2513    cmp\\t%1, %2\;movcs\\t%0, %2
2514    cmp\\t%1, %2\;movcc\\t%0, %1
2515    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2516   [(set_attr "conds" "clob")
2517    (set_attr "length" "8,8,12")]
2518 )
2519
2520 (define_insn "*store_minmaxsi"
2521   [(set (match_operand:SI 0 "memory_operand" "=m")
2522         (match_operator:SI 3 "minmax_operator"
2523          [(match_operand:SI 1 "s_register_operand" "r")
2524           (match_operand:SI 2 "s_register_operand" "r")]))
2525    (clobber (reg:CC CC_REGNUM))]
2526   "TARGET_ARM"
2527   "*
2528   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2529                                 operands[1], operands[2]);
2530   output_asm_insn (\"cmp\\t%1, %2\", operands);
2531   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2532   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2533   return \"\";
2534   "
2535   [(set_attr "conds" "clob")
2536    (set_attr "length" "12")
2537    (set_attr "type" "store1")]
2538 )
2539
2540 ; Reject the frame pointer in operand[1], since reloading this after
2541 ; it has been eliminated can cause carnage.
2542 (define_insn "*minmax_arithsi"
2543   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2544         (match_operator:SI 4 "shiftable_operator"
2545          [(match_operator:SI 5 "minmax_operator"
2546            [(match_operand:SI 2 "s_register_operand" "r,r")
2547             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2548           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2549    (clobber (reg:CC CC_REGNUM))]
2550   "TARGET_ARM
2551    && (GET_CODE (operands[1]) != REG
2552        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2553            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2554   "*
2555   {
2556     enum rtx_code code = GET_CODE (operands[4]);
2557
2558     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2559                                   operands[2], operands[3]);
2560     output_asm_insn (\"cmp\\t%2, %3\", operands);
2561     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2562     if (which_alternative != 0 || operands[3] != const0_rtx
2563         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2564       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2565     return \"\";
2566   }"
2567   [(set_attr "conds" "clob")
2568    (set_attr "length" "12")]
2569 )
2570
2571 \f
2572 ;; Shift and rotation insns
2573
2574 (define_expand "ashldi3"
2575   [(set (match_operand:DI            0 "s_register_operand" "")
2576         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2577                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2578   "TARGET_ARM"
2579   "
2580   if (GET_CODE (operands[2]) == CONST_INT)
2581     {
2582       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2583         {
2584           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2585           DONE;
2586         }
2587         /* Ideally we shouldn't fail here if we could know that operands[1] 
2588            ends up already living in an iwmmxt register. Otherwise it's
2589            cheaper to have the alternate code being generated than moving
2590            values to iwmmxt regs and back.  */
2591         FAIL;
2592     }
2593   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2594     FAIL;
2595   "
2596 )
2597
2598 (define_insn "arm_ashldi3_1bit"
2599   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2600         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2601                    (const_int 1)))
2602    (clobber (reg:CC CC_REGNUM))]
2603   "TARGET_ARM"
2604   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2605   [(set_attr "conds" "clob")
2606    (set_attr "length" "8")]
2607 )
2608
2609 (define_expand "ashlsi3"
2610   [(set (match_operand:SI            0 "s_register_operand" "")
2611         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2612                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2613   "TARGET_EITHER"
2614   "
2615   if (GET_CODE (operands[2]) == CONST_INT
2616       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2617     {
2618       emit_insn (gen_movsi (operands[0], const0_rtx));
2619       DONE;
2620     }
2621   "
2622 )
2623
2624 (define_insn "*thumb_ashlsi3"
2625   [(set (match_operand:SI            0 "register_operand" "=l,l")
2626         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2627                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2628   "TARGET_THUMB"
2629   "lsl\\t%0, %1, %2"
2630   [(set_attr "length" "2")]
2631 )
2632
2633 (define_expand "ashrdi3"
2634   [(set (match_operand:DI              0 "s_register_operand" "")
2635         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2636                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2637   "TARGET_ARM"
2638   "
2639   if (GET_CODE (operands[2]) == CONST_INT)
2640     {
2641       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2642         {
2643           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2644           DONE;
2645         }
2646         /* Ideally we shouldn't fail here if we could know that operands[1] 
2647            ends up already living in an iwmmxt register. Otherwise it's
2648            cheaper to have the alternate code being generated than moving
2649            values to iwmmxt regs and back.  */
2650         FAIL;
2651     }
2652   else if (!TARGET_REALLY_IWMMXT)
2653     FAIL;
2654   "
2655 )
2656
2657 (define_insn "arm_ashrdi3_1bit"
2658   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2659         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2660                      (const_int 1)))
2661    (clobber (reg:CC CC_REGNUM))]
2662   "TARGET_ARM"
2663   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2664   [(set_attr "conds" "clob")
2665    (set_attr "length" "8")]
2666 )
2667
2668 (define_expand "ashrsi3"
2669   [(set (match_operand:SI              0 "s_register_operand" "")
2670         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2671                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2672   "TARGET_EITHER"
2673   "
2674   if (GET_CODE (operands[2]) == CONST_INT
2675       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2676     operands[2] = GEN_INT (31);
2677   "
2678 )
2679
2680 (define_insn "*thumb_ashrsi3"
2681   [(set (match_operand:SI              0 "register_operand" "=l,l")
2682         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2683                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2684   "TARGET_THUMB"
2685   "asr\\t%0, %1, %2"
2686   [(set_attr "length" "2")]
2687 )
2688
2689 (define_expand "lshrdi3"
2690   [(set (match_operand:DI              0 "s_register_operand" "")
2691         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2692                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2693   "TARGET_ARM"
2694   "
2695   if (GET_CODE (operands[2]) == CONST_INT)
2696     {
2697       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2698         {
2699           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2700           DONE;
2701         }
2702         /* Ideally we shouldn't fail here if we could know that operands[1] 
2703            ends up already living in an iwmmxt register. Otherwise it's
2704            cheaper to have the alternate code being generated than moving
2705            values to iwmmxt regs and back.  */
2706         FAIL;
2707     }
2708   else if (!TARGET_REALLY_IWMMXT)
2709     FAIL;
2710   "
2711 )
2712
2713 (define_insn "arm_lshrdi3_1bit"
2714   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2715         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2716                      (const_int 1)))
2717    (clobber (reg:CC CC_REGNUM))]
2718   "TARGET_ARM"
2719   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2720   [(set_attr "conds" "clob")
2721    (set_attr "length" "8")]
2722 )
2723
2724 (define_expand "lshrsi3"
2725   [(set (match_operand:SI              0 "s_register_operand" "")
2726         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2727                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2728   "TARGET_EITHER"
2729   "
2730   if (GET_CODE (operands[2]) == CONST_INT
2731       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2732     {
2733       emit_insn (gen_movsi (operands[0], const0_rtx));
2734       DONE;
2735     }
2736   "
2737 )
2738
2739 (define_insn "*thumb_lshrsi3"
2740   [(set (match_operand:SI              0 "register_operand" "=l,l")
2741         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2742                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2743   "TARGET_THUMB"
2744   "lsr\\t%0, %1, %2"
2745   [(set_attr "length" "2")]
2746 )
2747
2748 (define_expand "rotlsi3"
2749   [(set (match_operand:SI              0 "s_register_operand" "")
2750         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2751                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2752   "TARGET_ARM"
2753   "
2754   if (GET_CODE (operands[2]) == CONST_INT)
2755     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2756   else
2757     {
2758       rtx reg = gen_reg_rtx (SImode);
2759       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2760       operands[2] = reg;
2761     }
2762   "
2763 )
2764
2765 (define_expand "rotrsi3"
2766   [(set (match_operand:SI              0 "s_register_operand" "")
2767         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2768                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2769   "TARGET_EITHER"
2770   "
2771   if (TARGET_ARM)
2772     {
2773       if (GET_CODE (operands[2]) == CONST_INT
2774           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2775         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2776     }
2777   else /* TARGET_THUMB */
2778     {
2779       if (GET_CODE (operands [2]) == CONST_INT)
2780         operands [2] = force_reg (SImode, operands[2]);
2781     }
2782   "
2783 )
2784
2785 (define_insn "*thumb_rotrsi3"
2786   [(set (match_operand:SI              0 "register_operand" "=l")
2787         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2788                      (match_operand:SI 2 "register_operand" "l")))]
2789   "TARGET_THUMB"
2790   "ror\\t%0, %0, %2"
2791   [(set_attr "length" "2")]
2792 )
2793
2794 (define_insn "*arm_shiftsi3"
2795   [(set (match_operand:SI   0 "s_register_operand" "=r")
2796         (match_operator:SI  3 "shift_operator"
2797          [(match_operand:SI 1 "s_register_operand"  "r")
2798           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2799   "TARGET_ARM"
2800   "mov%?\\t%0, %1%S3"
2801   [(set_attr "predicable" "yes")
2802    (set_attr "shift" "1")
2803    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2804                       (const_string "alu_shift")
2805                       (const_string "alu_shift_reg")))]
2806 )
2807
2808 (define_insn "*shiftsi3_compare0"
2809   [(set (reg:CC_NOOV CC_REGNUM)
2810         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2811                           [(match_operand:SI 1 "s_register_operand" "r")
2812                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2813                          (const_int 0)))
2814    (set (match_operand:SI 0 "s_register_operand" "=r")
2815         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2816   "TARGET_ARM"
2817   "mov%?s\\t%0, %1%S3"
2818   [(set_attr "conds" "set")
2819    (set_attr "shift" "1")
2820    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2821                       (const_string "alu_shift")
2822                       (const_string "alu_shift_reg")))]
2823 )
2824
2825 (define_insn "*shiftsi3_compare0_scratch"
2826   [(set (reg:CC_NOOV CC_REGNUM)
2827         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2828                           [(match_operand:SI 1 "s_register_operand" "r")
2829                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2830                          (const_int 0)))
2831    (clobber (match_scratch:SI 0 "=r"))]
2832   "TARGET_ARM"
2833   "mov%?s\\t%0, %1%S3"
2834   [(set_attr "conds" "set")
2835    (set_attr "shift" "1")]
2836 )
2837
2838 (define_insn "*notsi_shiftsi"
2839   [(set (match_operand:SI 0 "s_register_operand" "=r")
2840         (not:SI (match_operator:SI 3 "shift_operator"
2841                  [(match_operand:SI 1 "s_register_operand" "r")
2842                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2843   "TARGET_ARM"
2844   "mvn%?\\t%0, %1%S3"
2845   [(set_attr "predicable" "yes")
2846    (set_attr "shift" "1")
2847    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2848                       (const_string "alu_shift")
2849                       (const_string "alu_shift_reg")))]
2850 )
2851
2852 (define_insn "*notsi_shiftsi_compare0"
2853   [(set (reg:CC_NOOV CC_REGNUM)
2854         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2855                           [(match_operand:SI 1 "s_register_operand" "r")
2856                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2857                          (const_int 0)))
2858    (set (match_operand:SI 0 "s_register_operand" "=r")
2859         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2860   "TARGET_ARM"
2861   "mvn%?s\\t%0, %1%S3"
2862   [(set_attr "conds" "set")
2863    (set_attr "shift" "1")
2864    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2865                       (const_string "alu_shift")
2866                       (const_string "alu_shift_reg")))]
2867 )
2868
2869 (define_insn "*not_shiftsi_compare0_scratch"
2870   [(set (reg:CC_NOOV CC_REGNUM)
2871         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2872                           [(match_operand:SI 1 "s_register_operand" "r")
2873                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2874                          (const_int 0)))
2875    (clobber (match_scratch:SI 0 "=r"))]
2876   "TARGET_ARM"
2877   "mvn%?s\\t%0, %1%S3"
2878   [(set_attr "conds" "set")
2879    (set_attr "shift" "1")
2880    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2881                       (const_string "alu_shift")
2882                       (const_string "alu_shift_reg")))]
2883 )
2884
2885 ;; We don't really have extzv, but defining this using shifts helps
2886 ;; to reduce register pressure later on.
2887
2888 (define_expand "extzv"
2889   [(set (match_dup 4)
2890         (ashift:SI (match_operand:SI   1 "register_operand" "")
2891                    (match_operand:SI   2 "const_int_operand" "")))
2892    (set (match_operand:SI              0 "register_operand" "")
2893         (lshiftrt:SI (match_dup 4)
2894                      (match_operand:SI 3 "const_int_operand" "")))]
2895   "TARGET_THUMB"
2896   "
2897   {
2898     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2899     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2900     
2901     operands[3] = GEN_INT (rshift);
2902     
2903     if (lshift == 0)
2904       {
2905         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2906         DONE;
2907       }
2908       
2909     operands[2] = GEN_INT (lshift);
2910     operands[4] = gen_reg_rtx (SImode);
2911   }"
2912 )
2913
2914 \f
2915 ;; Unary arithmetic insns
2916
2917 (define_expand "negdi2"
2918  [(parallel
2919    [(set (match_operand:DI          0 "s_register_operand" "")
2920           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2921     (clobber (reg:CC CC_REGNUM))])]
2922   "TARGET_EITHER"
2923   "
2924   if (TARGET_THUMB)
2925     {
2926       if (GET_CODE (operands[1]) != REG)
2927         operands[1] = force_reg (SImode, operands[1]);
2928      }
2929   "
2930 )
2931
2932 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2933 ;; The second alternative is to allow the common case of a *full* overlap.
2934 (define_insn "*arm_negdi2"
2935   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2936         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2937    (clobber (reg:CC CC_REGNUM))]
2938   "TARGET_ARM"
2939   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2940   [(set_attr "conds" "clob")
2941    (set_attr "length" "8")]
2942 )
2943
2944 (define_insn "*thumb_negdi2"
2945   [(set (match_operand:DI         0 "register_operand" "=&l")
2946         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2947    (clobber (reg:CC CC_REGNUM))]
2948   "TARGET_THUMB"
2949   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2950   [(set_attr "length" "6")]
2951 )
2952
2953 (define_expand "negsi2"
2954   [(set (match_operand:SI         0 "s_register_operand" "")
2955         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2956   "TARGET_EITHER"
2957   ""
2958 )
2959
2960 (define_insn "*arm_negsi2"
2961   [(set (match_operand:SI         0 "s_register_operand" "=r")
2962         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2963   "TARGET_ARM"
2964   "rsb%?\\t%0, %1, #0"
2965   [(set_attr "predicable" "yes")]
2966 )
2967
2968 (define_insn "*thumb_negsi2"
2969   [(set (match_operand:SI         0 "register_operand" "=l")
2970         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2971   "TARGET_THUMB"
2972   "neg\\t%0, %1"
2973   [(set_attr "length" "2")]
2974 )
2975
2976 (define_expand "negsf2"
2977   [(set (match_operand:SF         0 "s_register_operand" "")
2978         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2979   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2980   ""
2981 )
2982
2983 (define_expand "negdf2"
2984   [(set (match_operand:DF         0 "s_register_operand" "")
2985         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2986   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2987   "")
2988
2989 ;; abssi2 doesn't really clobber the condition codes if a different register
2990 ;; is being set.  To keep things simple, assume during rtl manipulations that
2991 ;; it does, but tell the final scan operator the truth.  Similarly for
2992 ;; (neg (abs...))
2993
2994 (define_expand "abssi2"
2995   [(parallel
2996     [(set (match_operand:SI         0 "s_register_operand" "")
2997           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2998      (clobber (reg:CC CC_REGNUM))])]
2999   "TARGET_ARM"
3000   "")
3001
3002 (define_insn "*arm_abssi2"
3003   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3004         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3005    (clobber (reg:CC CC_REGNUM))]
3006   "TARGET_ARM"
3007   "@
3008    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3009    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3010   [(set_attr "conds" "clob,*")
3011    (set_attr "shift" "1")
3012    ;; predicable can't be set based on the variant, so left as no
3013    (set_attr "length" "8")]
3014 )
3015
3016 (define_insn "*neg_abssi2"
3017   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3018         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3019    (clobber (reg:CC CC_REGNUM))]
3020   "TARGET_ARM"
3021   "@
3022    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3023    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3024   [(set_attr "conds" "clob,*")
3025    (set_attr "shift" "1")
3026    ;; predicable can't be set based on the variant, so left as no
3027    (set_attr "length" "8")]
3028 )
3029
3030 (define_expand "abssf2"
3031   [(set (match_operand:SF         0 "s_register_operand" "")
3032         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3033   "TARGET_ARM && TARGET_HARD_FLOAT"
3034   "")
3035
3036 (define_expand "absdf2"
3037   [(set (match_operand:DF         0 "s_register_operand" "")
3038         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3039   "TARGET_ARM && TARGET_HARD_FLOAT"
3040   "")
3041
3042 (define_expand "sqrtsf2"
3043   [(set (match_operand:SF 0 "s_register_operand" "")
3044         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3045   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3046   "")
3047
3048 (define_expand "sqrtdf2"
3049   [(set (match_operand:DF 0 "s_register_operand" "")
3050         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3051   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3052   "")
3053
3054 (define_insn_and_split "one_cmpldi2"
3055   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3056         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3057   "TARGET_ARM"
3058   "#"
3059   "TARGET_ARM && reload_completed"
3060   [(set (match_dup 0) (not:SI (match_dup 1)))
3061    (set (match_dup 2) (not:SI (match_dup 3)))]
3062   "
3063   {
3064     operands[2] = gen_highpart (SImode, operands[0]);
3065     operands[0] = gen_lowpart (SImode, operands[0]);
3066     operands[3] = gen_highpart (SImode, operands[1]);
3067     operands[1] = gen_lowpart (SImode, operands[1]);
3068   }"
3069   [(set_attr "length" "8")
3070    (set_attr "predicable" "yes")]
3071 )
3072
3073 (define_expand "one_cmplsi2"
3074   [(set (match_operand:SI         0 "s_register_operand" "")
3075         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3076   "TARGET_EITHER"
3077   ""
3078 )
3079
3080 (define_insn "*arm_one_cmplsi2"
3081   [(set (match_operand:SI         0 "s_register_operand" "=r")
3082         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3083   "TARGET_ARM"
3084   "mvn%?\\t%0, %1"
3085   [(set_attr "predicable" "yes")]
3086 )
3087
3088 (define_insn "*thumb_one_cmplsi2"
3089   [(set (match_operand:SI         0 "register_operand" "=l")
3090         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3091   "TARGET_THUMB"
3092   "mvn\\t%0, %1"
3093   [(set_attr "length" "2")]
3094 )
3095
3096 (define_insn "*notsi_compare0"
3097   [(set (reg:CC_NOOV CC_REGNUM)
3098         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3099                          (const_int 0)))
3100    (set (match_operand:SI 0 "s_register_operand" "=r")
3101         (not:SI (match_dup 1)))]
3102   "TARGET_ARM"
3103   "mvn%?s\\t%0, %1"
3104   [(set_attr "conds" "set")]
3105 )
3106
3107 (define_insn "*notsi_compare0_scratch"
3108   [(set (reg:CC_NOOV CC_REGNUM)
3109         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3110                          (const_int 0)))
3111    (clobber (match_scratch:SI 0 "=r"))]
3112   "TARGET_ARM"
3113   "mvn%?s\\t%0, %1"
3114   [(set_attr "conds" "set")]
3115 )
3116 \f
3117 ;; Fixed <--> Floating conversion insns
3118
3119 (define_expand "floatsisf2"
3120   [(set (match_operand:SF           0 "s_register_operand" "")
3121         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3122   "TARGET_ARM && TARGET_HARD_FLOAT"
3123   "
3124   if (TARGET_MAVERICK)
3125     {
3126       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3127       DONE;
3128     }
3129 ")
3130
3131 (define_expand "floatsidf2"
3132   [(set (match_operand:DF           0 "s_register_operand" "")
3133         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3134   "TARGET_ARM && TARGET_HARD_FLOAT"
3135   "
3136   if (TARGET_MAVERICK)
3137     {
3138       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3139       DONE;
3140     }
3141 ")
3142
3143 (define_expand "fix_truncsfsi2"
3144   [(set (match_operand:SI         0 "s_register_operand" "")
3145         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3146   "TARGET_ARM && TARGET_HARD_FLOAT"
3147   "
3148   if (TARGET_MAVERICK)
3149     {
3150       if (!cirrus_fp_register (operands[0], SImode))
3151         operands[0] = force_reg (SImode, operands[0]);
3152       if (!cirrus_fp_register (operands[1], SFmode))
3153         operands[1] = force_reg (SFmode, operands[0]);
3154       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3155       DONE;
3156     }
3157 ")
3158
3159 (define_expand "fix_truncdfsi2"
3160   [(set (match_operand:SI         0 "s_register_operand" "")
3161         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3162   "TARGET_ARM && TARGET_HARD_FLOAT"
3163   "
3164   if (TARGET_MAVERICK)
3165     {
3166       if (!cirrus_fp_register (operands[1], DFmode))
3167         operands[1] = force_reg (DFmode, operands[0]);
3168       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3169       DONE;
3170     }
3171 ")
3172
3173 ;; Truncation insns
3174
3175 (define_expand "truncdfsf2"
3176   [(set (match_operand:SF  0 "s_register_operand" "")
3177         (float_truncate:SF
3178          (match_operand:DF 1 "s_register_operand" "")))]
3179   "TARGET_ARM && TARGET_HARD_FLOAT"
3180   ""
3181 )
3182 \f
3183 ;; Zero and sign extension instructions.
3184
3185 (define_insn "zero_extendsidi2"
3186   [(set (match_operand:DI 0 "s_register_operand" "=r")
3187         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3188   "TARGET_ARM"
3189   "*
3190     if (REGNO (operands[1])
3191         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3192       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3193     return \"mov%?\\t%R0, #0\";
3194   "
3195   [(set_attr "length" "8")
3196    (set_attr "predicable" "yes")]
3197 )
3198
3199 (define_insn "zero_extendqidi2"
3200   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3201         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3202   "TARGET_ARM"
3203   "@
3204    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3205    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3206   [(set_attr "length" "8")
3207    (set_attr "predicable" "yes")
3208    (set_attr "type" "*,load_byte")
3209    (set_attr "pool_range" "*,4092")
3210    (set_attr "neg_pool_range" "*,4084")]
3211 )
3212
3213 (define_insn "extendsidi2"
3214   [(set (match_operand:DI 0 "s_register_operand" "=r")
3215         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3216   "TARGET_ARM"
3217   "*
3218     if (REGNO (operands[1])
3219         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3220       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3221     return \"mov%?\\t%R0, %Q0, asr #31\";
3222   "
3223   [(set_attr "length" "8")
3224    (set_attr "shift" "1")
3225    (set_attr "predicable" "yes")]
3226 )
3227
3228 (define_expand "zero_extendhisi2"
3229   [(set (match_dup 2)
3230         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3231                    (const_int 16)))
3232    (set (match_operand:SI 0 "s_register_operand" "")
3233         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3234   "TARGET_EITHER"
3235   "
3236   {
3237     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3238       {
3239         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3240                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3241         DONE;
3242       }
3243
3244     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3245       {
3246         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3247         DONE;
3248       }
3249
3250     if (!s_register_operand (operands[1], HImode))
3251       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3252
3253     if (arm_arch6)
3254       {
3255         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3256                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3257         DONE;
3258       }
3259
3260     operands[1] = gen_lowpart (SImode, operands[1]);
3261     operands[2] = gen_reg_rtx (SImode);
3262   }"
3263 )
3264
3265 (define_insn "*thumb_zero_extendhisi2"
3266   [(set (match_operand:SI 0 "register_operand" "=l")
3267         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3268   "TARGET_THUMB && !arm_arch6"
3269   "*
3270   rtx mem = XEXP (operands[1], 0);
3271
3272   if (GET_CODE (mem) == CONST)
3273     mem = XEXP (mem, 0);
3274     
3275   if (GET_CODE (mem) == LABEL_REF)
3276     return \"ldr\\t%0, %1\";
3277     
3278   if (GET_CODE (mem) == PLUS)
3279     {
3280       rtx a = XEXP (mem, 0);
3281       rtx b = XEXP (mem, 1);
3282
3283       /* This can happen due to bugs in reload.  */
3284       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3285         {
3286           rtx ops[2];
3287           ops[0] = operands[0];
3288           ops[1] = a;
3289       
3290           output_asm_insn (\"mov        %0, %1\", ops);
3291
3292           XEXP (mem, 0) = operands[0];
3293        }
3294
3295       else if (   GET_CODE (a) == LABEL_REF
3296                && GET_CODE (b) == CONST_INT)
3297         return \"ldr\\t%0, %1\";
3298     }
3299     
3300   return \"ldrh\\t%0, %1\";
3301   "
3302   [(set_attr "length" "4")
3303    (set_attr "type" "load_byte")
3304    (set_attr "pool_range" "60")]
3305 )
3306
3307 (define_insn "*thumb_zero_extendhisi2_v6"
3308   [(set (match_operand:SI 0 "register_operand" "=l,l")
3309         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3310   "TARGET_THUMB && arm_arch6"
3311   "*
3312   rtx mem;
3313
3314   if (which_alternative == 0)
3315     return \"uxth\\t%0, %1\";
3316
3317   mem = XEXP (operands[1], 0);
3318
3319   if (GET_CODE (mem) == CONST)
3320     mem = XEXP (mem, 0);
3321     
3322   if (GET_CODE (mem) == LABEL_REF)
3323     return \"ldr\\t%0, %1\";
3324     
3325   if (GET_CODE (mem) == PLUS)
3326     {
3327       rtx a = XEXP (mem, 0);
3328       rtx b = XEXP (mem, 1);
3329
3330       /* This can happen due to bugs in reload.  */
3331       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3332         {
3333           rtx ops[2];
3334           ops[0] = operands[0];
3335           ops[1] = a;
3336       
3337           output_asm_insn (\"mov        %0, %1\", ops);
3338
3339           XEXP (mem, 0) = operands[0];
3340        }
3341
3342       else if (   GET_CODE (a) == LABEL_REF
3343                && GET_CODE (b) == CONST_INT)
3344         return \"ldr\\t%0, %1\";
3345     }
3346     
3347   return \"ldrh\\t%0, %1\";
3348   "
3349   [(set_attr "length" "2,4")
3350    (set_attr "type" "alu_shift,load_byte")
3351    (set_attr "pool_range" "*,60")]
3352 )
3353
3354 (define_insn "*arm_zero_extendhisi2"
3355   [(set (match_operand:SI 0 "s_register_operand" "=r")
3356         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3357   "TARGET_ARM && arm_arch4 && !arm_arch6"
3358   "ldr%?h\\t%0, %1"
3359   [(set_attr "type" "load_byte")
3360    (set_attr "predicable" "yes")
3361    (set_attr "pool_range" "256")
3362    (set_attr "neg_pool_range" "244")]
3363 )
3364
3365 (define_insn "*arm_zero_extendhisi2_v6"
3366   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3367         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3368   "TARGET_ARM && arm_arch6"
3369   "@
3370    uxth%?\\t%0, %1
3371    ldr%?h\\t%0, %1"
3372   [(set_attr "type" "alu_shift,load_byte")
3373    (set_attr "predicable" "yes")
3374    (set_attr "pool_range" "*,256")
3375    (set_attr "neg_pool_range" "*,244")]
3376 )
3377
3378 (define_insn "*arm_zero_extendhisi2addsi"
3379   [(set (match_operand:SI 0 "s_register_operand" "=r")
3380         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3381                  (match_operand:SI 2 "s_register_operand" "r")))]
3382   "TARGET_ARM && arm_arch6"
3383   "uxtah%?\\t%0, %2, %1"
3384   [(set_attr "type" "alu_shift")
3385    (set_attr "predicable" "yes")]
3386 )
3387
3388 (define_split
3389   [(set (match_operand:SI 0 "s_register_operand" "")
3390         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3391    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3392   "TARGET_ARM && (!arm_arch4)"
3393   [(set (match_dup 2) (match_dup 1))
3394    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3395   "
3396   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3397     FAIL;
3398   "
3399 )
3400
3401 (define_split
3402   [(set (match_operand:SI 0 "s_register_operand" "")
3403         (match_operator:SI 3 "shiftable_operator"
3404          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3405           (match_operand:SI 4 "s_register_operand" "")]))
3406    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3407   "TARGET_ARM && (!arm_arch4)"
3408   [(set (match_dup 2) (match_dup 1))
3409    (set (match_dup 0)
3410         (match_op_dup 3
3411          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3412   "
3413   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3414     FAIL;
3415   "
3416 )
3417
3418 (define_expand "zero_extendqisi2"
3419   [(set (match_operand:SI 0 "s_register_operand" "")
3420         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3421   "TARGET_EITHER"
3422   "
3423   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3424     {
3425       if (TARGET_ARM)
3426         {
3427           emit_insn (gen_andsi3 (operands[0],
3428                                  gen_lowpart (SImode, operands[1]),
3429                                  GEN_INT (255)));
3430         }
3431       else /* TARGET_THUMB */
3432         {
3433           rtx temp = gen_reg_rtx (SImode);
3434           rtx ops[3];
3435           
3436           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3437           operands[1] = gen_lowpart (SImode, operands[1]);
3438
3439           ops[0] = temp;
3440           ops[1] = operands[1];
3441           ops[2] = GEN_INT (24);
3442
3443           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3444                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3445           
3446           ops[0] = operands[0];
3447           ops[1] = temp;
3448           ops[2] = GEN_INT (24);
3449
3450           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3451                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3452         }
3453       DONE;
3454     }
3455   "
3456 )
3457
3458 (define_insn "*thumb_zero_extendqisi2"
3459   [(set (match_operand:SI 0 "register_operand" "=l")
3460         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3461   "TARGET_THUMB && !arm_arch6"
3462   "ldrb\\t%0, %1"
3463   [(set_attr "length" "2")
3464    (set_attr "type" "load_byte")
3465    (set_attr "pool_range" "32")]
3466 )
3467
3468 (define_insn "*thumb_zero_extendqisi2_v6"
3469   [(set (match_operand:SI 0 "register_operand" "=l,l")
3470         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3471   "TARGET_THUMB && arm_arch6"
3472   "@
3473    uxtb\\t%0, %1
3474    ldrb\\t%0, %1"
3475   [(set_attr "length" "2,2")
3476    (set_attr "type" "alu_shift,load_byte")
3477    (set_attr "pool_range" "*,32")]
3478 )
3479
3480 (define_insn "*arm_zero_extendqisi2"
3481   [(set (match_operand:SI 0 "s_register_operand" "=r")
3482         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3483   "TARGET_ARM && !arm_arch6"
3484   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3485   [(set_attr "type" "load_byte")
3486    (set_attr "predicable" "yes")
3487    (set_attr "pool_range" "4096")
3488    (set_attr "neg_pool_range" "4084")]
3489 )
3490
3491 (define_insn "*arm_zero_extendqisi2_v6"
3492   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3493         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3494   "TARGET_ARM && arm_arch6"
3495   "@
3496    uxtb%?\\t%0, %1
3497    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3498   [(set_attr "type" "alu_shift,load_byte")
3499    (set_attr "predicable" "yes")
3500    (set_attr "pool_range" "*,4096")
3501    (set_attr "neg_pool_range" "*,4084")]
3502 )
3503
3504 (define_insn "*arm_zero_extendqisi2addsi"
3505   [(set (match_operand:SI 0 "s_register_operand" "=r")
3506         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3507                  (match_operand:SI 2 "s_register_operand" "r")))]
3508   "TARGET_ARM && arm_arch6"
3509   "uxtab%?\\t%0, %2, %1"
3510   [(set_attr "predicable" "yes")
3511    (set_attr "type" "alu_shift")]
3512 )
3513
3514 (define_split
3515   [(set (match_operand:SI 0 "s_register_operand" "")
3516         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3517    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3518   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3519   [(set (match_dup 2) (match_dup 1))
3520    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3521   ""
3522 )
3523
3524 (define_insn "*compareqi_eq0"
3525   [(set (reg:CC_Z CC_REGNUM)
3526         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3527                          (const_int 0)))]
3528   "TARGET_ARM"
3529   "tst\\t%0, #255"
3530   [(set_attr "conds" "set")]
3531 )
3532
3533 (define_expand "extendhisi2"
3534   [(set (match_dup 2)
3535         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3536                    (const_int 16)))
3537    (set (match_operand:SI 0 "s_register_operand" "")
3538         (ashiftrt:SI (match_dup 2)
3539                      (const_int 16)))]
3540   "TARGET_EITHER"
3541   "
3542   {
3543     if (GET_CODE (operands[1]) == MEM)
3544       {
3545         if (TARGET_THUMB)
3546           {
3547             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3548             DONE;
3549           }
3550         else if (arm_arch4)
3551           {
3552             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3553                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3554             DONE;
3555           }
3556       }
3557
3558     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3559       {
3560         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3561         DONE;
3562       }
3563
3564     if (!s_register_operand (operands[1], HImode))
3565       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3566
3567     if (arm_arch6)
3568       {
3569         if (TARGET_THUMB)
3570           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3571         else
3572           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3573                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3574
3575         DONE;
3576       }
3577
3578     operands[1] = gen_lowpart (SImode, operands[1]);
3579     operands[2] = gen_reg_rtx (SImode);
3580   }"
3581 )
3582
3583 (define_insn "thumb_extendhisi2"
3584   [(set (match_operand:SI 0 "register_operand" "=l")
3585         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3586    (clobber (match_scratch:SI 2 "=&l"))]
3587   "TARGET_THUMB && !arm_arch6"
3588   "*
3589   {
3590     rtx ops[4];
3591     rtx mem = XEXP (operands[1], 0);
3592
3593     /* This code used to try to use 'V', and fix the address only if it was
3594        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3595        range of QImode offsets, and offsettable_address_p does a QImode
3596        address check.  */
3597        
3598     if (GET_CODE (mem) == CONST)
3599       mem = XEXP (mem, 0);
3600     
3601     if (GET_CODE (mem) == LABEL_REF)
3602       return \"ldr\\t%0, %1\";
3603     
3604     if (GET_CODE (mem) == PLUS)
3605       {
3606         rtx a = XEXP (mem, 0);
3607         rtx b = XEXP (mem, 1);
3608
3609         if (GET_CODE (a) == LABEL_REF
3610             && GET_CODE (b) == CONST_INT)
3611           return \"ldr\\t%0, %1\";
3612
3613         if (GET_CODE (b) == REG)
3614           return \"ldrsh\\t%0, %1\";
3615           
3616         ops[1] = a;
3617         ops[2] = b;
3618       }
3619     else
3620       {
3621         ops[1] = mem;
3622         ops[2] = const0_rtx;
3623       }
3624       
3625     if (GET_CODE (ops[1]) != REG)
3626       {
3627         debug_rtx (ops[1]);
3628         abort ();
3629       }
3630
3631     ops[0] = operands[0];
3632     ops[3] = operands[2];
3633     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3634     return \"\";
3635   }"
3636   [(set_attr "length" "4")
3637    (set_attr "type" "load_byte")
3638    (set_attr "pool_range" "1020")]
3639 )
3640
3641 ;; We used to have an early-clobber on the scratch register here.
3642 ;; However, there's a bug somewhere in reload which means that this
3643 ;; can be partially ignored during spill allocation if the memory
3644 ;; address also needs reloading; this causes an abort later on when
3645 ;; we try to verify the operands.  Fortunately, we don't really need
3646 ;; the early-clobber: we can always use operand 0 if operand 2
3647 ;; overlaps the address.
3648 (define_insn "*thumb_extendhisi2_insn_v6"
3649   [(set (match_operand:SI 0 "register_operand" "=l,l")
3650         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3651    (clobber (match_scratch:SI 2 "=X,l"))]
3652   "TARGET_THUMB && arm_arch6"
3653   "*
3654   {
3655     rtx ops[4];
3656     rtx mem;
3657
3658     if (which_alternative == 0)
3659       return \"sxth\\t%0, %1\";
3660
3661     mem = XEXP (operands[1], 0);
3662
3663     /* This code used to try to use 'V', and fix the address only if it was
3664        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3665        range of QImode offsets, and offsettable_address_p does a QImode
3666        address check.  */
3667        
3668     if (GET_CODE (mem) == CONST)
3669       mem = XEXP (mem, 0);
3670     
3671     if (GET_CODE (mem) == LABEL_REF)
3672       return \"ldr\\t%0, %1\";
3673     
3674     if (GET_CODE (mem) == PLUS)
3675       {
3676         rtx a = XEXP (mem, 0);
3677         rtx b = XEXP (mem, 1);
3678
3679         if (GET_CODE (a) == LABEL_REF
3680             && GET_CODE (b) == CONST_INT)
3681           return \"ldr\\t%0, %1\";
3682
3683         if (GET_CODE (b) == REG)
3684           return \"ldrsh\\t%0, %1\";
3685           
3686         ops[1] = a;
3687         ops[2] = b;
3688       }
3689     else
3690       {
3691         ops[1] = mem;
3692         ops[2] = const0_rtx;
3693       }
3694       
3695     if (GET_CODE (ops[1]) != REG)
3696       {
3697         debug_rtx (ops[1]);
3698         abort ();
3699       }
3700
3701     ops[0] = operands[0];
3702     if (reg_mentioned_p (operands[2], ops[1]))
3703       ops[3] = ops[0];
3704     else
3705       ops[3] = operands[2];
3706     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3707     return \"\";
3708   }"
3709   [(set_attr "length" "2,4")
3710    (set_attr "type" "alu_shift,load_byte")
3711    (set_attr "pool_range" "*,1020")]
3712 )
3713
3714 (define_expand "extendhisi2_mem"
3715   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3716    (set (match_dup 3)
3717         (zero_extend:SI (match_dup 7)))
3718    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3719    (set (match_operand:SI 0 "" "")
3720         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3721   "TARGET_ARM"
3722   "
3723   {
3724     rtx mem1, mem2;
3725     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3726
3727     mem1 = gen_rtx_MEM (QImode, addr);
3728     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3729     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3730     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3731     operands[0] = gen_lowpart (SImode, operands[0]);
3732     operands[1] = mem1;
3733     operands[2] = gen_reg_rtx (SImode);
3734     operands[3] = gen_reg_rtx (SImode);
3735     operands[6] = gen_reg_rtx (SImode);
3736     operands[7] = mem2;
3737
3738     if (BYTES_BIG_ENDIAN)
3739       {
3740         operands[4] = operands[2];
3741         operands[5] = operands[3];
3742       }
3743     else
3744       {
3745         operands[4] = operands[3];
3746         operands[5] = operands[2];
3747       }
3748   }"
3749 )
3750
3751 (define_insn "*arm_extendhisi2"
3752   [(set (match_operand:SI 0 "s_register_operand" "=r")
3753         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3754   "TARGET_ARM && arm_arch4 && !arm_arch6"
3755   "ldr%?sh\\t%0, %1"
3756   [(set_attr "type" "load_byte")
3757    (set_attr "predicable" "yes")
3758    (set_attr "pool_range" "256")
3759    (set_attr "neg_pool_range" "244")]
3760 )
3761
3762 (define_insn "*arm_extendhisi2_v6"
3763   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3764         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3765   "TARGET_ARM && arm_arch6"
3766   "@
3767    sxth%?\\t%0, %1
3768    ldr%?sh\\t%0, %1"
3769   [(set_attr "type" "alu_shift,load_byte")
3770    (set_attr "predicable" "yes")
3771    (set_attr "pool_range" "*,256")
3772    (set_attr "neg_pool_range" "*,244")]
3773 )
3774
3775 (define_insn "*arm_extendhisi2addsi"
3776   [(set (match_operand:SI 0 "s_register_operand" "=r")
3777         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3778                  (match_operand:SI 2 "s_register_operand" "r")))]
3779   "TARGET_ARM && arm_arch6"
3780   "sxtah%?\\t%0, %2, %1"
3781 )
3782
3783 (define_split
3784   [(set (match_operand:SI                 0 "s_register_operand" "")
3785         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3786    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3787   "TARGET_ARM && (!arm_arch4)"
3788   [(set (match_dup 2) (match_dup 1))
3789    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3790   "
3791   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3792     FAIL;
3793   "
3794 )
3795
3796 (define_split
3797   [(set (match_operand:SI                   0 "s_register_operand" "")
3798         (match_operator:SI                  3 "shiftable_operator"
3799          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3800           (match_operand:SI                 4 "s_register_operand" "")]))
3801    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3802   "TARGET_ARM && (!arm_arch4)"
3803   [(set (match_dup 2) (match_dup 1))
3804    (set (match_dup 0)
3805         (match_op_dup 3
3806          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3807   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3808      FAIL;
3809   "
3810 )
3811
3812 (define_expand "extendqihi2"
3813   [(set (match_dup 2)
3814         (ashift:SI (match_operand:QI 1 "general_operand" "")
3815                    (const_int 24)))
3816    (set (match_operand:HI 0 "s_register_operand" "")
3817         (ashiftrt:SI (match_dup 2)
3818                      (const_int 24)))]
3819   "TARGET_ARM"
3820   "
3821   {
3822     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3823       {
3824         emit_insn (gen_rtx_SET (VOIDmode,
3825                                 operands[0],
3826                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3827         DONE;
3828       }
3829     if (!s_register_operand (operands[1], QImode))
3830       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3831     operands[0] = gen_lowpart (SImode, operands[0]);
3832     operands[1] = gen_lowpart (SImode, operands[1]);
3833     operands[2] = gen_reg_rtx (SImode);
3834   }"
3835 )
3836
3837 (define_insn "*extendqihi_insn"
3838   [(set (match_operand:HI 0 "s_register_operand" "=r")
3839         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3840   "TARGET_ARM && arm_arch4"
3841   "ldr%?sb\\t%0, %1"
3842   [(set_attr "type" "load_byte")
3843    (set_attr "predicable" "yes")
3844    (set_attr "pool_range" "256")
3845    (set_attr "neg_pool_range" "244")]
3846 )
3847
3848 (define_expand "extendqisi2"
3849   [(set (match_dup 2)
3850         (ashift:SI (match_operand:QI 1 "general_operand" "")
3851                    (const_int 24)))
3852    (set (match_operand:SI 0 "s_register_operand" "")
3853         (ashiftrt:SI (match_dup 2)
3854                      (const_int 24)))]
3855   "TARGET_EITHER"
3856   "
3857   {
3858     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3859       {
3860         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3861                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3862         DONE;
3863       }
3864
3865     if (!s_register_operand (operands[1], QImode))
3866       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3867
3868     if (arm_arch6)
3869       {
3870         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3871                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3872         DONE;
3873       }
3874
3875     operands[1] = gen_lowpart (SImode, operands[1]);
3876     operands[2] = gen_reg_rtx (SImode);
3877   }"
3878 )
3879
3880 (define_insn "*arm_extendqisi"
3881   [(set (match_operand:SI 0 "s_register_operand" "=r")
3882         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3883   "TARGET_ARM && arm_arch4 && !arm_arch6"
3884   "ldr%?sb\\t%0, %1"
3885   [(set_attr "type" "load_byte")
3886    (set_attr "predicable" "yes")
3887    (set_attr "pool_range" "256")
3888    (set_attr "neg_pool_range" "244")]
3889 )
3890
3891 (define_insn "*arm_extendqisi_v6"
3892   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3893         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3894   "TARGET_ARM && arm_arch6"
3895   "@
3896    sxtb%?\\t%0, %1
3897    ldr%?sb\\t%0, %1"
3898   [(set_attr "type" "alu_shift,load_byte")
3899    (set_attr "predicable" "yes")
3900    (set_attr "pool_range" "*,256")
3901    (set_attr "neg_pool_range" "*,244")]
3902 )
3903
3904 (define_insn "*arm_extendqisi2addsi"
3905   [(set (match_operand:SI 0 "s_register_operand" "=r")
3906         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3907                  (match_operand:SI 2 "s_register_operand" "r")))]
3908   "TARGET_ARM && arm_arch6"
3909   "sxtab%?\\t%0, %2, %1"
3910   [(set_attr "type" "alu_shift")
3911    (set_attr "predicable" "yes")]
3912 )
3913
3914 (define_insn "*thumb_extendqisi2"
3915   [(set (match_operand:SI 0 "register_operand" "=l,l")
3916         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3917   "TARGET_THUMB && !arm_arch6"
3918   "*
3919   {
3920     rtx ops[3];
3921     rtx mem = XEXP (operands[1], 0);
3922     
3923     if (GET_CODE (mem) == CONST)
3924       mem = XEXP (mem, 0);
3925     
3926     if (GET_CODE (mem) == LABEL_REF)
3927       return \"ldr\\t%0, %1\";
3928
3929     if (GET_CODE (mem) == PLUS
3930         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3931       return \"ldr\\t%0, %1\";
3932       
3933     if (which_alternative == 0)
3934       return \"ldrsb\\t%0, %1\";
3935       
3936     ops[0] = operands[0];
3937     
3938     if (GET_CODE (mem) == PLUS)
3939       {
3940         rtx a = XEXP (mem, 0);
3941         rtx b = XEXP (mem, 1);
3942         
3943         ops[1] = a;
3944         ops[2] = b;
3945
3946         if (GET_CODE (a) == REG)
3947           {
3948             if (GET_CODE (b) == REG)
3949               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3950             else if (REGNO (a) == REGNO (ops[0]))
3951               {
3952                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3953                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3954                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3955               }
3956             else
3957               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3958           }
3959         else if (GET_CODE (b) != REG)
3960           abort ();
3961         else
3962           {
3963             if (REGNO (b) == REGNO (ops[0]))
3964               {
3965                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3966                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3967                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3968               }
3969             else
3970               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3971           }
3972       }
3973     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3974       {
3975         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3976         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3977         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3978       }
3979     else
3980       {
3981         ops[1] = mem;
3982         ops[2] = const0_rtx;
3983         
3984         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3985       }
3986     return \"\";
3987   }"
3988   [(set_attr "length" "2,6")
3989    (set_attr "type" "load_byte,load_byte")
3990    (set_attr "pool_range" "32,32")]
3991 )
3992
3993 (define_insn "*thumb_extendqisi2_v6"
3994   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3995         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3996   "TARGET_THUMB && arm_arch6"
3997   "*
3998   {
3999     rtx ops[3];
4000     rtx mem;
4001
4002     if (which_alternative == 0)
4003       return \"sxtb\\t%0, %1\";
4004
4005     mem = XEXP (operands[1], 0);
4006     
4007     if (GET_CODE (mem) == CONST)
4008       mem = XEXP (mem, 0);
4009     
4010     if (GET_CODE (mem) == LABEL_REF)
4011       return \"ldr\\t%0, %1\";
4012
4013     if (GET_CODE (mem) == PLUS
4014         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4015       return \"ldr\\t%0, %1\";
4016       
4017     if (which_alternative == 0)
4018       return \"ldrsb\\t%0, %1\";
4019       
4020     ops[0] = operands[0];
4021     
4022     if (GET_CODE (mem) == PLUS)
4023       {
4024         rtx a = XEXP (mem, 0);
4025         rtx b = XEXP (mem, 1);
4026         
4027         ops[1] = a;
4028         ops[2] = b;
4029
4030         if (GET_CODE (a) == REG)
4031           {
4032             if (GET_CODE (b) == REG)
4033               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4034             else if (REGNO (a) == REGNO (ops[0]))
4035               {
4036                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4037                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4038               }
4039             else
4040               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4041           }
4042         else if (GET_CODE (b) != REG)
4043           abort ();
4044         else
4045           {
4046             if (REGNO (b) == REGNO (ops[0]))
4047               {
4048                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4049                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4050               }
4051             else
4052               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4053           }
4054       }
4055     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4056       {
4057         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4058         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4059       }
4060     else
4061       {
4062         ops[1] = mem;
4063         ops[2] = const0_rtx;
4064         
4065         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4066       }
4067     return \"\";
4068   }"
4069   [(set_attr "length" "2,2,4")
4070    (set_attr "type" "alu_shift,load_byte,load_byte")
4071    (set_attr "pool_range" "*,32,32")]
4072 )
4073
4074 (define_expand "extendsfdf2"
4075   [(set (match_operand:DF                  0 "s_register_operand" "")
4076         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4077   "TARGET_ARM && TARGET_HARD_FLOAT"
4078   ""
4079 )
4080 \f
4081 ;; Move insns (including loads and stores)
4082
4083 ;; XXX Just some ideas about movti.
4084 ;; I don't think these are a good idea on the arm, there just aren't enough
4085 ;; registers
4086 ;;(define_expand "loadti"
4087 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4088 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4089 ;;  "" "")
4090
4091 ;;(define_expand "storeti"
4092 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4093 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4094 ;;  "" "")
4095
4096 ;;(define_expand "movti"
4097 ;;  [(set (match_operand:TI 0 "general_operand" "")
4098 ;;      (match_operand:TI 1 "general_operand" ""))]
4099 ;;  ""
4100 ;;  "
4101 ;;{
4102 ;;  rtx insn;
4103 ;;
4104 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4105 ;;    operands[1] = copy_to_reg (operands[1]);
4106 ;;  if (GET_CODE (operands[0]) == MEM)
4107 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4108 ;;  else if (GET_CODE (operands[1]) == MEM)
4109 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4110 ;;  else
4111 ;;    FAIL;
4112 ;;
4113 ;;  emit_insn (insn);
4114 ;;  DONE;
4115 ;;}")
4116
4117 ;; Recognize garbage generated above.
4118
4119 ;;(define_insn ""
4120 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4121 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4122 ;;  ""
4123 ;;  "*
4124 ;;  {
4125 ;;    register mem = (which_alternative < 3);
4126 ;;    register const char *template;
4127 ;;
4128 ;;    operands[mem] = XEXP (operands[mem], 0);
4129 ;;    switch (which_alternative)
4130 ;;      {
4131 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4132 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4133 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4134 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4135 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4136 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4137 ;;      }
4138 ;;    output_asm_insn (template, operands);
4139 ;;    return \"\";
4140 ;;  }")
4141
4142 (define_expand "movdi"
4143   [(set (match_operand:DI 0 "general_operand" "")
4144         (match_operand:DI 1 "general_operand" ""))]
4145   "TARGET_EITHER"
4146   "
4147   if (TARGET_THUMB)
4148     {
4149       if (!no_new_pseudos)
4150         {
4151           if (GET_CODE (operands[0]) != REG)
4152             operands[1] = force_reg (DImode, operands[1]);
4153         }
4154     }
4155   "
4156 )
4157
4158 (define_insn "*arm_movdi"
4159   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
4160         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
4161   "TARGET_ARM
4162   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4163   && !TARGET_IWMMXT"
4164   "*
4165   return (output_move_double (operands));
4166   "
4167   [(set_attr "length" "8")
4168    (set_attr "type" "*,load2,store2")
4169    (set_attr "pool_range" "*,1020,*")
4170    (set_attr "neg_pool_range" "*,1008,*")]
4171 )
4172
4173 ;; We can't actually do base+index doubleword loads if the index and
4174 ;; destination overlap.  Split here so that we at least have chance to
4175 ;; schedule.
4176 (define_split
4177   [(set (match_operand:DI 0 "s_register_operand" "")
4178         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4179                          (match_operand:SI 2 "s_register_operand" ""))))]
4180   "TARGET_LDRD
4181   && reg_overlap_mentioned_p (operands[0], operands[1])
4182   && reg_overlap_mentioned_p (operands[0], operands[2])"
4183   [(set (match_dup 4)
4184         (plus:SI (match_dup 1)
4185                  (match_dup 2)))
4186    (set (match_dup 0)
4187         (mem:DI (match_dup 4)))]
4188   "
4189   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4190   "
4191 )
4192
4193 ;;; ??? This should have alternatives for constants.
4194 ;;; ??? This was originally identical to the movdf_insn pattern.
4195 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4196 ;;; thumb_reorg with a memory reference.
4197 (define_insn "*thumb_movdi_insn"
4198   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4199         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4200   "TARGET_THUMB
4201    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4202    && (   register_operand (operands[0], DImode)
4203        || register_operand (operands[1], DImode))"
4204   "*
4205   {
4206   switch (which_alternative)
4207     {
4208     default:
4209     case 0:
4210       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4211         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4212       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4213     case 1:
4214       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4215     case 2:
4216       operands[1] = GEN_INT (- INTVAL (operands[1]));
4217       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4218     case 3:
4219       return \"ldmia\\t%1, {%0, %H0}\";
4220     case 4:
4221       return \"stmia\\t%0, {%1, %H1}\";
4222     case 5:
4223       return thumb_load_double_from_address (operands);
4224     case 6:
4225       operands[2] = gen_rtx_MEM (SImode,
4226                              plus_constant (XEXP (operands[0], 0), 4));
4227       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4228       return \"\";
4229     case 7:
4230       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4231         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4232       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4233     }
4234   }"
4235   [(set_attr "length" "4,4,6,2,2,6,4,4")
4236    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4237    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4238 )
4239
4240 (define_expand "movsi"
4241   [(set (match_operand:SI 0 "general_operand" "")
4242         (match_operand:SI 1 "general_operand" ""))]
4243   "TARGET_EITHER"
4244   "
4245   if (TARGET_ARM)
4246     {
4247       /* Everything except mem = const or mem = mem can be done easily.  */
4248       if (GET_CODE (operands[0]) == MEM)
4249         operands[1] = force_reg (SImode, operands[1]);
4250       if (arm_general_register_operand (operands[0], SImode)
4251           && GET_CODE (operands[1]) == CONST_INT
4252           && !(const_ok_for_arm (INTVAL (operands[1]))
4253                || const_ok_for_arm (~INTVAL (operands[1]))))
4254         {
4255            arm_split_constant (SET, SImode, NULL_RTX,
4256                                INTVAL (operands[1]), operands[0], NULL_RTX,
4257                                optimize && !no_new_pseudos);
4258           DONE;
4259         }
4260     }
4261   else /* TARGET_THUMB....  */
4262     {
4263       if (!no_new_pseudos)
4264         {
4265           if (GET_CODE (operands[0]) != REG)
4266             operands[1] = force_reg (SImode, operands[1]);
4267         }
4268     }
4269     
4270   if (flag_pic
4271       && (CONSTANT_P (operands[1])
4272          || symbol_mentioned_p (operands[1])
4273          || label_mentioned_p (operands[1])))
4274     operands[1] = legitimize_pic_address (operands[1], SImode,
4275                                           (no_new_pseudos ? operands[0] : 0));
4276   "
4277 )
4278
4279 (define_insn "*arm_movsi_insn"
4280   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4281         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4282   "TARGET_ARM && ! TARGET_IWMMXT
4283    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4284    && (   register_operand (operands[0], SImode)
4285        || register_operand (operands[1], SImode))"
4286   "@
4287    mov%?\\t%0, %1
4288    mvn%?\\t%0, #%B1
4289    ldr%?\\t%0, %1
4290    str%?\\t%1, %0"
4291   [(set_attr "type" "*,*,load1,store1")
4292    (set_attr "predicable" "yes")
4293    (set_attr "pool_range" "*,*,4096,*")
4294    (set_attr "neg_pool_range" "*,*,4084,*")]
4295 )
4296
4297 (define_split
4298   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4299         (match_operand:SI 1 "const_int_operand" ""))]
4300   "TARGET_ARM
4301   && (!(const_ok_for_arm (INTVAL (operands[1]))
4302         || const_ok_for_arm (~INTVAL (operands[1]))))"
4303   [(clobber (const_int 0))]
4304   "
4305   arm_split_constant (SET, SImode, NULL_RTX, 
4306                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4307   DONE;
4308   "
4309 )
4310
4311 (define_insn "*thumb_movsi_insn"
4312   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4313         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4314   "TARGET_THUMB
4315    && (   register_operand (operands[0], SImode) 
4316        || register_operand (operands[1], SImode))"
4317   "@
4318    mov  %0, %1
4319    mov  %0, %1
4320    #
4321    #
4322    ldmia\\t%1, {%0}
4323    stmia\\t%0, {%1}
4324    ldr\\t%0, %1
4325    str\\t%1, %0
4326    mov\\t%0, %1"
4327   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4328    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4329    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4330 )
4331
4332 (define_split 
4333   [(set (match_operand:SI 0 "register_operand" "")
4334         (match_operand:SI 1 "const_int_operand" ""))]
4335   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4336   [(set (match_dup 0) (match_dup 1))
4337    (set (match_dup 0) (neg:SI (match_dup 0)))]
4338   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4339 )
4340
4341 (define_split 
4342   [(set (match_operand:SI 0 "register_operand" "")
4343         (match_operand:SI 1 "const_int_operand" ""))]
4344   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4345   [(set (match_dup 0) (match_dup 1))
4346    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4347   "
4348   {
4349     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4350     unsigned HOST_WIDE_INT mask = 0xff;
4351     int i;
4352     
4353     for (i = 0; i < 25; i++)
4354       if ((val & (mask << i)) == val)
4355         break;
4356
4357     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4358     if (i == 0)
4359       FAIL;
4360
4361     operands[1] = GEN_INT (val >> i);
4362     operands[2] = GEN_INT (i);
4363   }"
4364 )
4365
4366 ;; When generating pic, we need to load the symbol offset into a register.
4367 ;; So that the optimizer does not confuse this with a normal symbol load
4368 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4369 ;; since that is the only type of relocation we can use.
4370
4371 ;; The rather odd constraints on the following are to force reload to leave
4372 ;; the insn alone, and to force the minipool generation pass to then move
4373 ;; the GOT symbol to memory.
4374
4375 (define_insn "pic_load_addr_arm"
4376   [(set (match_operand:SI 0 "s_register_operand" "=r")
4377         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4378   "TARGET_ARM && flag_pic"
4379   "ldr%?\\t%0, %1"
4380   [(set_attr "type" "load1")
4381    (set (attr "pool_range")     (const_int 4096))
4382    (set (attr "neg_pool_range") (const_int 4084))]
4383 )
4384
4385 (define_insn "pic_load_addr_thumb"
4386   [(set (match_operand:SI 0 "s_register_operand" "=l")
4387         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4388   "TARGET_THUMB && flag_pic"
4389   "ldr\\t%0, %1"
4390   [(set_attr "type" "load1")
4391    (set (attr "pool_range") (const_int 1024))]
4392 )
4393
4394 ;; This variant is used for AOF assembly, since it needs to mention the
4395 ;; pic register in the rtl.
4396 (define_expand "pic_load_addr_based"
4397   [(set (match_operand:SI 0 "s_register_operand" "")
4398         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4399   "TARGET_ARM && flag_pic"
4400   "operands[2] = pic_offset_table_rtx;"
4401 )
4402
4403 (define_insn "*pic_load_addr_based_insn"
4404   [(set (match_operand:SI 0 "s_register_operand" "=r")
4405         (unspec:SI [(match_operand 1 "" "")
4406                     (match_operand 2 "s_register_operand" "r")]
4407                    UNSPEC_PIC_SYM))]
4408   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4409   "*
4410 #ifdef AOF_ASSEMBLER
4411   operands[1] = aof_pic_entry (operands[1]);
4412 #endif
4413   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4414   return \"\";
4415   "
4416   [(set_attr "type" "load1")
4417    (set (attr "pool_range")
4418         (if_then_else (eq_attr "is_thumb" "yes")
4419                       (const_int 1024)
4420                       (const_int 4096)))
4421    (set (attr "neg_pool_range")
4422         (if_then_else (eq_attr "is_thumb" "yes")
4423                       (const_int 0)
4424                       (const_int 4084)))]
4425 )
4426
4427 (define_insn "pic_add_dot_plus_four"
4428   [(set (match_operand:SI 0 "register_operand" "+r")
4429         (unspec:SI [(plus:SI (match_dup 0)
4430                              (const (plus:SI (pc) (const_int 4))))]
4431                    UNSPEC_PIC_BASE))
4432    (use (label_ref (match_operand 1 "" "")))]
4433   "TARGET_THUMB && flag_pic"
4434   "*
4435   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4436                              CODE_LABEL_NUMBER (operands[1]));
4437   return \"add\\t%0, %|pc\";
4438   "
4439   [(set_attr "length" "2")]
4440 )
4441
4442 (define_insn "pic_add_dot_plus_eight"
4443   [(set (match_operand:SI 0 "register_operand" "+r")
4444         (unspec:SI [(plus:SI (match_dup 0)
4445                              (const (plus:SI (pc) (const_int 8))))]
4446                    UNSPEC_PIC_BASE))
4447    (use (label_ref (match_operand 1 "" "")))]
4448   "TARGET_ARM && flag_pic"
4449   "*
4450     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4451                                CODE_LABEL_NUMBER (operands[1]));
4452     return \"add%?\\t%0, %|pc, %0\";
4453   "
4454   [(set_attr "predicable" "yes")]
4455 )
4456
4457 (define_expand "builtin_setjmp_receiver"
4458   [(label_ref (match_operand 0 "" ""))]
4459   "flag_pic"
4460   "
4461 {
4462   arm_load_pic_register ();
4463   DONE;
4464 }")
4465
4466 ;; If copying one reg to another we can set the condition codes according to
4467 ;; its value.  Such a move is common after a return from subroutine and the
4468 ;; result is being tested against zero.
4469
4470 (define_insn "*movsi_compare0"
4471   [(set (reg:CC CC_REGNUM)
4472         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4473                     (const_int 0)))
4474    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4475         (match_dup 1))]
4476   "TARGET_ARM"
4477   "@
4478    cmp%?\\t%0, #0
4479    sub%?s\\t%0, %1, #0"
4480   [(set_attr "conds" "set")]
4481 )
4482
4483 ;; Subroutine to store a half word from a register into memory.
4484 ;; Operand 0 is the source register (HImode)
4485 ;; Operand 1 is the destination address in a register (SImode)
4486
4487 ;; In both this routine and the next, we must be careful not to spill
4488 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4489 ;; can generate unrecognizable rtl.
4490
4491 (define_expand "storehi"
4492   [;; store the low byte
4493    (set (match_operand 1 "" "") (match_dup 3))
4494    ;; extract the high byte
4495    (set (match_dup 2)
4496         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4497    ;; store the high byte
4498    (set (match_dup 4) (match_dup 5))]
4499   "TARGET_ARM"
4500   "
4501   {
4502     rtx op1 = operands[1];
4503     rtx addr = XEXP (op1, 0);
4504     enum rtx_code code = GET_CODE (addr);
4505
4506     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4507         || code == MINUS)
4508       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4509
4510     operands[4] = adjust_address (op1, QImode, 1);
4511     operands[1] = adjust_address (operands[1], QImode, 0);
4512     operands[3] = gen_lowpart (QImode, operands[0]);
4513     operands[0] = gen_lowpart (SImode, operands[0]);
4514     operands[2] = gen_reg_rtx (SImode);
4515     operands[5] = gen_lowpart (QImode, operands[2]);
4516   }"
4517 )
4518
4519 (define_expand "storehi_bigend"
4520   [(set (match_dup 4) (match_dup 3))
4521    (set (match_dup 2)
4522         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4523    (set (match_operand 1 "" "") (match_dup 5))]
4524   "TARGET_ARM"
4525   "
4526   {
4527     rtx op1 = operands[1];
4528     rtx addr = XEXP (op1, 0);
4529     enum rtx_code code = GET_CODE (addr);
4530
4531     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4532         || code == MINUS)
4533       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4534
4535     operands[4] = adjust_address (op1, QImode, 1);
4536     operands[1] = adjust_address (operands[1], QImode, 0);
4537     operands[3] = gen_lowpart (QImode, operands[0]);
4538     operands[0] = gen_lowpart (SImode, operands[0]);
4539     operands[2] = gen_reg_rtx (SImode);
4540     operands[5] = gen_lowpart (QImode, operands[2]);
4541   }"
4542 )
4543
4544 ;; Subroutine to store a half word integer constant into memory.
4545 (define_expand "storeinthi"
4546   [(set (match_operand 0 "" "")
4547         (match_operand 1 "" ""))
4548    (set (match_dup 3) (match_dup 2))]
4549   "TARGET_ARM"
4550   "
4551   {
4552     HOST_WIDE_INT value = INTVAL (operands[1]);
4553     rtx addr = XEXP (operands[0], 0);
4554     rtx op0 = operands[0];
4555     enum rtx_code code = GET_CODE (addr);
4556
4557     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4558         || code == MINUS)
4559       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4560
4561     operands[1] = gen_reg_rtx (SImode);
4562     if (BYTES_BIG_ENDIAN)
4563       {
4564         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4565         if ((value & 255) == ((value >> 8) & 255))
4566           operands[2] = operands[1];
4567         else
4568           {
4569             operands[2] = gen_reg_rtx (SImode);
4570             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4571           }
4572       }
4573     else
4574       {
4575         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4576         if ((value & 255) == ((value >> 8) & 255))
4577           operands[2] = operands[1];
4578         else
4579           {
4580             operands[2] = gen_reg_rtx (SImode);
4581             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4582           }
4583       }
4584
4585     operands[3] = adjust_address (op0, QImode, 1);
4586     operands[0] = adjust_address (operands[0], QImode, 0);
4587     operands[2] = gen_lowpart (QImode, operands[2]);
4588     operands[1] = gen_lowpart (QImode, operands[1]);
4589   }"
4590 )
4591
4592 (define_expand "storehi_single_op"
4593   [(set (match_operand:HI 0 "memory_operand" "")
4594         (match_operand:HI 1 "general_operand" ""))]
4595   "TARGET_ARM && arm_arch4"
4596   "
4597   if (!s_register_operand (operands[1], HImode))
4598     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4599   "
4600 )
4601
4602 (define_expand "movhi"
4603   [(set (match_operand:HI 0 "general_operand" "")
4604         (match_operand:HI 1 "general_operand" ""))]
4605   "TARGET_EITHER"
4606   "
4607   if (TARGET_ARM)
4608     {
4609       if (!no_new_pseudos)
4610         {
4611           if (GET_CODE (operands[0]) == MEM)
4612             {
4613               if (arm_arch4)
4614                 {
4615                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4616                   DONE;
4617                 }
4618               if (GET_CODE (operands[1]) == CONST_INT)
4619                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4620               else
4621                 {
4622                   if (GET_CODE (operands[1]) == MEM)
4623                     operands[1] = force_reg (HImode, operands[1]);
4624                   if (BYTES_BIG_ENDIAN)
4625                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4626                   else
4627                    emit_insn (gen_storehi (operands[1], operands[0]));
4628                 }
4629               DONE;
4630             }
4631           /* Sign extend a constant, and keep it in an SImode reg.  */
4632           else if (GET_CODE (operands[1]) == CONST_INT)
4633             {
4634               rtx reg = gen_reg_rtx (SImode);
4635               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4636
4637               /* If the constant is already valid, leave it alone.  */
4638               if (!const_ok_for_arm (val))
4639                 {
4640                   /* If setting all the top bits will make the constant 
4641                      loadable in a single instruction, then set them.  
4642                      Otherwise, sign extend the number.  */
4643
4644                   if (const_ok_for_arm (~(val | ~0xffff)))
4645                     val |= ~0xffff;
4646                   else if (val & 0x8000)
4647                     val |= ~0xffff;
4648                 }
4649
4650               emit_insn (gen_movsi (reg, GEN_INT (val)));
4651               operands[1] = gen_lowpart (HImode, reg);
4652             }
4653           else if (arm_arch4 && optimize && !no_new_pseudos
4654                    && GET_CODE (operands[1]) == MEM)
4655             {
4656               rtx reg = gen_reg_rtx (SImode);
4657
4658               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4659               operands[1] = gen_lowpart (HImode, reg);
4660             }
4661           else if (!arm_arch4)
4662             {
4663               if (GET_CODE (operands[1]) == MEM)
4664                 {
4665                   rtx base;
4666                   rtx offset = const0_rtx;
4667                   rtx reg = gen_reg_rtx (SImode);
4668
4669                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4670                        || (GET_CODE (base) == PLUS
4671                            && (GET_CODE (offset = XEXP (base, 1))
4672                                == CONST_INT)
4673                            && ((INTVAL(offset) & 1) != 1)
4674                            && GET_CODE (base = XEXP (base, 0)) == REG))
4675                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4676                     {
4677                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4678                       rtx new;
4679
4680                       new = gen_rtx_MEM (SImode,
4681                                          plus_constant (base, new_offset));
4682                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4683                       emit_insn (gen_movsi (reg, new));
4684                       if (((INTVAL (offset) & 2) != 0)
4685                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4686                         {
4687                           rtx reg2 = gen_reg_rtx (SImode);
4688
4689                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4690                           reg = reg2;
4691                         }
4692                     }
4693                   else
4694                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4695
4696                   operands[1] = gen_lowpart (HImode, reg);
4697                }
4698            }
4699         }
4700       /* Handle loading a large integer during reload.  */
4701       else if (GET_CODE (operands[1]) == CONST_INT
4702                && !const_ok_for_arm (INTVAL (operands[1]))
4703                && !const_ok_for_arm (~INTVAL (operands[1])))
4704         {
4705           /* Writing a constant to memory needs a scratch, which should
4706              be handled with SECONDARY_RELOADs.  */
4707           if (GET_CODE (operands[0]) != REG)
4708             abort ();
4709
4710           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4711           emit_insn (gen_movsi (operands[0], operands[1]));
4712           DONE;
4713        }
4714     }
4715   else /* TARGET_THUMB */
4716     {
4717       if (!no_new_pseudos)
4718         {
4719           if (GET_CODE (operands[0]) != REG)
4720             operands[1] = force_reg (HImode, operands[1]);
4721
4722           /* ??? We shouldn't really get invalid addresses here, but this can
4723              happen if we are passed a SP (never OK for HImode/QImode) or 
4724              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4725              HImode/QImode) relative address.  */
4726           /* ??? This should perhaps be fixed elsewhere, for instance, in
4727              fixup_stack_1, by checking for other kinds of invalid addresses,
4728              e.g. a bare reference to a virtual register.  This may confuse the
4729              alpha though, which must handle this case differently.  */
4730           if (GET_CODE (operands[0]) == MEM
4731               && !memory_address_p (GET_MODE (operands[0]),
4732                                     XEXP (operands[0], 0)))
4733             operands[0]
4734               = replace_equiv_address (operands[0],
4735                                        copy_to_reg (XEXP (operands[0], 0)));
4736    
4737           if (GET_CODE (operands[1]) == MEM
4738               && !memory_address_p (GET_MODE (operands[1]),
4739                                     XEXP (operands[1], 0)))
4740             operands[1]
4741               = replace_equiv_address (operands[1],
4742                                        copy_to_reg (XEXP (operands[1], 0)));
4743         }
4744       /* Handle loading a large integer during reload.  */
4745       else if (GET_CODE (operands[1]) == CONST_INT
4746                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4747         {
4748           /* Writing a constant to memory needs a scratch, which should
4749              be handled with SECONDARY_RELOADs.  */
4750           if (GET_CODE (operands[0]) != REG)
4751             abort ();
4752
4753           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4754           emit_insn (gen_movsi (operands[0], operands[1]));
4755           DONE;
4756         }
4757     }
4758   "
4759 )
4760
4761 (define_insn "*thumb_movhi_insn"
4762   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4763         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4764   "TARGET_THUMB
4765    && (   register_operand (operands[0], HImode)
4766        || register_operand (operands[1], HImode))"
4767   "*
4768   switch (which_alternative)
4769     {
4770     case 0: return \"add        %0, %1, #0\";
4771     case 2: return \"strh       %1, %0\";
4772     case 3: return \"mov        %0, %1\";
4773     case 4: return \"mov        %0, %1\";
4774     case 5: return \"mov        %0, %1\";
4775     default: abort ();
4776     case 1:
4777       /* The stack pointer can end up being taken as an index register.
4778           Catch this case here and deal with it.  */
4779       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4780           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4781           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4782         {
4783           rtx ops[2];
4784           ops[0] = operands[0];
4785           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4786       
4787           output_asm_insn (\"mov        %0, %1\", ops);
4788
4789           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4790     
4791         }
4792       return \"ldrh     %0, %1\";
4793     }"
4794   [(set_attr "length" "2,4,2,2,2,2")
4795    (set_attr "type" "*,load1,store1,*,*,*")]
4796 )
4797
4798
4799 (define_expand "movhi_bytes"
4800   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4801    (set (match_dup 3)
4802         (zero_extend:SI (match_dup 6)))
4803    (set (match_operand:SI 0 "" "")
4804          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4805   "TARGET_ARM"
4806   "
4807   {
4808     rtx mem1, mem2;
4809     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4810
4811     mem1 = gen_rtx_MEM (QImode, addr);
4812     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4813     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4814     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4815     operands[0] = gen_lowpart (SImode, operands[0]);
4816     operands[1] = mem1;
4817     operands[2] = gen_reg_rtx (SImode);
4818     operands[3] = gen_reg_rtx (SImode);
4819     operands[6] = mem2;
4820
4821     if (BYTES_BIG_ENDIAN)
4822       {
4823         operands[4] = operands[2];
4824         operands[5] = operands[3];
4825       }
4826     else
4827       {
4828         operands[4] = operands[3];
4829         operands[5] = operands[2];
4830       }
4831   }"
4832 )
4833
4834 (define_expand "movhi_bigend"
4835   [(set (match_dup 2)
4836         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4837                    (const_int 16)))
4838    (set (match_dup 3)
4839         (ashiftrt:SI (match_dup 2) (const_int 16)))
4840    (set (match_operand:HI 0 "s_register_operand" "")
4841         (match_dup 4))]
4842   "TARGET_ARM"
4843   "
4844   operands[2] = gen_reg_rtx (SImode);
4845   operands[3] = gen_reg_rtx (SImode);
4846   operands[4] = gen_lowpart (HImode, operands[3]);
4847   "
4848 )
4849
4850 ;; Pattern to recognize insn generated default case above
4851 (define_insn "*movhi_insn_arch4"
4852   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4853         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4854   "TARGET_ARM
4855    && arm_arch4
4856    && (GET_CODE (operands[1]) != CONST_INT
4857        || const_ok_for_arm (INTVAL (operands[1]))
4858        || const_ok_for_arm (~INTVAL (operands[1])))"
4859   "@
4860    mov%?\\t%0, %1\\t%@ movhi
4861    mvn%?\\t%0, #%B1\\t%@ movhi
4862    str%?h\\t%1, %0\\t%@ movhi 
4863    ldr%?h\\t%0, %1\\t%@ movhi"
4864   [(set_attr "type" "*,*,store1,load1")
4865    (set_attr "predicable" "yes")
4866    (set_attr "pool_range" "*,*,*,256")
4867    (set_attr "neg_pool_range" "*,*,*,244")]
4868 )
4869
4870 (define_insn "*movhi_bytes"
4871   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4872         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4873   "TARGET_ARM"
4874   "@
4875    mov%?\\t%0, %1\\t%@ movhi
4876    mvn%?\\t%0, #%B1\\t%@ movhi"
4877   [(set_attr "predicable" "yes")]
4878 )
4879
4880 (define_insn "thumb_movhi_clobber"
4881   [(set (match_operand:HI     0 "memory_operand"   "=m")
4882         (match_operand:HI     1 "register_operand" "l"))
4883    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4884   "TARGET_THUMB"
4885   "*
4886   abort ();"
4887 )
4888         
4889 ;; We use a DImode scratch because we may occasionally need an additional
4890 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4891 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4892 (define_expand "reload_outhi"
4893   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4894               (match_operand:HI 1 "s_register_operand"        "r")
4895               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4896   "TARGET_EITHER"
4897   "if (TARGET_ARM)
4898      arm_reload_out_hi (operands);
4899    else
4900      thumb_reload_out_hi (operands);
4901   DONE;
4902   "
4903 )
4904
4905 (define_expand "reload_inhi"
4906   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4907               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4908               (match_operand:DI 2 "s_register_operand" "=&r")])]
4909   "TARGET_EITHER"
4910   "
4911   if (TARGET_ARM)
4912     arm_reload_in_hi (operands);
4913   else
4914     thumb_reload_out_hi (operands);
4915   DONE;
4916 ")
4917
4918 (define_expand "movqi"
4919   [(set (match_operand:QI 0 "general_operand" "")
4920         (match_operand:QI 1 "general_operand" ""))]
4921   "TARGET_EITHER"
4922   "
4923   if (TARGET_ARM)
4924     {
4925       /* Everything except mem = const or mem = mem can be done easily */
4926
4927       if (!no_new_pseudos)
4928         {
4929           if (GET_CODE (operands[1]) == CONST_INT)
4930             {
4931               rtx reg = gen_reg_rtx (SImode);
4932
4933               emit_insn (gen_movsi (reg, operands[1]));
4934               operands[1] = gen_lowpart (QImode, reg);
4935             }
4936           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4937             {
4938               rtx reg = gen_reg_rtx (SImode);
4939
4940               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4941               operands[1] = gen_lowpart (QImode, reg);
4942             }
4943           if (GET_CODE (operands[0]) == MEM)
4944             operands[1] = force_reg (QImode, operands[1]);
4945         }
4946     }
4947   else /* TARGET_THUMB */
4948     {
4949       if (!no_new_pseudos)
4950         {
4951           if (GET_CODE (operands[0]) != REG)
4952             operands[1] = force_reg (QImode, operands[1]);
4953
4954           /* ??? We shouldn't really get invalid addresses here, but this can
4955              happen if we are passed a SP (never OK for HImode/QImode) or
4956              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4957              HImode/QImode) relative address.  */
4958           /* ??? This should perhaps be fixed elsewhere, for instance, in
4959              fixup_stack_1, by checking for other kinds of invalid addresses,
4960              e.g. a bare reference to a virtual register.  This may confuse the
4961              alpha though, which must handle this case differently.  */
4962           if (GET_CODE (operands[0]) == MEM
4963               && !memory_address_p (GET_MODE (operands[0]),
4964                                      XEXP (operands[0], 0)))
4965             operands[0]
4966               = replace_equiv_address (operands[0],
4967                                        copy_to_reg (XEXP (operands[0], 0)));
4968           if (GET_CODE (operands[1]) == MEM
4969               && !memory_address_p (GET_MODE (operands[1]),
4970                                     XEXP (operands[1], 0)))
4971              operands[1]
4972                = replace_equiv_address (operands[1],
4973                                         copy_to_reg (XEXP (operands[1], 0)));
4974         }
4975       /* Handle loading a large integer during reload.  */
4976       else if (GET_CODE (operands[1]) == CONST_INT
4977                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4978         {
4979           /* Writing a constant to memory needs a scratch, which should
4980              be handled with SECONDARY_RELOADs.  */
4981           if (GET_CODE (operands[0]) != REG)
4982             abort ();
4983
4984           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4985           emit_insn (gen_movsi (operands[0], operands[1]));
4986           DONE;
4987        }
4988     }
4989   "
4990 )
4991
4992
4993 (define_insn "*arm_movqi_insn"
4994   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4995         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4996   "TARGET_ARM
4997    && (   register_operand (operands[0], QImode)
4998        || register_operand (operands[1], QImode))"
4999   "@
5000    mov%?\\t%0, %1
5001    mvn%?\\t%0, #%B1
5002    ldr%?b\\t%0, %1
5003    str%?b\\t%1, %0"
5004   [(set_attr "type" "*,*,load1,store1")
5005    (set_attr "predicable" "yes")]
5006 )
5007
5008 (define_insn "*thumb_movqi_insn"
5009   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5010         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5011   "TARGET_THUMB
5012    && (   register_operand (operands[0], QImode)
5013        || register_operand (operands[1], QImode))"
5014   "@
5015    add\\t%0, %1, #0
5016    ldrb\\t%0, %1
5017    strb\\t%1, %0
5018    mov\\t%0, %1
5019    mov\\t%0, %1
5020    mov\\t%0, %1"
5021   [(set_attr "length" "2")
5022    (set_attr "type" "*,load1,store1,*,*,*")
5023    (set_attr "pool_range" "*,32,*,*,*,*")]
5024 )
5025
5026 (define_expand "movsf"
5027   [(set (match_operand:SF 0 "general_operand" "")
5028         (match_operand:SF 1 "general_operand" ""))]
5029   "TARGET_EITHER"
5030   "
5031   if (TARGET_ARM)
5032     {
5033       if (GET_CODE (operands[0]) == MEM)
5034         operands[1] = force_reg (SFmode, operands[1]);
5035     }
5036   else /* TARGET_THUMB */
5037     {
5038       if (!no_new_pseudos)
5039         {
5040            if (GET_CODE (operands[0]) != REG)
5041              operands[1] = force_reg (SFmode, operands[1]);
5042         }
5043     }
5044   "
5045 )
5046
5047 (define_split
5048   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5049         (match_operand:SF 1 "immediate_operand" ""))]
5050   "TARGET_ARM
5051    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5052    && reload_completed
5053    && GET_CODE (operands[1]) == CONST_DOUBLE"
5054   [(set (match_dup 2) (match_dup 3))]
5055   "
5056   operands[2] = gen_lowpart (SImode, operands[0]);
5057   operands[3] = gen_lowpart (SImode, operands[1]);
5058   if (operands[2] == 0 || operands[3] == 0)
5059     FAIL;
5060   "
5061 )
5062
5063 (define_insn "*arm_movsf_soft_insn"
5064   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5065         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5066   "TARGET_ARM
5067    && TARGET_SOFT_FLOAT
5068    && (GET_CODE (operands[0]) != MEM
5069        || register_operand (operands[1], SFmode))"
5070   "@
5071    mov%?\\t%0, %1
5072    ldr%?\\t%0, %1\\t%@ float
5073    str%?\\t%1, %0\\t%@ float"
5074   [(set_attr "length" "4,4,4")
5075    (set_attr "predicable" "yes")
5076    (set_attr "type" "*,load1,store1")
5077    (set_attr "pool_range" "*,4096,*")
5078    (set_attr "neg_pool_range" "*,4084,*")]
5079 )
5080
5081 ;;; ??? This should have alternatives for constants.
5082 (define_insn "*thumb_movsf_insn"
5083   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5084         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5085   "TARGET_THUMB
5086    && (   register_operand (operands[0], SFmode) 
5087        || register_operand (operands[1], SFmode))"
5088   "@
5089    add\\t%0, %1, #0
5090    ldmia\\t%1, {%0}
5091    stmia\\t%0, {%1}
5092    ldr\\t%0, %1
5093    str\\t%1, %0
5094    mov\\t%0, %1
5095    mov\\t%0, %1"
5096   [(set_attr "length" "2")
5097    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5098    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5099 )
5100
5101 (define_expand "movdf"
5102   [(set (match_operand:DF 0 "general_operand" "")
5103         (match_operand:DF 1 "general_operand" ""))]
5104   "TARGET_EITHER"
5105   "
5106   if (TARGET_ARM)
5107     {
5108       if (GET_CODE (operands[0]) == MEM)
5109         operands[1] = force_reg (DFmode, operands[1]);
5110     }
5111   else /* TARGET_THUMB */
5112     {
5113       if (!no_new_pseudos)
5114         {
5115           if (GET_CODE (operands[0]) != REG)
5116             operands[1] = force_reg (DFmode, operands[1]);
5117         }
5118     }
5119   "
5120 )
5121
5122 ;; Reloading a df mode value stored in integer regs to memory can require a
5123 ;; scratch reg.
5124 (define_expand "reload_outdf"
5125   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5126    (match_operand:DF 1 "s_register_operand" "r")
5127    (match_operand:SI 2 "s_register_operand" "=&r")]
5128   "TARGET_ARM"
5129   "
5130   {
5131     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5132
5133     if (code == REG)
5134       operands[2] = XEXP (operands[0], 0);
5135     else if (code == POST_INC || code == PRE_DEC)
5136       {
5137         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5138         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5139         emit_insn (gen_movdi (operands[0], operands[1]));
5140         DONE;
5141       }
5142     else if (code == PRE_INC)
5143       {
5144         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5145
5146         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5147         operands[2] = reg;
5148       }
5149     else if (code == POST_DEC)
5150       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5151     else
5152       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5153                              XEXP (XEXP (operands[0], 0), 1)));
5154
5155     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5156                             operands[1]));
5157
5158     if (code == POST_DEC)
5159       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5160
5161     DONE;
5162   }"
5163 )
5164
5165 (define_insn "*movdf_soft_insn"
5166   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5167         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5168   "TARGET_ARM && TARGET_SOFT_FLOAT
5169   "
5170   "* return output_move_double (operands);"
5171   [(set_attr "length" "8,8,8")
5172    (set_attr "type" "*,load2,store2")
5173    (set_attr "pool_range" "1020")
5174    (set_attr "neg_pool_range" "1008")]
5175 )
5176
5177 ;;; ??? This should have alternatives for constants.
5178 ;;; ??? This was originally identical to the movdi_insn pattern.
5179 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5180 ;;; thumb_reorg with a memory reference.
5181 (define_insn "*thumb_movdf_insn"
5182   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5183         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5184   "TARGET_THUMB
5185    && (   register_operand (operands[0], DFmode)
5186        || register_operand (operands[1], DFmode))"
5187   "*
5188   switch (which_alternative)
5189     {
5190     default:
5191     case 0:
5192       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5193         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5194       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5195     case 1:
5196       return \"ldmia\\t%1, {%0, %H0}\";
5197     case 2:
5198       return \"stmia\\t%0, {%1, %H1}\";
5199     case 3:
5200       return thumb_load_double_from_address (operands);
5201     case 4:
5202       operands[2] = gen_rtx_MEM (SImode,
5203                                  plus_constant (XEXP (operands[0], 0), 4));
5204       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5205       return \"\";
5206     case 5:
5207       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5208         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5209       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5210     }
5211   "
5212   [(set_attr "length" "4,2,2,6,4,4")
5213    (set_attr "type" "*,load2,store2,load2,store2,*")
5214    (set_attr "pool_range" "*,*,*,1020,*,*")]
5215 )
5216
5217 ;; Vector Moves
5218 (define_expand "movv2si"
5219   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5220         (match_operand:V2SI 1 "general_operand" ""))]
5221   "TARGET_REALLY_IWMMXT"
5222 {
5223 })
5224
5225 (define_expand "movv4hi"
5226   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5227         (match_operand:V4HI 1 "general_operand" ""))]
5228   "TARGET_REALLY_IWMMXT"
5229 {
5230 })
5231
5232 (define_expand "movv8qi"
5233   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5234         (match_operand:V8QI 1 "general_operand" ""))]
5235   "TARGET_REALLY_IWMMXT"
5236 {
5237 })
5238 \f
5239
5240 ;; load- and store-multiple insns
5241 ;; The arm can load/store any set of registers, provided that they are in
5242 ;; ascending order; but that is beyond GCC so stick with what it knows.
5243
5244 (define_expand "load_multiple"
5245   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5246                           (match_operand:SI 1 "" ""))
5247                      (use (match_operand:SI 2 "" ""))])]
5248   "TARGET_ARM"
5249 {
5250   HOST_WIDE_INT offset = 0;
5251
5252   /* Support only fixed point registers.  */
5253   if (GET_CODE (operands[2]) != CONST_INT
5254       || INTVAL (operands[2]) > 14
5255       || INTVAL (operands[2]) < 2
5256       || GET_CODE (operands[1]) != MEM
5257       || GET_CODE (operands[0]) != REG
5258       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5259       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5260     FAIL;
5261
5262   operands[3]
5263     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5264                              force_reg (SImode, XEXP (operands[1], 0)),
5265                              TRUE, FALSE, operands[1], &offset);
5266 })
5267
5268 ;; Load multiple with write-back
5269
5270 (define_insn "*ldmsi_postinc4"
5271   [(match_parallel 0 "load_multiple_operation"
5272     [(set (match_operand:SI 1 "s_register_operand" "=r")
5273           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5274                    (const_int 16)))
5275      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5276           (mem:SI (match_dup 2)))
5277      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5278           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5279      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5280           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5281      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5282           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5283   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5284   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5285   [(set_attr "type" "load4")
5286    (set_attr "predicable" "yes")]
5287 )
5288
5289 (define_insn "*ldmsi_postinc3"
5290   [(match_parallel 0 "load_multiple_operation"
5291     [(set (match_operand:SI 1 "s_register_operand" "=r")
5292           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5293                    (const_int 12)))
5294      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5295           (mem:SI (match_dup 2)))
5296      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5297           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5298      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5299           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5300   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5301   "ldm%?ia\\t%1!, {%3, %4, %5}"
5302   [(set_attr "type" "load3")
5303    (set_attr "predicable" "yes")]
5304 )
5305
5306 (define_insn "*ldmsi_postinc2"
5307   [(match_parallel 0 "load_multiple_operation"
5308     [(set (match_operand:SI 1 "s_register_operand" "=r")
5309           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5310                    (const_int 8)))
5311      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5312           (mem:SI (match_dup 2)))
5313      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5314           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5315   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5316   "ldm%?ia\\t%1!, {%3, %4}"
5317   [(set_attr "type" "load2")
5318    (set_attr "predicable" "yes")]
5319 )
5320
5321 ;; Ordinary load multiple
5322
5323 (define_insn "*ldmsi4"
5324   [(match_parallel 0 "load_multiple_operation"
5325     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5326           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5327      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5328           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5329      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5330           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5331      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5332           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5333   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5334   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5335   [(set_attr "type" "load4")
5336    (set_attr "predicable" "yes")]
5337 )
5338
5339 (define_insn "*ldmsi3"
5340   [(match_parallel 0 "load_multiple_operation"
5341     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5342           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5343      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5344           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5345      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5346           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5347   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5348   "ldm%?ia\\t%1, {%2, %3, %4}"
5349   [(set_attr "type" "load3")
5350    (set_attr "predicable" "yes")]
5351 )
5352
5353 (define_insn "*ldmsi2"
5354   [(match_parallel 0 "load_multiple_operation"
5355     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5356           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5357      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5358           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5359   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5360   "ldm%?ia\\t%1, {%2, %3}"
5361   [(set_attr "type" "load2")
5362    (set_attr "predicable" "yes")]
5363 )
5364
5365 (define_expand "store_multiple"
5366   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5367                           (match_operand:SI 1 "" ""))
5368                      (use (match_operand:SI 2 "" ""))])]
5369   "TARGET_ARM"
5370 {
5371   HOST_WIDE_INT offset = 0;
5372
5373   /* Support only fixed point registers.  */
5374   if (GET_CODE (operands[2]) != CONST_INT
5375       || INTVAL (operands[2]) > 14
5376       || INTVAL (operands[2]) < 2
5377       || GET_CODE (operands[1]) != REG
5378       || GET_CODE (operands[0]) != MEM
5379       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5380       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5381     FAIL;
5382
5383   operands[3]
5384     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5385                               force_reg (SImode, XEXP (operands[0], 0)),
5386                               TRUE, FALSE, operands[0], &offset);
5387 })
5388
5389 ;; Store multiple with write-back
5390
5391 (define_insn "*stmsi_postinc4"
5392   [(match_parallel 0 "store_multiple_operation"
5393     [(set (match_operand:SI 1 "s_register_operand" "=r")
5394           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5395                    (const_int 16)))
5396      (set (mem:SI (match_dup 2))
5397           (match_operand:SI 3 "arm_hard_register_operand" ""))
5398      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5399           (match_operand:SI 4 "arm_hard_register_operand" ""))
5400      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5401           (match_operand:SI 5 "arm_hard_register_operand" ""))
5402      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5403           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5404   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5405   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5406   [(set_attr "predicable" "yes")
5407    (set_attr "type" "store4")]
5408 )
5409
5410 (define_insn "*stmsi_postinc3"
5411   [(match_parallel 0 "store_multiple_operation"
5412     [(set (match_operand:SI 1 "s_register_operand" "=r")
5413           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5414                    (const_int 12)))
5415      (set (mem:SI (match_dup 2))
5416           (match_operand:SI 3 "arm_hard_register_operand" ""))
5417      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5418           (match_operand:SI 4 "arm_hard_register_operand" ""))
5419      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5420           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5421   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5422   "stm%?ia\\t%1!, {%3, %4, %5}"
5423   [(set_attr "predicable" "yes")
5424    (set_attr "type" "store3")]
5425 )
5426
5427 (define_insn "*stmsi_postinc2"
5428   [(match_parallel 0 "store_multiple_operation"
5429     [(set (match_operand:SI 1 "s_register_operand" "=r")
5430           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5431                    (const_int 8)))
5432      (set (mem:SI (match_dup 2))
5433           (match_operand:SI 3 "arm_hard_register_operand" ""))
5434      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5435           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5436   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5437   "stm%?ia\\t%1!, {%3, %4}"
5438   [(set_attr "predicable" "yes")
5439    (set_attr "type" "store2")]
5440 )
5441
5442 ;; Ordinary store multiple
5443
5444 (define_insn "*stmsi4"
5445   [(match_parallel 0 "store_multiple_operation"
5446     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5447           (match_operand:SI 2 "arm_hard_register_operand" ""))
5448      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5449           (match_operand:SI 3 "arm_hard_register_operand" ""))
5450      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5451           (match_operand:SI 4 "arm_hard_register_operand" ""))
5452      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5453           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5454   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5455   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5456   [(set_attr "predicable" "yes")
5457    (set_attr "type" "store4")]
5458 )
5459
5460 (define_insn "*stmsi3"
5461   [(match_parallel 0 "store_multiple_operation"
5462     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5463           (match_operand:SI 2 "arm_hard_register_operand" ""))
5464      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5465           (match_operand:SI 3 "arm_hard_register_operand" ""))
5466      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5467           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5468   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5469   "stm%?ia\\t%1, {%2, %3, %4}"
5470   [(set_attr "predicable" "yes")
5471    (set_attr "type" "store3")]
5472 )
5473
5474 (define_insn "*stmsi2"
5475   [(match_parallel 0 "store_multiple_operation"
5476     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5477           (match_operand:SI 2 "arm_hard_register_operand" ""))
5478      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5479           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5480   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5481   "stm%?ia\\t%1, {%2, %3}"
5482   [(set_attr "predicable" "yes")
5483    (set_attr "type" "store2")]
5484 )
5485
5486 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5487 ;; We could let this apply for blocks of less than this, but it clobbers so
5488 ;; many registers that there is then probably a better way.
5489
5490 (define_expand "movmemqi"
5491   [(match_operand:BLK 0 "general_operand" "")
5492    (match_operand:BLK 1 "general_operand" "")
5493    (match_operand:SI 2 "const_int_operand" "")
5494    (match_operand:SI 3 "const_int_operand" "")]
5495   "TARGET_EITHER"
5496   "
5497   if (TARGET_ARM)
5498     {
5499       if (arm_gen_movmemqi (operands))
5500         DONE;
5501       FAIL;
5502     }
5503   else /* TARGET_THUMB */
5504     {
5505       if (   INTVAL (operands[3]) != 4
5506           || INTVAL (operands[2]) > 48)
5507         FAIL;
5508
5509       thumb_expand_movmemqi (operands);
5510       DONE;
5511     }
5512   "
5513 )
5514
5515 ;; Thumb block-move insns
5516
5517 (define_insn "movmem12b"
5518   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5519         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5520    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5521         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5522    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5523         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5524    (set (match_operand:SI 0 "register_operand" "=l")
5525         (plus:SI (match_dup 2) (const_int 12)))
5526    (set (match_operand:SI 1 "register_operand" "=l")
5527         (plus:SI (match_dup 3) (const_int 12)))
5528    (clobber (match_scratch:SI 4 "=&l"))
5529    (clobber (match_scratch:SI 5 "=&l"))
5530    (clobber (match_scratch:SI 6 "=&l"))]
5531   "TARGET_THUMB"
5532   "* return thumb_output_move_mem_multiple (3, operands);"
5533   [(set_attr "length" "4")
5534    ; This isn't entirely accurate...  It loads as well, but in terms of
5535    ; scheduling the following insn it is better to consider it as a store
5536    (set_attr "type" "store3")]
5537 )
5538
5539 (define_insn "movmem8b"
5540   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5541         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5542    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5543         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5544    (set (match_operand:SI 0 "register_operand" "=l")
5545         (plus:SI (match_dup 2) (const_int 8)))
5546    (set (match_operand:SI 1 "register_operand" "=l")
5547         (plus:SI (match_dup 3) (const_int 8)))
5548    (clobber (match_scratch:SI 4 "=&l"))
5549    (clobber (match_scratch:SI 5 "=&l"))]
5550   "TARGET_THUMB"
5551   "* return thumb_output_move_mem_multiple (2, operands);"
5552   [(set_attr "length" "4")
5553    ; This isn't entirely accurate...  It loads as well, but in terms of
5554    ; scheduling the following insn it is better to consider it as a store
5555    (set_attr "type" "store2")]
5556 )
5557
5558 \f
5559
5560 ;; Compare & branch insns
5561 ;; The range calculations are based as follows:
5562 ;; For forward branches, the address calculation returns the address of
5563 ;; the next instruction.  This is 2 beyond the branch instruction.
5564 ;; For backward branches, the address calculation returns the address of
5565 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5566 ;; instruction for the shortest sequence, and 4 before the branch instruction
5567 ;; if we have to jump around an unconditional branch.
5568 ;; To the basic branch range the PC offset must be added (this is +4).
5569 ;; So for forward branches we have 
5570 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5571 ;; And for backward branches we have 
5572 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5573 ;;
5574 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5575 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5576
5577 (define_expand "cbranchsi4"
5578   [(set (pc) (if_then_else
5579               (match_operator 0 "arm_comparison_operator"
5580                [(match_operand:SI 1 "s_register_operand" "")
5581                 (match_operand:SI 2 "nonmemory_operand" "")])
5582               (label_ref (match_operand 3 "" ""))
5583               (pc)))]
5584   "TARGET_THUMB"
5585   "
5586   if (thumb_cmpneg_operand (operands[2], SImode))
5587     {
5588       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5589                                               operands[3], operands[0]));
5590       DONE;
5591     }
5592   if (!thumb_cmp_operand (operands[2], SImode))
5593     operands[2] = force_reg (SImode, operands[2]);
5594   ")
5595
5596 (define_insn "*cbranchsi4_insn"
5597   [(set (pc) (if_then_else
5598               (match_operator 0 "arm_comparison_operator"
5599                [(match_operand:SI 1 "s_register_operand" "l,*h")
5600                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5601               (label_ref (match_operand 3 "" ""))
5602               (pc)))]
5603   "TARGET_THUMB"
5604   "*
5605   output_asm_insn (\"cmp\\t%1, %2\", operands);
5606
5607   switch (get_attr_length (insn))
5608     {
5609     case 4:  return \"b%d0\\t%l3\";
5610     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5611     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5612     }
5613   "
5614   [(set (attr "far_jump")
5615         (if_then_else
5616             (eq_attr "length" "8")
5617             (const_string "yes")
5618             (const_string "no")))
5619    (set (attr "length") 
5620         (if_then_else
5621             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5622                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5623             (const_int 4)
5624             (if_then_else
5625                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5626                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5627                 (const_int 6)
5628                 (const_int 8))))]
5629 )
5630
5631 (define_insn "cbranchsi4_scratch"
5632   [(set (pc) (if_then_else
5633               (match_operator 4 "arm_comparison_operator"
5634                [(match_operand:SI 1 "s_register_operand" "l,0")
5635                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5636               (label_ref (match_operand 3 "" ""))
5637               (pc)))
5638    (clobber (match_scratch:SI 0 "=l,l"))]
5639   "TARGET_THUMB"
5640   "*
5641   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5642
5643   switch (get_attr_length (insn))
5644     {
5645     case 4:  return \"b%d4\\t%l3\";
5646     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5647     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5648     }
5649   "
5650   [(set (attr "far_jump")
5651         (if_then_else
5652             (eq_attr "length" "8")
5653             (const_string "yes")
5654             (const_string "no")))
5655    (set (attr "length") 
5656         (if_then_else
5657             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5658                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5659             (const_int 4)
5660             (if_then_else
5661                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5662                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5663                 (const_int 6)
5664                 (const_int 8))))]
5665 )
5666 (define_insn "*movsi_cbranchsi4"
5667   [(set (pc)
5668         (if_then_else
5669          (match_operator 3 "arm_comparison_operator"
5670           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5671            (const_int 0)])
5672          (label_ref (match_operand 2 "" ""))
5673          (pc)))
5674    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5675         (match_dup 1))]
5676   "TARGET_THUMB"
5677   "*{
5678   if (which_alternative == 0)
5679     output_asm_insn (\"cmp\t%0, #0\", operands);
5680   else if (which_alternative == 1)
5681     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5682   else
5683     {
5684       output_asm_insn (\"cmp\t%1, #0\", operands);
5685       if (which_alternative == 2)
5686         output_asm_insn (\"mov\t%0, %1\", operands);
5687       else
5688         output_asm_insn (\"str\t%1, %0\", operands);
5689     }
5690   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5691     {
5692     case 4:  return \"b%d3\\t%l2\";
5693     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5694     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5695     }
5696   }"
5697   [(set (attr "far_jump")
5698         (if_then_else
5699             (ior (and (gt (symbol_ref ("which_alternative"))
5700                           (const_int 1))
5701                       (eq_attr "length" "8"))
5702                  (eq_attr "length" "10"))
5703             (const_string "yes")
5704             (const_string "no")))
5705    (set (attr "length")
5706      (if_then_else
5707        (le (symbol_ref ("which_alternative"))
5708                        (const_int 1))
5709        (if_then_else
5710          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5711               (le (minus (match_dup 2) (pc)) (const_int 256)))
5712          (const_int 4)
5713          (if_then_else
5714            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5715                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5716            (const_int 6)
5717            (const_int 8)))
5718        (if_then_else
5719          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5720               (le (minus (match_dup 2) (pc)) (const_int 256)))
5721          (const_int 6)
5722          (if_then_else
5723            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5724                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5725            (const_int 8)
5726            (const_int 10)))))]
5727 )
5728
5729 (define_insn "*negated_cbranchsi4"
5730   [(set (pc)
5731         (if_then_else
5732          (match_operator 0 "arm_comparison_operator"
5733           [(match_operand:SI 1 "s_register_operand" "l")
5734            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5735          (label_ref (match_operand 3 "" ""))
5736          (pc)))]
5737   "TARGET_THUMB"
5738   "*
5739   output_asm_insn (\"cmn\\t%1, %2\", operands);
5740   switch (get_attr_length (insn))
5741     {
5742     case 4:  return \"b%d0\\t%l3\";
5743     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5744     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5745     }
5746   "
5747   [(set (attr "far_jump")
5748         (if_then_else
5749             (eq_attr "length" "8")
5750             (const_string "yes")
5751             (const_string "no")))
5752    (set (attr "length") 
5753         (if_then_else
5754             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5755                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5756             (const_int 4)
5757             (if_then_else
5758                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5759                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5760                 (const_int 6)
5761                 (const_int 8))))]
5762 )
5763
5764 (define_insn "*tbit_cbranch"
5765   [(set (pc)
5766         (if_then_else
5767          (match_operator 0 "equality_operator"
5768           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5769                             (const_int 1)
5770                             (match_operand:SI 2 "const_int_operand" "i"))
5771            (const_int 0)])
5772          (label_ref (match_operand 3 "" ""))
5773          (pc)))
5774    (clobber (match_scratch:SI 4 "=l"))]
5775   "TARGET_THUMB"
5776   "*
5777   {
5778   rtx op[3];
5779   op[0] = operands[4];
5780   op[1] = operands[1];
5781   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5782
5783   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5784   switch (get_attr_length (insn))
5785     {
5786     case 4:  return \"b%d0\\t%l3\";
5787     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5788     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5789     }
5790   }"
5791   [(set (attr "far_jump")
5792         (if_then_else
5793             (eq_attr "length" "8")
5794             (const_string "yes")
5795             (const_string "no")))
5796    (set (attr "length") 
5797         (if_then_else
5798             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5799                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5800             (const_int 4)
5801             (if_then_else
5802                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5803                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5804                 (const_int 6)
5805                 (const_int 8))))]
5806 )
5807   
5808 (define_insn "*tstsi3_cbranch"
5809   [(set (pc)
5810         (if_then_else
5811          (match_operator 3 "equality_operator"
5812           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5813                    (match_operand:SI 1 "s_register_operand" "l"))
5814            (const_int 0)])
5815          (label_ref (match_operand 2 "" ""))
5816          (pc)))]
5817   "TARGET_THUMB"
5818   "*
5819   {
5820   output_asm_insn (\"tst\\t%0, %1\", operands);
5821   switch (get_attr_length (insn))
5822     {
5823     case 4:  return \"b%d3\\t%l2\";
5824     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5825     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5826     }
5827   }"
5828   [(set (attr "far_jump")
5829         (if_then_else
5830             (eq_attr "length" "8")
5831             (const_string "yes")
5832             (const_string "no")))
5833    (set (attr "length") 
5834         (if_then_else
5835             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5836                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5837             (const_int 4)
5838             (if_then_else
5839                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5840                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5841                 (const_int 6)
5842                 (const_int 8))))]
5843 )
5844   
5845 (define_insn "*andsi3_cbranch"
5846   [(set (pc)
5847         (if_then_else
5848          (match_operator 5 "equality_operator"
5849           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5850                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5851            (const_int 0)])
5852          (label_ref (match_operand 4 "" ""))
5853          (pc)))
5854    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5855         (and:SI (match_dup 2) (match_dup 3)))
5856    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5857   "TARGET_THUMB"
5858   "*
5859   {
5860   if (which_alternative == 0)
5861     output_asm_insn (\"and\\t%0, %3\", operands);
5862   else if (which_alternative == 1)
5863     {
5864       output_asm_insn (\"and\\t%1, %3\", operands);
5865       output_asm_insn (\"mov\\t%0, %1\", operands);
5866     }
5867   else
5868     {
5869       output_asm_insn (\"and\\t%1, %3\", operands);
5870       output_asm_insn (\"str\\t%1, %0\", operands);
5871     }
5872
5873   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5874     {
5875     case 4:  return \"b%d5\\t%l4\";
5876     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5877     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5878     }
5879   }"
5880   [(set (attr "far_jump")
5881         (if_then_else
5882             (ior (and (eq (symbol_ref ("which_alternative"))
5883                           (const_int 0))
5884                       (eq_attr "length" "8"))
5885                  (eq_attr "length" "10"))
5886             (const_string "yes")
5887             (const_string "no")))
5888    (set (attr "length")
5889      (if_then_else
5890        (eq (symbol_ref ("which_alternative"))
5891                        (const_int 0))
5892        (if_then_else
5893          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5894               (le (minus (match_dup 4) (pc)) (const_int 256)))
5895          (const_int 4)
5896          (if_then_else
5897            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5898                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5899            (const_int 6)
5900            (const_int 8)))
5901        (if_then_else
5902          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5903               (le (minus (match_dup 4) (pc)) (const_int 256)))
5904          (const_int 6)
5905          (if_then_else
5906            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5907                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5908            (const_int 8)
5909            (const_int 10)))))]
5910 )
5911
5912 (define_insn "*orrsi3_cbranch_scratch"
5913   [(set (pc)
5914         (if_then_else
5915          (match_operator 4 "equality_operator"
5916           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5917                    (match_operand:SI 2 "s_register_operand" "l"))
5918            (const_int 0)])
5919          (label_ref (match_operand 3 "" ""))
5920          (pc)))
5921    (clobber (match_scratch:SI 0 "=l"))]
5922   "TARGET_THUMB"
5923   "*
5924   {
5925   output_asm_insn (\"orr\\t%0, %2\", operands);
5926   switch (get_attr_length (insn))
5927     {
5928     case 4:  return \"b%d4\\t%l3\";
5929     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5930     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5931     }
5932   }"
5933   [(set (attr "far_jump")
5934         (if_then_else
5935             (eq_attr "length" "8")
5936             (const_string "yes")
5937             (const_string "no")))
5938    (set (attr "length") 
5939         (if_then_else
5940             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5941                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5942             (const_int 4)
5943             (if_then_else
5944                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5945                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5946                 (const_int 6)
5947                 (const_int 8))))]
5948 )
5949   
5950 (define_insn "*orrsi3_cbranch"
5951   [(set (pc)
5952         (if_then_else
5953          (match_operator 5 "equality_operator"
5954           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5955                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5956            (const_int 0)])
5957          (label_ref (match_operand 4 "" ""))
5958          (pc)))
5959    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5960         (ior:SI (match_dup 2) (match_dup 3)))
5961    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5962   "TARGET_THUMB"
5963   "*
5964   {
5965   if (which_alternative == 0)
5966     output_asm_insn (\"orr\\t%0, %3\", operands);
5967   else if (which_alternative == 1)
5968     {
5969       output_asm_insn (\"orr\\t%1, %3\", operands);
5970       output_asm_insn (\"mov\\t%0, %1\", operands);
5971     }
5972   else
5973     {
5974       output_asm_insn (\"orr\\t%1, %3\", operands);
5975       output_asm_insn (\"str\\t%1, %0\", operands);
5976     }
5977
5978   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5979     {
5980     case 4:  return \"b%d5\\t%l4\";
5981     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5982     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5983     }
5984   }"
5985   [(set (attr "far_jump")
5986         (if_then_else
5987             (ior (and (eq (symbol_ref ("which_alternative"))
5988                           (const_int 0))
5989                       (eq_attr "length" "8"))
5990                  (eq_attr "length" "10"))
5991             (const_string "yes")
5992             (const_string "no")))
5993    (set (attr "length")
5994      (if_then_else
5995        (eq (symbol_ref ("which_alternative"))
5996                        (const_int 0))
5997        (if_then_else
5998          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5999               (le (minus (match_dup 4) (pc)) (const_int 256)))
6000          (const_int 4)
6001          (if_then_else
6002            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6003                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6004            (const_int 6)
6005            (const_int 8)))
6006        (if_then_else
6007          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6008               (le (minus (match_dup 4) (pc)) (const_int 256)))
6009          (const_int 6)
6010          (if_then_else
6011            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6012                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6013            (const_int 8)
6014            (const_int 10)))))]
6015 )
6016
6017 (define_insn "*xorsi3_cbranch_scratch"
6018   [(set (pc)
6019         (if_then_else
6020          (match_operator 4 "equality_operator"
6021           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6022                    (match_operand:SI 2 "s_register_operand" "l"))
6023            (const_int 0)])
6024          (label_ref (match_operand 3 "" ""))
6025          (pc)))
6026    (clobber (match_scratch:SI 0 "=l"))]
6027   "TARGET_THUMB"
6028   "*
6029   {
6030   output_asm_insn (\"eor\\t%0, %2\", operands);
6031   switch (get_attr_length (insn))
6032     {
6033     case 4:  return \"b%d4\\t%l3\";
6034     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6035     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6036     }
6037   }"
6038   [(set (attr "far_jump")
6039         (if_then_else
6040             (eq_attr "length" "8")
6041             (const_string "yes")
6042             (const_string "no")))
6043    (set (attr "length") 
6044         (if_then_else
6045             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6046                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6047             (const_int 4)
6048             (if_then_else
6049                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6050                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6051                 (const_int 6)
6052                 (const_int 8))))]
6053 )
6054   
6055 (define_insn "*xorsi3_cbranch"
6056   [(set (pc)
6057         (if_then_else
6058          (match_operator 5 "equality_operator"
6059           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6060                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6061            (const_int 0)])
6062          (label_ref (match_operand 4 "" ""))
6063          (pc)))
6064    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6065         (xor:SI (match_dup 2) (match_dup 3)))
6066    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6067   "TARGET_THUMB"
6068   "*
6069   {
6070   if (which_alternative == 0)
6071     output_asm_insn (\"eor\\t%0, %3\", operands);
6072   else if (which_alternative == 1)
6073     {
6074       output_asm_insn (\"eor\\t%1, %3\", operands);
6075       output_asm_insn (\"mov\\t%0, %1\", operands);
6076     }
6077   else
6078     {
6079       output_asm_insn (\"eor\\t%1, %3\", operands);
6080       output_asm_insn (\"str\\t%1, %0\", operands);
6081     }
6082
6083   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6084     {
6085     case 4:  return \"b%d5\\t%l4\";
6086     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6087     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6088     }
6089   }"
6090   [(set (attr "far_jump")
6091         (if_then_else
6092             (ior (and (eq (symbol_ref ("which_alternative"))
6093                           (const_int 0))
6094                       (eq_attr "length" "8"))
6095                  (eq_attr "length" "10"))
6096             (const_string "yes")
6097             (const_string "no")))
6098    (set (attr "length")
6099      (if_then_else
6100        (eq (symbol_ref ("which_alternative"))
6101                        (const_int 0))
6102        (if_then_else
6103          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6104               (le (minus (match_dup 4) (pc)) (const_int 256)))
6105          (const_int 4)
6106          (if_then_else
6107            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6108                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6109            (const_int 6)
6110            (const_int 8)))
6111        (if_then_else
6112          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6113               (le (minus (match_dup 4) (pc)) (const_int 256)))
6114          (const_int 6)
6115          (if_then_else
6116            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6117                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6118            (const_int 8)
6119            (const_int 10)))))]
6120 )
6121
6122 (define_insn "*bicsi3_cbranch_scratch"
6123   [(set (pc)
6124         (if_then_else
6125          (match_operator 4 "equality_operator"
6126           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6127                    (match_operand:SI 1 "s_register_operand" "0"))
6128            (const_int 0)])
6129          (label_ref (match_operand 3 "" ""))
6130          (pc)))
6131    (clobber (match_scratch:SI 0 "=l"))]
6132   "TARGET_THUMB"
6133   "*
6134   {
6135   output_asm_insn (\"bic\\t%0, %2\", operands);
6136   switch (get_attr_length (insn))
6137     {
6138     case 4:  return \"b%d4\\t%l3\";
6139     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6140     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6141     }
6142   }"
6143   [(set (attr "far_jump")
6144         (if_then_else
6145             (eq_attr "length" "8")
6146             (const_string "yes")
6147             (const_string "no")))
6148    (set (attr "length") 
6149         (if_then_else
6150             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6151                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6152             (const_int 4)
6153             (if_then_else
6154                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6155                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6156                 (const_int 6)
6157                 (const_int 8))))]
6158 )
6159   
6160 (define_insn "*bicsi3_cbranch"
6161   [(set (pc)
6162         (if_then_else
6163          (match_operator 5 "equality_operator"
6164           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6165                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6166            (const_int 0)])
6167          (label_ref (match_operand 4 "" ""))
6168          (pc)))
6169    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6170         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6171    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6172   "TARGET_THUMB"
6173   "*
6174   {
6175   if (which_alternative == 0)
6176     output_asm_insn (\"bic\\t%0, %3\", operands);
6177   else if (which_alternative <= 2)
6178     {
6179       output_asm_insn (\"bic\\t%1, %3\", operands);
6180       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6181          conditions again, since we're only testing for equality.  */
6182       output_asm_insn (\"mov\\t%0, %1\", operands);
6183     }
6184   else
6185     {
6186       output_asm_insn (\"bic\\t%1, %3\", operands);
6187       output_asm_insn (\"str\\t%1, %0\", operands);
6188     }
6189
6190   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6191     {
6192     case 4:  return \"b%d5\\t%l4\";
6193     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6194     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6195     }
6196   }"
6197   [(set (attr "far_jump")
6198         (if_then_else
6199             (ior (and (eq (symbol_ref ("which_alternative"))
6200                           (const_int 0))
6201                       (eq_attr "length" "8"))
6202                  (eq_attr "length" "10"))
6203             (const_string "yes")
6204             (const_string "no")))
6205    (set (attr "length")
6206      (if_then_else
6207        (eq (symbol_ref ("which_alternative"))
6208                        (const_int 0))
6209        (if_then_else
6210          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6211               (le (minus (match_dup 4) (pc)) (const_int 256)))
6212          (const_int 4)
6213          (if_then_else
6214            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6215                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6216            (const_int 6)
6217            (const_int 8)))
6218        (if_then_else
6219          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6220               (le (minus (match_dup 4) (pc)) (const_int 256)))
6221          (const_int 6)
6222          (if_then_else
6223            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6224                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6225            (const_int 8)
6226            (const_int 10)))))]
6227 )
6228
6229 (define_insn "*cbranchne_decr1"
6230   [(set (pc)
6231         (if_then_else (match_operator 3 "equality_operator"
6232                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6233                         (const_int 0)])
6234                       (label_ref (match_operand 4 "" ""))
6235                       (pc)))
6236    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6237         (plus:SI (match_dup 2) (const_int -1)))
6238    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6239   "TARGET_THUMB"
6240   "*
6241    {
6242      rtx cond[2];
6243      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6244                                 ? GEU : LTU),
6245                                VOIDmode, operands[2], const1_rtx);
6246      cond[1] = operands[4];
6247
6248      if (which_alternative == 0)
6249        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6250      else if (which_alternative == 1)
6251        {
6252          /* We must provide an alternative for a hi reg because reload 
6253             cannot handle output reloads on a jump instruction, but we
6254             can't subtract into that.  Fortunately a mov from lo to hi
6255             does not clobber the condition codes.  */
6256          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6257          output_asm_insn (\"mov\\t%0, %1\", operands);
6258        }
6259      else
6260        {
6261          /* Similarly, but the target is memory.  */
6262          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6263          output_asm_insn (\"str\\t%1, %0\", operands);
6264        }
6265
6266      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6267        {
6268          case 4:
6269            output_asm_insn (\"b%d0\\t%l1\", cond);
6270            return \"\";
6271          case 6:
6272            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6273            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6274          default:
6275            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6276            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6277        }
6278    }
6279   "
6280   [(set (attr "far_jump")
6281         (if_then_else
6282             (ior (and (eq (symbol_ref ("which_alternative"))
6283                           (const_int 0))
6284                       (eq_attr "length" "8"))
6285                  (eq_attr "length" "10"))
6286             (const_string "yes")
6287             (const_string "no")))
6288    (set_attr_alternative "length"
6289       [
6290        ;; Alternative 0
6291        (if_then_else
6292          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6293               (le (minus (match_dup 4) (pc)) (const_int 256)))
6294          (const_int 4)
6295          (if_then_else
6296            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6297                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6298            (const_int 6)
6299            (const_int 8)))
6300        ;; Alternative 1
6301        (if_then_else
6302          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6303               (le (minus (match_dup 4) (pc)) (const_int 256)))
6304          (const_int 6)
6305          (if_then_else
6306            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6307                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6308            (const_int 8)
6309            (const_int 10)))
6310        ;; Alternative 2
6311        (if_then_else
6312          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6313               (le (minus (match_dup 4) (pc)) (const_int 256)))
6314          (const_int 6)
6315          (if_then_else
6316            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6317                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6318            (const_int 8)
6319            (const_int 10)))
6320        ;; Alternative 3
6321        (if_then_else
6322          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6323               (le (minus (match_dup 4) (pc)) (const_int 256)))
6324          (const_int 6)
6325          (if_then_else
6326            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6327                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6328            (const_int 8)
6329            (const_int 10)))])]
6330 )
6331
6332 (define_insn "*addsi3_cbranch"
6333   [(set (pc)
6334         (if_then_else
6335          (match_operator 4 "comparison_operator"
6336           [(plus:SI
6337             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6338             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6339            (const_int 0)])
6340          (label_ref (match_operand 5 "" ""))
6341          (pc)))
6342    (set
6343     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6344     (plus:SI (match_dup 2) (match_dup 3)))
6345    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6346   "TARGET_THUMB
6347    && (GET_CODE (operands[4]) == EQ
6348        || GET_CODE (operands[4]) == NE
6349        || GET_CODE (operands[4]) == GE
6350        || GET_CODE (operands[4]) == LT)"
6351   "*
6352    {
6353      rtx cond[3];
6354
6355      
6356      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6357      cond[1] = operands[2];
6358      cond[2] = operands[3];
6359
6360      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6361        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6362      else
6363        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6364
6365      if (which_alternative >= 3
6366          && which_alternative < 4)
6367        output_asm_insn (\"mov\\t%0, %1\", operands);
6368      else if (which_alternative >= 4)
6369        output_asm_insn (\"str\\t%1, %0\", operands);
6370
6371      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6372        {
6373          case 4:
6374            return \"b%d4\\t%l5\";
6375          case 6:
6376            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6377          default:
6378            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6379        }
6380    }
6381   "
6382   [(set (attr "far_jump")
6383         (if_then_else
6384             (ior (and (lt (symbol_ref ("which_alternative"))
6385                           (const_int 3))
6386                       (eq_attr "length" "8"))
6387                  (eq_attr "length" "10"))
6388             (const_string "yes")
6389             (const_string "no")))
6390    (set (attr "length")
6391      (if_then_else
6392        (lt (symbol_ref ("which_alternative"))
6393                        (const_int 3))
6394        (if_then_else
6395          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6396               (le (minus (match_dup 5) (pc)) (const_int 256)))
6397          (const_int 4)
6398          (if_then_else
6399            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6400                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6401            (const_int 6)
6402            (const_int 8)))
6403        (if_then_else
6404          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6405               (le (minus (match_dup 5) (pc)) (const_int 256)))
6406          (const_int 6)
6407          (if_then_else
6408            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6409                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6410            (const_int 8)
6411            (const_int 10)))))]
6412 )
6413
6414 (define_insn "*addsi3_cbranch_scratch"
6415   [(set (pc)
6416         (if_then_else
6417          (match_operator 3 "comparison_operator"
6418           [(plus:SI
6419             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6420             (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6421            (const_int 0)])
6422          (label_ref (match_operand 4 "" ""))
6423          (pc)))
6424    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6425   "TARGET_THUMB
6426    && (GET_CODE (operands[3]) == EQ
6427        || GET_CODE (operands[3]) == NE
6428        || GET_CODE (operands[3]) == GE
6429        || GET_CODE (operands[3]) == LT)"
6430   "*
6431    {
6432      switch (which_alternative)
6433        {
6434        case 0:
6435          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6436          break;
6437        case 1:
6438          output_asm_insn (\"cmn\t%1, %2\", operands);
6439          break;
6440        case 2:
6441          output_asm_insn (\"add\t%0, %1, %2\", operands);
6442          break;
6443        case 3:
6444          output_asm_insn (\"add\t%0, %0, %2\", operands);
6445          break;
6446        }
6447
6448      switch (get_attr_length (insn))
6449        {
6450          case 4:
6451            return \"b%d3\\t%l4\";
6452          case 6:
6453            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6454          default:
6455            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6456        }
6457    }
6458   "
6459   [(set (attr "far_jump")
6460         (if_then_else
6461             (eq_attr "length" "8")
6462             (const_string "yes")
6463             (const_string "no")))
6464    (set (attr "length")
6465        (if_then_else
6466          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6467               (le (minus (match_dup 4) (pc)) (const_int 256)))
6468          (const_int 4)
6469          (if_then_else
6470            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6471                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6472            (const_int 6)
6473            (const_int 8))))]
6474 )
6475
6476 (define_insn "*subsi3_cbranch"
6477   [(set (pc)
6478         (if_then_else
6479          (match_operator 4 "comparison_operator"
6480           [(minus:SI
6481             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6482             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6483            (const_int 0)])
6484          (label_ref (match_operand 5 "" ""))
6485          (pc)))
6486    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6487         (minus:SI (match_dup 2) (match_dup 3)))
6488    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6489   "TARGET_THUMB
6490    && (GET_CODE (operands[4]) == EQ
6491        || GET_CODE (operands[4]) == NE
6492        || GET_CODE (operands[4]) == GE
6493        || GET_CODE (operands[4]) == LT)"
6494   "*
6495    {
6496      if (which_alternative == 0)
6497        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6498      else if (which_alternative == 1)
6499        {
6500          /* We must provide an alternative for a hi reg because reload 
6501             cannot handle output reloads on a jump instruction, but we
6502             can't subtract into that.  Fortunately a mov from lo to hi
6503             does not clobber the condition codes.  */
6504          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6505          output_asm_insn (\"mov\\t%0, %1\", operands);
6506        }
6507      else
6508        {
6509          /* Similarly, but the target is memory.  */
6510          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6511          output_asm_insn (\"str\\t%1, %0\", operands);
6512        }
6513
6514      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6515        {
6516          case 4:
6517            return \"b%d4\\t%l5\";
6518          case 6:
6519            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6520          default:
6521            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6522        }
6523    }
6524   "
6525   [(set (attr "far_jump")
6526         (if_then_else
6527             (ior (and (eq (symbol_ref ("which_alternative"))
6528                           (const_int 0))
6529                       (eq_attr "length" "8"))
6530                  (eq_attr "length" "10"))
6531             (const_string "yes")
6532             (const_string "no")))
6533    (set (attr "length")
6534      (if_then_else
6535        (eq (symbol_ref ("which_alternative"))
6536                        (const_int 0))
6537        (if_then_else
6538          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6539               (le (minus (match_dup 5) (pc)) (const_int 256)))
6540          (const_int 4)
6541          (if_then_else
6542            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6543                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6544            (const_int 6)
6545            (const_int 8)))
6546        (if_then_else
6547          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6548               (le (minus (match_dup 5) (pc)) (const_int 256)))
6549          (const_int 6)
6550          (if_then_else
6551            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6552                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6553            (const_int 8)
6554            (const_int 10)))))]
6555 )
6556
6557 (define_insn "*subsi3_cbranch_scratch"
6558   [(set (pc)
6559         (if_then_else
6560          (match_operator 0 "arm_comparison_operator"
6561           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6562                      (match_operand:SI 2 "nonmemory_operand" "l"))
6563            (const_int 0)])
6564          (label_ref (match_operand 3 "" ""))
6565          (pc)))]
6566   "TARGET_THUMB
6567    && (GET_CODE (operands[0]) == EQ
6568        || GET_CODE (operands[0]) == NE
6569        || GET_CODE (operands[0]) == GE
6570        || GET_CODE (operands[0]) == LT)"
6571   "*
6572   output_asm_insn (\"cmp\\t%1, %2\", operands);
6573   switch (get_attr_length (insn))
6574     {
6575     case 4:  return \"b%d0\\t%l3\";
6576     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6577     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6578     }
6579   "
6580   [(set (attr "far_jump")
6581         (if_then_else
6582             (eq_attr "length" "8")
6583             (const_string "yes")
6584             (const_string "no")))
6585    (set (attr "length") 
6586         (if_then_else
6587             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6588                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6589             (const_int 4)
6590             (if_then_else
6591                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6592                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6593                 (const_int 6)
6594                 (const_int 8))))]
6595 )
6596
6597 ;; Comparison and test insns
6598
6599 (define_expand "cmpsi"
6600   [(match_operand:SI 0 "s_register_operand" "")
6601    (match_operand:SI 1 "arm_add_operand" "")]
6602   "TARGET_ARM"
6603   "{
6604     arm_compare_op0 = operands[0];
6605     arm_compare_op1 = operands[1];
6606     DONE;
6607   }"
6608 )
6609
6610 (define_expand "cmpsf"
6611   [(match_operand:SF 0 "s_register_operand" "")
6612    (match_operand:SF 1 "arm_float_compare_operand" "")]
6613   "TARGET_ARM && TARGET_HARD_FLOAT"
6614   "
6615   arm_compare_op0 = operands[0];
6616   arm_compare_op1 = operands[1];
6617   DONE;
6618   "
6619 )
6620
6621 (define_expand "cmpdf"
6622   [(match_operand:DF 0 "s_register_operand" "")
6623    (match_operand:DF 1 "arm_float_compare_operand" "")]
6624   "TARGET_ARM && TARGET_HARD_FLOAT"
6625   "
6626   arm_compare_op0 = operands[0];
6627   arm_compare_op1 = operands[1];
6628   DONE;
6629   "
6630 )
6631
6632 (define_insn "*arm_cmpsi_insn"
6633   [(set (reg:CC CC_REGNUM)
6634         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6635                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6636   "TARGET_ARM"
6637   "@
6638    cmp%?\\t%0, %1
6639    cmn%?\\t%0, #%n1"
6640   [(set_attr "conds" "set")]
6641 )
6642
6643 (define_insn "*cmpsi_shiftsi"
6644   [(set (reg:CC CC_REGNUM)
6645         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6646                     (match_operator:SI  3 "shift_operator"
6647                      [(match_operand:SI 1 "s_register_operand" "r")
6648                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6649   "TARGET_ARM"
6650   "cmp%?\\t%0, %1%S3"
6651   [(set_attr "conds" "set")
6652    (set_attr "shift" "1")
6653    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6654                       (const_string "alu_shift")
6655                       (const_string "alu_shift_reg")))]
6656 )
6657
6658 (define_insn "*cmpsi_shiftsi_swp"
6659   [(set (reg:CC_SWP CC_REGNUM)
6660         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6661                          [(match_operand:SI 1 "s_register_operand" "r")
6662                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6663                         (match_operand:SI 0 "s_register_operand" "r")))]
6664   "TARGET_ARM"
6665   "cmp%?\\t%0, %1%S3"
6666   [(set_attr "conds" "set")
6667    (set_attr "shift" "1")
6668    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6669                       (const_string "alu_shift")
6670                       (const_string "alu_shift_reg")))]
6671 )
6672
6673 (define_insn "*cmpsi_neg_shiftsi"
6674   [(set (reg:CC CC_REGNUM)
6675         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6676                     (neg:SI (match_operator:SI 3 "shift_operator"
6677                              [(match_operand:SI 1 "s_register_operand" "r")
6678                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6679   "TARGET_ARM"
6680   "cmn%?\\t%0, %1%S3"
6681   [(set_attr "conds" "set")
6682    (set_attr "shift" "1")
6683    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6684                       (const_string "alu_shift")
6685                       (const_string "alu_shift_reg")))]
6686 )
6687
6688 ;; Cirrus SF compare instruction
6689 (define_insn "*cirrus_cmpsf"
6690   [(set (reg:CCFP CC_REGNUM)
6691         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6692                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6693   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6694   "cfcmps%?\\tr15, %V0, %V1"
6695   [(set_attr "type"   "mav_farith")
6696    (set_attr "cirrus" "compare")]
6697 )
6698
6699 ;; Cirrus DF compare instruction
6700 (define_insn "*cirrus_cmpdf"
6701   [(set (reg:CCFP CC_REGNUM)
6702         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6703                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6704   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6705   "cfcmpd%?\\tr15, %V0, %V1"
6706   [(set_attr "type"   "mav_farith")
6707    (set_attr "cirrus" "compare")]
6708 )
6709
6710 ;; Cirrus DI compare instruction
6711 (define_expand "cmpdi"
6712   [(match_operand:DI 0 "cirrus_fp_register" "")
6713    (match_operand:DI 1 "cirrus_fp_register" "")]
6714   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6715   "{
6716      arm_compare_op0 = operands[0];
6717      arm_compare_op1 = operands[1];
6718      DONE;
6719    }")
6720
6721 (define_insn "*cirrus_cmpdi"
6722   [(set (reg:CC CC_REGNUM)
6723         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6724                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6725   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6726   "cfcmp64%?\\tr15, %V0, %V1"
6727   [(set_attr "type"   "mav_farith")
6728    (set_attr "cirrus" "compare")]
6729 )
6730
6731 ; This insn allows redundant compares to be removed by cse, nothing should
6732 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6733 ; is deleted later on. The match_dup will match the mode here, so that
6734 ; mode changes of the condition codes aren't lost by this even though we don't
6735 ; specify what they are.
6736
6737 (define_insn "*deleted_compare"
6738   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6739   "TARGET_ARM"
6740   "\\t%@ deleted compare"
6741   [(set_attr "conds" "set")
6742    (set_attr "length" "0")]
6743 )
6744
6745 \f
6746 ;; Conditional branch insns
6747
6748 (define_expand "beq"
6749   [(set (pc)
6750         (if_then_else (eq (match_dup 1) (const_int 0))
6751                       (label_ref (match_operand 0 "" ""))
6752                       (pc)))]
6753   "TARGET_ARM"
6754   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6755 )
6756
6757 (define_expand "bne"
6758   [(set (pc)
6759         (if_then_else (ne (match_dup 1) (const_int 0))
6760                       (label_ref (match_operand 0 "" ""))
6761                       (pc)))]
6762   "TARGET_ARM"
6763   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6764 )
6765
6766 (define_expand "bgt"
6767   [(set (pc)
6768         (if_then_else (gt (match_dup 1) (const_int 0))
6769                       (label_ref (match_operand 0 "" ""))
6770                       (pc)))]
6771   "TARGET_ARM"
6772   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6773 )
6774
6775 (define_expand "ble"
6776   [(set (pc)
6777         (if_then_else (le (match_dup 1) (const_int 0))
6778                       (label_ref (match_operand 0 "" ""))
6779                       (pc)))]
6780   "TARGET_ARM"
6781   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6782 )
6783
6784 (define_expand "bge"
6785   [(set (pc)
6786         (if_then_else (ge (match_dup 1) (const_int 0))
6787                       (label_ref (match_operand 0 "" ""))
6788                       (pc)))]
6789   "TARGET_ARM"
6790   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6791 )
6792
6793 (define_expand "blt"
6794   [(set (pc)
6795         (if_then_else (lt (match_dup 1) (const_int 0))
6796                       (label_ref (match_operand 0 "" ""))
6797                       (pc)))]
6798   "TARGET_ARM"
6799   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6800 )
6801
6802 (define_expand "bgtu"
6803   [(set (pc)
6804         (if_then_else (gtu (match_dup 1) (const_int 0))
6805                       (label_ref (match_operand 0 "" ""))
6806                       (pc)))]
6807   "TARGET_ARM"
6808   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6809 )
6810
6811 (define_expand "bleu"
6812   [(set (pc)
6813         (if_then_else (leu (match_dup 1) (const_int 0))
6814                       (label_ref (match_operand 0 "" ""))
6815                       (pc)))]
6816   "TARGET_ARM"
6817   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6818 )
6819
6820 (define_expand "bgeu"
6821   [(set (pc)
6822         (if_then_else (geu (match_dup 1) (const_int 0))
6823                       (label_ref (match_operand 0 "" ""))
6824                       (pc)))]
6825   "TARGET_ARM"
6826   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6827 )
6828
6829 (define_expand "bltu"
6830   [(set (pc)
6831         (if_then_else (ltu (match_dup 1) (const_int 0))
6832                       (label_ref (match_operand 0 "" ""))
6833                       (pc)))]
6834   "TARGET_ARM"
6835   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6836 )
6837
6838 (define_expand "bunordered"
6839   [(set (pc)
6840         (if_then_else (unordered (match_dup 1) (const_int 0))
6841                       (label_ref (match_operand 0 "" ""))
6842                       (pc)))]
6843   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6844   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6845                                       arm_compare_op1);"
6846 )
6847
6848 (define_expand "bordered"
6849   [(set (pc)
6850         (if_then_else (ordered (match_dup 1) (const_int 0))
6851                       (label_ref (match_operand 0 "" ""))
6852                       (pc)))]
6853   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6854   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6855                                       arm_compare_op1);"
6856 )
6857
6858 (define_expand "bungt"
6859   [(set (pc)
6860         (if_then_else (ungt (match_dup 1) (const_int 0))
6861                       (label_ref (match_operand 0 "" ""))
6862                       (pc)))]
6863   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6864   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6865 )
6866
6867 (define_expand "bunlt"
6868   [(set (pc)
6869         (if_then_else (unlt (match_dup 1) (const_int 0))
6870                       (label_ref (match_operand 0 "" ""))
6871                       (pc)))]
6872   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6873   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6874 )
6875
6876 (define_expand "bunge"
6877   [(set (pc)
6878         (if_then_else (unge (match_dup 1) (const_int 0))
6879                       (label_ref (match_operand 0 "" ""))
6880                       (pc)))]
6881   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6882   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6883 )
6884
6885 (define_expand "bunle"
6886   [(set (pc)
6887         (if_then_else (unle (match_dup 1) (const_int 0))
6888                       (label_ref (match_operand 0 "" ""))
6889                       (pc)))]
6890   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6891   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6892 )
6893
6894 ;; The following two patterns need two branch instructions, since there is
6895 ;; no single instruction that will handle all cases.
6896 (define_expand "buneq"
6897   [(set (pc)
6898         (if_then_else (uneq (match_dup 1) (const_int 0))
6899                       (label_ref (match_operand 0 "" ""))
6900                       (pc)))]
6901   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6902   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6903 )
6904
6905 (define_expand "bltgt"
6906   [(set (pc)
6907         (if_then_else (ltgt (match_dup 1) (const_int 0))
6908                       (label_ref (match_operand 0 "" ""))
6909                       (pc)))]
6910   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6911   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6912 )
6913
6914 ;;
6915 ;; Patterns to match conditional branch insns.
6916 ;;
6917
6918 ; Special pattern to match UNEQ.
6919 (define_insn "*arm_buneq"
6920   [(set (pc)
6921         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6922                       (label_ref (match_operand 0 "" ""))
6923                       (pc)))]
6924   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6925   "*
6926   if (arm_ccfsm_state != 0)
6927     abort ();
6928
6929   return \"bvs\\t%l0\;beq\\t%l0\";
6930   "
6931   [(set_attr "conds" "jump_clob")
6932    (set_attr "length" "8")]
6933 )
6934
6935 ; Special pattern to match LTGT.
6936 (define_insn "*arm_bltgt"
6937   [(set (pc)
6938         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6939                       (label_ref (match_operand 0 "" ""))
6940                       (pc)))]
6941   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6942   "*
6943   if (arm_ccfsm_state != 0)
6944     abort ();
6945
6946   return \"bmi\\t%l0\;bgt\\t%l0\";
6947   "
6948   [(set_attr "conds" "jump_clob")
6949    (set_attr "length" "8")]
6950 )
6951
6952 (define_insn "*arm_cond_branch"
6953   [(set (pc)
6954         (if_then_else (match_operator 1 "arm_comparison_operator"
6955                        [(match_operand 2 "cc_register" "") (const_int 0)])
6956                       (label_ref (match_operand 0 "" ""))
6957                       (pc)))]
6958   "TARGET_ARM"
6959   "*
6960   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6961     {
6962       arm_ccfsm_state += 2;
6963       return \"\";
6964     }
6965   return \"b%d1\\t%l0\";
6966   "
6967   [(set_attr "conds" "use")
6968    (set_attr "type" "branch")]
6969 )
6970
6971 ; Special pattern to match reversed UNEQ.
6972 (define_insn "*arm_buneq_reversed"
6973   [(set (pc)
6974         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6975                       (pc)
6976                       (label_ref (match_operand 0 "" ""))))]
6977   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6978   "*
6979   if (arm_ccfsm_state != 0)
6980     abort ();
6981
6982   return \"bmi\\t%l0\;bgt\\t%l0\";
6983   "
6984   [(set_attr "conds" "jump_clob")
6985    (set_attr "length" "8")]
6986 )
6987
6988 ; Special pattern to match reversed LTGT.
6989 (define_insn "*arm_bltgt_reversed"
6990   [(set (pc)
6991         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6992                       (pc)
6993                       (label_ref (match_operand 0 "" ""))))]
6994   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6995   "*
6996   if (arm_ccfsm_state != 0)
6997     abort ();
6998
6999   return \"bvs\\t%l0\;beq\\t%l0\";
7000   "
7001   [(set_attr "conds" "jump_clob")
7002    (set_attr "length" "8")]
7003 )
7004
7005 (define_insn "*arm_cond_branch_reversed"
7006   [(set (pc)
7007         (if_then_else (match_operator 1 "arm_comparison_operator"
7008                        [(match_operand 2 "cc_register" "") (const_int 0)])
7009                       (pc)
7010                       (label_ref (match_operand 0 "" ""))))]
7011   "TARGET_ARM"
7012   "*
7013   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7014     {
7015       arm_ccfsm_state += 2;
7016       return \"\";
7017     }
7018   return \"b%D1\\t%l0\";
7019   "
7020   [(set_attr "conds" "use")
7021    (set_attr "type" "branch")]
7022 )
7023
7024 \f
7025
7026 ; scc insns
7027
7028 (define_expand "seq"
7029   [(set (match_operand:SI 0 "s_register_operand" "")
7030         (eq:SI (match_dup 1) (const_int 0)))]
7031   "TARGET_ARM"
7032   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7033 )
7034
7035 (define_expand "sne"
7036   [(set (match_operand:SI 0 "s_register_operand" "")
7037         (ne:SI (match_dup 1) (const_int 0)))]
7038   "TARGET_ARM"
7039   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7040 )
7041
7042 (define_expand "sgt"
7043   [(set (match_operand:SI 0 "s_register_operand" "")
7044         (gt:SI (match_dup 1) (const_int 0)))]
7045   "TARGET_ARM"
7046   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7047 )
7048
7049 (define_expand "sle"
7050   [(set (match_operand:SI 0 "s_register_operand" "")
7051         (le:SI (match_dup 1) (const_int 0)))]
7052   "TARGET_ARM"
7053   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7054 )
7055
7056 (define_expand "sge"
7057   [(set (match_operand:SI 0 "s_register_operand" "")
7058         (ge:SI (match_dup 1) (const_int 0)))]
7059   "TARGET_ARM"
7060   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7061 )
7062
7063 (define_expand "slt"
7064   [(set (match_operand:SI 0 "s_register_operand" "")
7065         (lt:SI (match_dup 1) (const_int 0)))]
7066   "TARGET_ARM"
7067   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7068 )
7069
7070 (define_expand "sgtu"
7071   [(set (match_operand:SI 0 "s_register_operand" "")
7072         (gtu:SI (match_dup 1) (const_int 0)))]
7073   "TARGET_ARM"
7074   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7075 )
7076
7077 (define_expand "sleu"
7078   [(set (match_operand:SI 0 "s_register_operand" "")
7079         (leu:SI (match_dup 1) (const_int 0)))]
7080   "TARGET_ARM"
7081   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7082 )
7083
7084 (define_expand "sgeu"
7085   [(set (match_operand:SI 0 "s_register_operand" "")
7086         (geu:SI (match_dup 1) (const_int 0)))]
7087   "TARGET_ARM"
7088   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7089 )
7090
7091 (define_expand "sltu"
7092   [(set (match_operand:SI 0 "s_register_operand" "")
7093         (ltu:SI (match_dup 1) (const_int 0)))]
7094   "TARGET_ARM"
7095   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7096 )
7097
7098 (define_expand "sunordered"
7099   [(set (match_operand:SI 0 "s_register_operand" "")
7100         (unordered:SI (match_dup 1) (const_int 0)))]
7101   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7102   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7103                                       arm_compare_op1);"
7104 )
7105
7106 (define_expand "sordered"
7107   [(set (match_operand:SI 0 "s_register_operand" "")
7108         (ordered:SI (match_dup 1) (const_int 0)))]
7109   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7110   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7111                                       arm_compare_op1);"
7112 )
7113
7114 (define_expand "sungt"
7115   [(set (match_operand:SI 0 "s_register_operand" "")
7116         (ungt:SI (match_dup 1) (const_int 0)))]
7117   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7118   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7119                                       arm_compare_op1);"
7120 )
7121
7122 (define_expand "sunge"
7123   [(set (match_operand:SI 0 "s_register_operand" "")
7124         (unge:SI (match_dup 1) (const_int 0)))]
7125   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7126   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7127                                       arm_compare_op1);"
7128 )
7129
7130 (define_expand "sunlt"
7131   [(set (match_operand:SI 0 "s_register_operand" "")
7132         (unlt:SI (match_dup 1) (const_int 0)))]
7133   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7134   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7135                                       arm_compare_op1);"
7136 )
7137
7138 (define_expand "sunle"
7139   [(set (match_operand:SI 0 "s_register_operand" "")
7140         (unle:SI (match_dup 1) (const_int 0)))]
7141   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7142   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7143                                       arm_compare_op1);"
7144 )
7145
7146 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7147 ;;; simple ARM instructions. 
7148 ;
7149 ; (define_expand "suneq"
7150 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7151 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7152 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7153 ;   "abort ();"
7154 ; )
7155 ;
7156 ; (define_expand "sltgt"
7157 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7158 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7159 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7160 ;   "abort ();"
7161 ; )
7162
7163 (define_insn "*mov_scc"
7164   [(set (match_operand:SI 0 "s_register_operand" "=r")
7165         (match_operator:SI 1 "arm_comparison_operator"
7166          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7167   "TARGET_ARM"
7168   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7169   [(set_attr "conds" "use")
7170    (set_attr "length" "8")]
7171 )
7172
7173 (define_insn "*mov_negscc"
7174   [(set (match_operand:SI 0 "s_register_operand" "=r")
7175         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7176                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7177   "TARGET_ARM"
7178   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7179   [(set_attr "conds" "use")
7180    (set_attr "length" "8")]
7181 )
7182
7183 (define_insn "*mov_notscc"
7184   [(set (match_operand:SI 0 "s_register_operand" "=r")
7185         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7186                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7187   "TARGET_ARM"
7188   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7189   [(set_attr "conds" "use")
7190    (set_attr "length" "8")]
7191 )
7192
7193 \f
7194 ;; Conditional move insns
7195
7196 (define_expand "movsicc"
7197   [(set (match_operand:SI 0 "s_register_operand" "")
7198         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7199                          (match_operand:SI 2 "arm_not_operand" "")
7200                          (match_operand:SI 3 "arm_not_operand" "")))]
7201   "TARGET_ARM"
7202   "
7203   {
7204     enum rtx_code code = GET_CODE (operands[1]);
7205     rtx ccreg;
7206
7207     if (code == UNEQ || code == LTGT)
7208       FAIL;
7209
7210     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7211     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7212   }"
7213 )
7214
7215 (define_expand "movsfcc"
7216   [(set (match_operand:SF 0 "s_register_operand" "")
7217         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7218                          (match_operand:SF 2 "s_register_operand" "")
7219                          (match_operand:SF 3 "nonmemory_operand" "")))]
7220   "TARGET_ARM"
7221   "
7222   {
7223     enum rtx_code code = GET_CODE (operands[1]);
7224     rtx ccreg;
7225
7226     if (code == UNEQ || code == LTGT)
7227       FAIL;
7228
7229     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7230        Otherwise, ensure it is a valid FP add operand */
7231     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7232         || (!arm_float_add_operand (operands[3], SFmode)))
7233       operands[3] = force_reg (SFmode, operands[3]);
7234
7235     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7236     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7237   }"
7238 )
7239
7240 (define_expand "movdfcc"
7241   [(set (match_operand:DF 0 "s_register_operand" "")
7242         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7243                          (match_operand:DF 2 "s_register_operand" "")
7244                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7245   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7246   "
7247   {
7248     enum rtx_code code = GET_CODE (operands[1]);
7249     rtx ccreg;
7250
7251     if (code == UNEQ || code == LTGT)
7252       FAIL;
7253
7254     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7255     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7256   }"
7257 )
7258
7259 (define_insn "*movsicc_insn"
7260   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7261         (if_then_else:SI
7262          (match_operator 3 "arm_comparison_operator"
7263           [(match_operand 4 "cc_register" "") (const_int 0)])
7264          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7265          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7266   "TARGET_ARM"
7267   "@
7268    mov%D3\\t%0, %2
7269    mvn%D3\\t%0, #%B2
7270    mov%d3\\t%0, %1
7271    mvn%d3\\t%0, #%B1
7272    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7273    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7274    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7275    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7276   [(set_attr "length" "4,4,4,4,8,8,8,8")
7277    (set_attr "conds" "use")]
7278 )
7279
7280 (define_insn "*movsfcc_soft_insn"
7281   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7282         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7283                           [(match_operand 4 "cc_register" "") (const_int 0)])
7284                          (match_operand:SF 1 "s_register_operand" "0,r")
7285                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7286   "TARGET_ARM && TARGET_SOFT_FLOAT"
7287   "@
7288    mov%D3\\t%0, %2
7289    mov%d3\\t%0, %1"
7290   [(set_attr "conds" "use")]
7291 )
7292
7293 \f
7294 ;; Jump and linkage insns
7295
7296 (define_expand "jump"
7297   [(set (pc)
7298         (label_ref (match_operand 0 "" "")))]
7299   "TARGET_EITHER"
7300   ""
7301 )
7302
7303 (define_insn "*arm_jump"
7304   [(set (pc)
7305         (label_ref (match_operand 0 "" "")))]
7306   "TARGET_ARM"
7307   "*
7308   {
7309     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7310       {
7311         arm_ccfsm_state += 2;
7312         return \"\";
7313       }
7314     return \"b%?\\t%l0\";
7315   }
7316   "
7317   [(set_attr "predicable" "yes")]
7318 )
7319
7320 (define_insn "*thumb_jump"
7321   [(set (pc)
7322         (label_ref (match_operand 0 "" "")))]
7323   "TARGET_THUMB"
7324   "*
7325   if (get_attr_length (insn) == 2)
7326     return \"b\\t%l0\";
7327   return \"bl\\t%l0\\t%@ far jump\";
7328   "
7329   [(set (attr "far_jump")
7330         (if_then_else
7331             (eq_attr "length" "4")
7332             (const_string "yes")
7333             (const_string "no")))
7334    (set (attr "length") 
7335         (if_then_else
7336             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7337                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7338             (const_int 2)
7339             (const_int 4)))]
7340 )
7341
7342 (define_expand "call"
7343   [(parallel [(call (match_operand 0 "memory_operand" "")
7344                     (match_operand 1 "general_operand" ""))
7345               (use (match_operand 2 "" ""))
7346               (clobber (reg:SI LR_REGNUM))])]
7347   "TARGET_EITHER"
7348   "
7349   {
7350     rtx callee;
7351     
7352     /* In an untyped call, we can get NULL for operand 2.  */
7353     if (operands[2] == NULL_RTX)
7354       operands[2] = const0_rtx;
7355       
7356     /* This is to decide if we should generate indirect calls by loading the
7357        32 bit address of the callee into a register before performing the
7358        branch and link.  operand[2] encodes the long_call/short_call
7359        attribute of the function being called.  This attribute is set whenever
7360        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7361        is used, and the short_call attribute can also be set if function is
7362        declared as static or if it has already been defined in the current
7363        compilation unit.  See arm.c and arm.h for info about this.  The third
7364        parameter to arm_is_longcall_p is used to tell it which pattern
7365        invoked it.  */
7366     callee  = XEXP (operands[0], 0);
7367     
7368     if (GET_CODE (callee) != REG
7369        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7370       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7371   }"
7372 )
7373
7374 (define_insn "*call_reg_armv5"
7375   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7376          (match_operand 1 "" ""))
7377    (use (match_operand 2 "" ""))
7378    (clobber (reg:SI LR_REGNUM))]
7379   "TARGET_ARM && arm_arch5"
7380   "blx%?\\t%0"
7381   [(set_attr "type" "call")]
7382 )
7383
7384 (define_insn "*call_reg_arm"
7385   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7386          (match_operand 1 "" ""))
7387    (use (match_operand 2 "" ""))
7388    (clobber (reg:SI LR_REGNUM))]
7389   "TARGET_ARM && !arm_arch5"
7390   "*
7391   return output_call (operands);
7392   "
7393   ;; length is worst case, normally it is only two
7394   [(set_attr "length" "12")
7395    (set_attr "type" "call")]
7396 )
7397
7398 (define_insn "*call_mem"
7399   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7400          (match_operand 1 "" ""))
7401    (use (match_operand 2 "" ""))
7402    (clobber (reg:SI LR_REGNUM))]
7403   "TARGET_ARM"
7404   "*
7405   return output_call_mem (operands);
7406   "
7407   [(set_attr "length" "12")
7408    (set_attr "type" "call")]
7409 )
7410
7411 (define_insn "*call_reg_thumb_v5"
7412   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7413          (match_operand 1 "" ""))
7414    (use (match_operand 2 "" ""))
7415    (clobber (reg:SI LR_REGNUM))]
7416   "TARGET_THUMB && arm_arch5"
7417   "blx\\t%0"
7418   [(set_attr "length" "2")
7419    (set_attr "type" "call")]
7420 )
7421
7422 (define_insn "*call_reg_thumb"
7423   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7424          (match_operand 1 "" ""))
7425    (use (match_operand 2 "" ""))
7426    (clobber (reg:SI LR_REGNUM))]
7427   "TARGET_THUMB && !arm_arch5"
7428   "*
7429   {
7430     if (TARGET_CALLER_INTERWORKING)
7431       return \"bl\\t%__interwork_call_via_%0\";
7432     else
7433       return \"bl\\t%__call_via_%0\";
7434   }"
7435   [(set_attr "type" "call")]
7436 )
7437
7438 (define_expand "call_value"
7439   [(parallel [(set (match_operand       0 "" "")
7440                    (call (match_operand 1 "memory_operand" "")
7441                          (match_operand 2 "general_operand" "")))
7442               (use (match_operand 3 "" ""))
7443               (clobber (reg:SI LR_REGNUM))])]
7444   "TARGET_EITHER"
7445   "
7446   {
7447     rtx callee = XEXP (operands[1], 0);
7448     
7449     /* In an untyped call, we can get NULL for operand 2.  */
7450     if (operands[3] == 0)
7451       operands[3] = const0_rtx;
7452       
7453     /* See the comment in define_expand \"call\".  */
7454     if (GET_CODE (callee) != REG
7455         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7456       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7457   }"
7458 )
7459
7460 (define_insn "*call_value_reg_armv5"
7461   [(set (match_operand 0 "" "")
7462         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7463               (match_operand 2 "" "")))
7464    (use (match_operand 3 "" ""))
7465    (clobber (reg:SI LR_REGNUM))]
7466   "TARGET_ARM && arm_arch5"
7467   "blx%?\\t%1"
7468   [(set_attr "type" "call")]
7469 )
7470
7471 (define_insn "*call_value_reg_arm"
7472   [(set (match_operand 0 "" "")
7473         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7474               (match_operand 2 "" "")))
7475    (use (match_operand 3 "" ""))
7476    (clobber (reg:SI LR_REGNUM))]
7477   "TARGET_ARM && !arm_arch5"
7478   "*
7479   return output_call (&operands[1]);
7480   "
7481   [(set_attr "length" "12")
7482    (set_attr "type" "call")]
7483 )
7484
7485 (define_insn "*call_value_mem"
7486   [(set (match_operand 0 "" "")
7487         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7488               (match_operand 2 "" "")))
7489    (use (match_operand 3 "" ""))
7490    (clobber (reg:SI LR_REGNUM))]
7491   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7492   "*
7493   return output_call_mem (&operands[1]);
7494   "
7495   [(set_attr "length" "12")
7496    (set_attr "type" "call")]
7497 )
7498
7499 (define_insn "*call_value_reg_thumb_v5"
7500   [(set (match_operand 0 "" "")
7501         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7502               (match_operand 2 "" "")))
7503    (use (match_operand 3 "" ""))
7504    (clobber (reg:SI LR_REGNUM))]
7505   "TARGET_THUMB && arm_arch5"
7506   "blx\\t%1"
7507   [(set_attr "length" "2")
7508    (set_attr "type" "call")]
7509 )
7510
7511 (define_insn "*call_value_reg_thumb"
7512   [(set (match_operand 0 "" "")
7513         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7514               (match_operand 2 "" "")))
7515    (use (match_operand 3 "" ""))
7516    (clobber (reg:SI LR_REGNUM))]
7517   "TARGET_THUMB && !arm_arch5"
7518   "*
7519   {
7520     if (TARGET_CALLER_INTERWORKING)
7521       return \"bl\\t%__interwork_call_via_%1\";
7522     else
7523       return \"bl\\t%__call_via_%1\";
7524   }"
7525   [(set_attr "type" "call")]
7526 )
7527
7528 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7529 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7530
7531 (define_insn "*call_symbol"
7532   [(call (mem:SI (match_operand:SI 0 "" ""))
7533          (match_operand 1 "" ""))
7534    (use (match_operand 2 "" ""))
7535    (clobber (reg:SI LR_REGNUM))]
7536   "TARGET_ARM
7537    && (GET_CODE (operands[0]) == SYMBOL_REF)
7538    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7539   "*
7540   {
7541     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7542   }"
7543   [(set_attr "type" "call")]
7544 )
7545
7546 (define_insn "*call_value_symbol"
7547   [(set (match_operand 0 "s_register_operand" "")
7548         (call (mem:SI (match_operand:SI 1 "" ""))
7549         (match_operand:SI 2 "" "")))
7550    (use (match_operand 3 "" ""))
7551    (clobber (reg:SI LR_REGNUM))]
7552   "TARGET_ARM
7553    && (GET_CODE (operands[1]) == SYMBOL_REF)
7554    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7555   "*
7556   {
7557     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7558   }"
7559   [(set_attr "type" "call")]
7560 )
7561
7562 (define_insn "*call_insn"
7563   [(call (mem:SI (match_operand:SI 0 "" ""))
7564          (match_operand:SI 1 "" ""))
7565    (use (match_operand 2 "" ""))
7566    (clobber (reg:SI LR_REGNUM))]
7567   "TARGET_THUMB
7568    && GET_CODE (operands[0]) == SYMBOL_REF
7569    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7570   "bl\\t%a0"
7571   [(set_attr "length" "4")
7572    (set_attr "type" "call")]
7573 )
7574
7575 (define_insn "*call_value_insn"
7576   [(set (match_operand 0 "register_operand" "")
7577         (call (mem:SI (match_operand 1 "" ""))
7578               (match_operand 2 "" "")))
7579    (use (match_operand 3 "" ""))
7580    (clobber (reg:SI LR_REGNUM))]
7581   "TARGET_THUMB
7582    && GET_CODE (operands[1]) == SYMBOL_REF
7583    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7584   "bl\\t%a1"
7585   [(set_attr "length" "4")
7586    (set_attr "type" "call")]
7587 )
7588
7589 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7590 (define_expand "sibcall"
7591   [(parallel [(call (match_operand 0 "memory_operand" "")
7592                     (match_operand 1 "general_operand" ""))
7593               (return)
7594               (use (match_operand 2 "" ""))])]
7595   "TARGET_ARM"
7596   "
7597   {
7598     if (operands[2] == NULL_RTX)
7599       operands[2] = const0_rtx;
7600   }"
7601 )
7602
7603 (define_expand "sibcall_value"
7604   [(parallel [(set (match_operand 0 "register_operand" "")
7605                    (call (match_operand 1 "memory_operand" "")
7606                          (match_operand 2 "general_operand" "")))
7607               (return)
7608               (use (match_operand 3 "" ""))])]
7609   "TARGET_ARM"
7610   "
7611   {
7612     if (operands[3] == NULL_RTX)
7613       operands[3] = const0_rtx;
7614   }"
7615 )
7616
7617 (define_insn "*sibcall_insn"
7618  [(call (mem:SI (match_operand:SI 0 "" "X"))
7619         (match_operand 1 "" ""))
7620   (return)
7621   (use (match_operand 2 "" ""))]
7622   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7623   "*
7624   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7625   "
7626   [(set_attr "type" "call")]
7627 )
7628
7629 (define_insn "*sibcall_value_insn"
7630  [(set (match_operand 0 "s_register_operand" "")
7631        (call (mem:SI (match_operand:SI 1 "" "X"))
7632              (match_operand 2 "" "")))
7633   (return)
7634   (use (match_operand 3 "" ""))]
7635   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7636   "*
7637   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7638   "
7639   [(set_attr "type" "call")]
7640 )
7641
7642 ;; Often the return insn will be the same as loading from memory, so set attr
7643 (define_insn "return"
7644   [(return)]
7645   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7646   "*
7647   {
7648     if (arm_ccfsm_state == 2)
7649       {
7650         arm_ccfsm_state += 2;
7651         return \"\";
7652       }
7653     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7654   }"
7655   [(set_attr "type" "load1")
7656    (set_attr "length" "12")
7657    (set_attr "predicable" "yes")]
7658 )
7659
7660 (define_insn "*cond_return"
7661   [(set (pc)
7662         (if_then_else (match_operator 0 "arm_comparison_operator"
7663                        [(match_operand 1 "cc_register" "") (const_int 0)])
7664                       (return)
7665                       (pc)))]
7666   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7667   "*
7668   {
7669     if (arm_ccfsm_state == 2)
7670       {
7671         arm_ccfsm_state += 2;
7672         return \"\";
7673       }
7674     return output_return_instruction (operands[0], TRUE, FALSE);
7675   }"
7676   [(set_attr "conds" "use")
7677    (set_attr "length" "12")
7678    (set_attr "type" "load1")]
7679 )
7680
7681 (define_insn "*cond_return_inverted"
7682   [(set (pc)
7683         (if_then_else (match_operator 0 "arm_comparison_operator"
7684                        [(match_operand 1 "cc_register" "") (const_int 0)])
7685                       (pc)
7686                       (return)))]
7687   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7688   "*
7689   {
7690     if (arm_ccfsm_state == 2)
7691       {
7692         arm_ccfsm_state += 2;
7693         return \"\";
7694       }
7695     return output_return_instruction (operands[0], TRUE, TRUE);
7696   }"
7697   [(set_attr "conds" "use")
7698    (set_attr "length" "12")
7699    (set_attr "type" "load1")]
7700 )
7701
7702 ;; Generate a sequence of instructions to determine if the processor is
7703 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7704 ;; mask.
7705
7706 (define_expand "return_addr_mask"
7707   [(set (match_dup 1)
7708       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7709                        (const_int 0)))
7710    (set (match_operand:SI 0 "s_register_operand" "")
7711       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7712                        (const_int -1)
7713                        (const_int 67108860)))] ; 0x03fffffc
7714   "TARGET_ARM"
7715   "
7716   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7717   ")
7718
7719 (define_insn "*check_arch2"
7720   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7721       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7722                        (const_int 0)))]
7723   "TARGET_ARM"
7724   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7725   [(set_attr "length" "8")
7726    (set_attr "conds" "set")]
7727 )
7728
7729 ;; Call subroutine returning any type.
7730
7731 (define_expand "untyped_call"
7732   [(parallel [(call (match_operand 0 "" "")
7733                     (const_int 0))
7734               (match_operand 1 "" "")
7735               (match_operand 2 "" "")])]
7736   "TARGET_ARM"
7737   "
7738   {
7739     int i;
7740
7741     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7742
7743     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7744       {
7745         rtx set = XVECEXP (operands[2], 0, i);
7746
7747         emit_move_insn (SET_DEST (set), SET_SRC (set));
7748       }
7749
7750     /* The optimizer does not know that the call sets the function value
7751        registers we stored in the result block.  We avoid problems by
7752        claiming that all hard registers are used and clobbered at this
7753        point.  */
7754     emit_insn (gen_blockage ());
7755
7756     DONE;
7757   }"
7758 )
7759
7760 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7761 ;; all of memory.  This blocks insns from being moved across this point.
7762
7763 (define_insn "blockage"
7764   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7765   "TARGET_EITHER"
7766   ""
7767   [(set_attr "length" "0")
7768    (set_attr "type" "block")]
7769 )
7770
7771 (define_expand "casesi"
7772   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7773    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7774    (match_operand:SI 2 "const_int_operand" "")  ; total range
7775    (match_operand:SI 3 "" "")                   ; table label
7776    (match_operand:SI 4 "" "")]                  ; Out of range label
7777   "TARGET_ARM"
7778   "
7779   {
7780     rtx reg;
7781     if (operands[1] != const0_rtx)
7782       {
7783         reg = gen_reg_rtx (SImode);
7784
7785         emit_insn (gen_addsi3 (reg, operands[0],
7786                                GEN_INT (-INTVAL (operands[1]))));
7787         operands[0] = reg;
7788       }
7789
7790     if (!const_ok_for_arm (INTVAL (operands[2])))
7791       operands[2] = force_reg (SImode, operands[2]);
7792
7793     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7794                                          operands[4]));
7795     DONE;
7796   }"
7797 )
7798
7799 ;; The USE in this pattern is needed to tell flow analysis that this is
7800 ;; a CASESI insn.  It has no other purpose.
7801 (define_insn "casesi_internal"
7802   [(parallel [(set (pc)
7803                (if_then_else
7804                 (leu (match_operand:SI 0 "s_register_operand" "r")
7805                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7806                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7807                                  (label_ref (match_operand 2 "" ""))))
7808                 (label_ref (match_operand 3 "" ""))))
7809               (clobber (reg:CC CC_REGNUM))
7810               (use (label_ref (match_dup 2)))])]
7811   "TARGET_ARM"
7812   "*
7813     if (flag_pic)
7814       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7815     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7816   "
7817   [(set_attr "conds" "clob")
7818    (set_attr "length" "12")]
7819 )
7820
7821 (define_expand "indirect_jump"
7822   [(set (pc)
7823         (match_operand:SI 0 "s_register_operand" ""))]
7824   "TARGET_EITHER"
7825   ""
7826 )
7827
7828 ;; NB Never uses BX.
7829 (define_insn "*arm_indirect_jump"
7830   [(set (pc)
7831         (match_operand:SI 0 "s_register_operand" "r"))]
7832   "TARGET_ARM"
7833   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7834   [(set_attr "predicable" "yes")]
7835 )
7836
7837 (define_insn "*load_indirect_jump"
7838   [(set (pc)
7839         (match_operand:SI 0 "memory_operand" "m"))]
7840   "TARGET_ARM"
7841   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7842   [(set_attr "type" "load1")
7843    (set_attr "pool_range" "4096")
7844    (set_attr "neg_pool_range" "4084")
7845    (set_attr "predicable" "yes")]
7846 )
7847
7848 ;; NB Never uses BX.
7849 (define_insn "*thumb_indirect_jump"
7850   [(set (pc)
7851         (match_operand:SI 0 "register_operand" "l*r"))]
7852   "TARGET_THUMB"
7853   "mov\\tpc, %0"
7854   [(set_attr "conds" "clob")
7855    (set_attr "length" "2")]
7856 )
7857
7858 \f
7859 ;; Misc insns
7860
7861 (define_insn "nop"
7862   [(const_int 0)]
7863   "TARGET_EITHER"
7864   "*
7865   if (TARGET_ARM)
7866     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7867   return  \"mov\\tr8, r8\";
7868   "
7869   [(set (attr "length")
7870         (if_then_else (eq_attr "is_thumb" "yes")
7871                       (const_int 2)
7872                       (const_int 4)))]
7873 )
7874
7875 \f
7876 ;; Patterns to allow combination of arithmetic, cond code and shifts
7877
7878 (define_insn "*arith_shiftsi"
7879   [(set (match_operand:SI 0 "s_register_operand" "=r")
7880         (match_operator:SI 1 "shiftable_operator"
7881           [(match_operator:SI 3 "shift_operator"
7882              [(match_operand:SI 4 "s_register_operand" "r")
7883               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7884            (match_operand:SI 2 "s_register_operand" "r")]))]
7885   "TARGET_ARM"
7886   "%i1%?\\t%0, %2, %4%S3"
7887   [(set_attr "predicable" "yes")
7888    (set_attr "shift" "4")
7889    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7890                       (const_string "alu_shift")
7891                       (const_string "alu_shift_reg")))]
7892 )
7893
7894 (define_split
7895   [(set (match_operand:SI 0 "s_register_operand" "")
7896         (match_operator:SI 1 "shiftable_operator"
7897          [(match_operator:SI 2 "shiftable_operator"
7898            [(match_operator:SI 3 "shift_operator"
7899              [(match_operand:SI 4 "s_register_operand" "")
7900               (match_operand:SI 5 "reg_or_int_operand" "")])
7901             (match_operand:SI 6 "s_register_operand" "")])
7902           (match_operand:SI 7 "arm_rhs_operand" "")]))
7903    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7904   "TARGET_ARM"
7905   [(set (match_dup 8)
7906         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7907                          (match_dup 6)]))
7908    (set (match_dup 0)
7909         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7910   "")
7911
7912 (define_insn "*arith_shiftsi_compare0"
7913   [(set (reg:CC_NOOV CC_REGNUM)
7914         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7915                           [(match_operator:SI 3 "shift_operator"
7916                             [(match_operand:SI 4 "s_register_operand" "r")
7917                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7918                            (match_operand:SI 2 "s_register_operand" "r")])
7919                          (const_int 0)))
7920    (set (match_operand:SI 0 "s_register_operand" "=r")
7921         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7922                          (match_dup 2)]))]
7923   "TARGET_ARM"
7924   "%i1%?s\\t%0, %2, %4%S3"
7925   [(set_attr "conds" "set")
7926    (set_attr "shift" "4")
7927    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7928                       (const_string "alu_shift")
7929                       (const_string "alu_shift_reg")))]
7930 )
7931
7932 (define_insn "*arith_shiftsi_compare0_scratch"
7933   [(set (reg:CC_NOOV CC_REGNUM)
7934         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7935                           [(match_operator:SI 3 "shift_operator"
7936                             [(match_operand:SI 4 "s_register_operand" "r")
7937                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7938                            (match_operand:SI 2 "s_register_operand" "r")])
7939                          (const_int 0)))
7940    (clobber (match_scratch:SI 0 "=r"))]
7941   "TARGET_ARM"
7942   "%i1%?s\\t%0, %2, %4%S3"
7943   [(set_attr "conds" "set")
7944    (set_attr "shift" "4")
7945    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7946                       (const_string "alu_shift")
7947                       (const_string "alu_shift_reg")))]
7948 )
7949
7950 (define_insn "*sub_shiftsi"
7951   [(set (match_operand:SI 0 "s_register_operand" "=r")
7952         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7953                   (match_operator:SI 2 "shift_operator"
7954                    [(match_operand:SI 3 "s_register_operand" "r")
7955                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7956   "TARGET_ARM"
7957   "sub%?\\t%0, %1, %3%S2"
7958   [(set_attr "predicable" "yes")
7959    (set_attr "shift" "3")
7960    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7961                       (const_string "alu_shift")
7962                       (const_string "alu_shift_reg")))]
7963 )
7964
7965 (define_insn "*sub_shiftsi_compare0"
7966   [(set (reg:CC_NOOV CC_REGNUM)
7967         (compare:CC_NOOV
7968          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7969                    (match_operator:SI 2 "shift_operator"
7970                     [(match_operand:SI 3 "s_register_operand" "r")
7971                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7972          (const_int 0)))
7973    (set (match_operand:SI 0 "s_register_operand" "=r")
7974         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7975                                                  (match_dup 4)])))]
7976   "TARGET_ARM"
7977   "sub%?s\\t%0, %1, %3%S2"
7978   [(set_attr "conds" "set")
7979    (set_attr "shift" "3")
7980    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7981                       (const_string "alu_shift")
7982                       (const_string "alu_shift_reg")))]
7983 )
7984
7985 (define_insn "*sub_shiftsi_compare0_scratch"
7986   [(set (reg:CC_NOOV CC_REGNUM)
7987         (compare:CC_NOOV
7988          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7989                    (match_operator:SI 2 "shift_operator"
7990                     [(match_operand:SI 3 "s_register_operand" "r")
7991                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7992          (const_int 0)))
7993    (clobber (match_scratch:SI 0 "=r"))]
7994   "TARGET_ARM"
7995   "sub%?s\\t%0, %1, %3%S2"
7996   [(set_attr "conds" "set")
7997    (set_attr "shift" "3")
7998    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7999                       (const_string "alu_shift")
8000                       (const_string "alu_shift_reg")))]
8001 )
8002
8003 \f
8004
8005 (define_insn "*and_scc"
8006   [(set (match_operand:SI 0 "s_register_operand" "=r")
8007         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8008                  [(match_operand 3 "cc_register" "") (const_int 0)])
8009                 (match_operand:SI 2 "s_register_operand" "r")))]
8010   "TARGET_ARM"
8011   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8012   [(set_attr "conds" "use")
8013    (set_attr "length" "8")]
8014 )
8015
8016 (define_insn "*ior_scc"
8017   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8018         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8019                  [(match_operand 3 "cc_register" "") (const_int 0)])
8020                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8021   "TARGET_ARM"
8022   "@
8023    orr%d2\\t%0, %1, #1
8024    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8025   [(set_attr "conds" "use")
8026    (set_attr "length" "4,8")]
8027 )
8028
8029 (define_insn "*compare_scc"
8030   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8031         (match_operator:SI 1 "arm_comparison_operator"
8032          [(match_operand:SI 2 "s_register_operand" "r,r")
8033           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8034    (clobber (reg:CC CC_REGNUM))]
8035   "TARGET_ARM"
8036   "*
8037     if (operands[3] == const0_rtx)
8038       {
8039         if (GET_CODE (operands[1]) == LT)
8040           return \"mov\\t%0, %2, lsr #31\";
8041
8042         if (GET_CODE (operands[1]) == GE)
8043           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8044
8045         if (GET_CODE (operands[1]) == EQ)
8046           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8047       }
8048
8049     if (GET_CODE (operands[1]) == NE)
8050       {
8051         if (which_alternative == 1)
8052           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8053         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8054       }
8055     if (which_alternative == 1)
8056       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8057     else
8058       output_asm_insn (\"cmp\\t%2, %3\", operands);
8059     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8060   "
8061   [(set_attr "conds" "clob")
8062    (set_attr "length" "12")]
8063 )
8064
8065 (define_insn "*cond_move"
8066   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8067         (if_then_else:SI (match_operator 3 "equality_operator"
8068                           [(match_operator 4 "arm_comparison_operator"
8069                             [(match_operand 5 "cc_register" "") (const_int 0)])
8070                            (const_int 0)])
8071                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8072                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8073   "TARGET_ARM"
8074   "*
8075     if (GET_CODE (operands[3]) == NE)
8076       {
8077         if (which_alternative != 1)
8078           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8079         if (which_alternative != 0)
8080           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8081         return \"\";
8082       }
8083     if (which_alternative != 0)
8084       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8085     if (which_alternative != 1)
8086       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8087     return \"\";
8088   "
8089   [(set_attr "conds" "use")
8090    (set_attr "length" "4,4,8")]
8091 )
8092
8093 (define_insn "*cond_arith"
8094   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8095         (match_operator:SI 5 "shiftable_operator" 
8096          [(match_operator:SI 4 "arm_comparison_operator"
8097            [(match_operand:SI 2 "s_register_operand" "r,r")
8098             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8099           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8100    (clobber (reg:CC CC_REGNUM))]
8101   "TARGET_ARM"
8102   "*
8103     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8104       return \"%i5\\t%0, %1, %2, lsr #31\";
8105
8106     output_asm_insn (\"cmp\\t%2, %3\", operands);
8107     if (GET_CODE (operands[5]) == AND)
8108       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8109     else if (GET_CODE (operands[5]) == MINUS)
8110       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8111     else if (which_alternative != 0)
8112       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8113     return \"%i5%d4\\t%0, %1, #1\";
8114   "
8115   [(set_attr "conds" "clob")
8116    (set_attr "length" "12")]
8117 )
8118
8119 (define_insn "*cond_sub"
8120   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8121         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8122                   (match_operator:SI 4 "arm_comparison_operator"
8123                    [(match_operand:SI 2 "s_register_operand" "r,r")
8124                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8125    (clobber (reg:CC CC_REGNUM))]
8126   "TARGET_ARM"
8127   "*
8128     output_asm_insn (\"cmp\\t%2, %3\", operands);
8129     if (which_alternative != 0)
8130       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8131     return \"sub%d4\\t%0, %1, #1\";
8132   "
8133   [(set_attr "conds" "clob")
8134    (set_attr "length" "8,12")]
8135 )
8136
8137 (define_insn "*cmp_ite0"
8138   [(set (match_operand 6 "dominant_cc_register" "")
8139         (compare
8140          (if_then_else:SI
8141           (match_operator 4 "arm_comparison_operator"
8142            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8143             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8144           (match_operator:SI 5 "arm_comparison_operator"
8145            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8146             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8147           (const_int 0))
8148          (const_int 0)))]
8149   "TARGET_ARM"
8150   "*
8151   {
8152     static const char * const opcodes[4][2] =
8153     {
8154       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8155        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8156       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8157        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8158       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8159        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8160       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8161        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8162     };
8163     int swap =
8164       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8165
8166     return opcodes[which_alternative][swap];
8167   }"
8168   [(set_attr "conds" "set")
8169    (set_attr "length" "8")]
8170 )
8171
8172 (define_insn "*cmp_ite1"
8173   [(set (match_operand 6 "dominant_cc_register" "")
8174         (compare
8175          (if_then_else:SI
8176           (match_operator 4 "arm_comparison_operator"
8177            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8178             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8179           (match_operator:SI 5 "arm_comparison_operator"
8180            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8181             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8182           (const_int 1))
8183          (const_int 0)))]
8184   "TARGET_ARM"
8185   "*
8186   {
8187     static const char * const opcodes[4][2] =
8188     {
8189       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8190        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8191       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8192        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8193       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8194        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8195       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8196        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8197     };
8198     int swap =
8199       comparison_dominates_p (GET_CODE (operands[5]),
8200                               reverse_condition (GET_CODE (operands[4])));
8201
8202     return opcodes[which_alternative][swap];
8203   }"
8204   [(set_attr "conds" "set")
8205    (set_attr "length" "8")]
8206 )
8207
8208 (define_insn "*cmp_and"
8209   [(set (match_operand 6 "dominant_cc_register" "")
8210         (compare
8211          (and:SI
8212           (match_operator 4 "arm_comparison_operator"
8213            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8214             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8215           (match_operator:SI 5 "arm_comparison_operator"
8216            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8217             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8218          (const_int 0)))]
8219   "TARGET_ARM"
8220   "*
8221   {
8222     static const char *const opcodes[4][2] =
8223     {
8224       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8225        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8226       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8227        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8228       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8229        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8230       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8231        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8232     };
8233     int swap =
8234       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8235
8236     return opcodes[which_alternative][swap];
8237   }"
8238   [(set_attr "conds" "set")
8239    (set_attr "predicable" "no")
8240    (set_attr "length" "8")]
8241 )
8242
8243 (define_insn "*cmp_ior"
8244   [(set (match_operand 6 "dominant_cc_register" "")
8245         (compare
8246          (ior:SI
8247           (match_operator 4 "arm_comparison_operator"
8248            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8249             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8250           (match_operator:SI 5 "arm_comparison_operator"
8251            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8252             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8253          (const_int 0)))]
8254   "TARGET_ARM"
8255   "*
8256 {
8257   static const char *const opcodes[4][2] =
8258   {
8259     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8260      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8261     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8262      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8263     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8264      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8265     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8266      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8267   };
8268   int swap =
8269     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8270
8271   return opcodes[which_alternative][swap];
8272 }
8273 "
8274   [(set_attr "conds" "set")
8275    (set_attr "length" "8")]
8276 )
8277
8278 (define_insn_and_split "*ior_scc_scc"
8279   [(set (match_operand:SI 0 "s_register_operand" "=r")
8280         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8281                  [(match_operand:SI 1 "s_register_operand" "r")
8282                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8283                 (match_operator:SI 6 "arm_comparison_operator"
8284                  [(match_operand:SI 4 "s_register_operand" "r")
8285                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8286    (clobber (reg:CC CC_REGNUM))]
8287   "TARGET_ARM
8288    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8289        != CCmode)"
8290   "#"
8291   "TARGET_ARM && reload_completed"
8292   [(set (match_dup 7)
8293         (compare
8294          (ior:SI
8295           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8296           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8297          (const_int 0)))
8298    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8299   "operands[7]
8300      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8301                                                   DOM_CC_X_OR_Y),
8302                     CC_REGNUM);"
8303   [(set_attr "conds" "clob")
8304    (set_attr "length" "16")])
8305
8306 ; If the above pattern is followed by a CMP insn, then the compare is 
8307 ; redundant, since we can rework the conditional instruction that follows.
8308 (define_insn_and_split "*ior_scc_scc_cmp"
8309   [(set (match_operand 0 "dominant_cc_register" "")
8310         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8311                           [(match_operand:SI 1 "s_register_operand" "r")
8312                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8313                          (match_operator:SI 6 "arm_comparison_operator"
8314                           [(match_operand:SI 4 "s_register_operand" "r")
8315                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8316                  (const_int 0)))
8317    (set (match_operand:SI 7 "s_register_operand" "=r")
8318         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8319                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8320   "TARGET_ARM"
8321   "#"
8322   "TARGET_ARM && reload_completed"
8323   [(set (match_dup 0)
8324         (compare
8325          (ior:SI
8326           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8327           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8328          (const_int 0)))
8329    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8330   ""
8331   [(set_attr "conds" "set")
8332    (set_attr "length" "16")])
8333
8334 (define_insn_and_split "*and_scc_scc"
8335   [(set (match_operand:SI 0 "s_register_operand" "=r")
8336         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8337                  [(match_operand:SI 1 "s_register_operand" "r")
8338                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8339                 (match_operator:SI 6 "arm_comparison_operator"
8340                  [(match_operand:SI 4 "s_register_operand" "r")
8341                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8342    (clobber (reg:CC CC_REGNUM))]
8343   "TARGET_ARM
8344    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8345        != CCmode)"
8346   "#"
8347   "TARGET_ARM && reload_completed
8348    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8349        != CCmode)"
8350   [(set (match_dup 7)
8351         (compare
8352          (and:SI
8353           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8354           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8355          (const_int 0)))
8356    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8357   "operands[7]
8358      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8359                                                   DOM_CC_X_AND_Y),
8360                     CC_REGNUM);"
8361   [(set_attr "conds" "clob")
8362    (set_attr "length" "16")])
8363
8364 ; If the above pattern is followed by a CMP insn, then the compare is 
8365 ; redundant, since we can rework the conditional instruction that follows.
8366 (define_insn_and_split "*and_scc_scc_cmp"
8367   [(set (match_operand 0 "dominant_cc_register" "")
8368         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8369                           [(match_operand:SI 1 "s_register_operand" "r")
8370                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8371                          (match_operator:SI 6 "arm_comparison_operator"
8372                           [(match_operand:SI 4 "s_register_operand" "r")
8373                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8374                  (const_int 0)))
8375    (set (match_operand:SI 7 "s_register_operand" "=r")
8376         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8377                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8378   "TARGET_ARM"
8379   "#"
8380   "TARGET_ARM && reload_completed"
8381   [(set (match_dup 0)
8382         (compare
8383          (and:SI
8384           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8385           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8386          (const_int 0)))
8387    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8388   ""
8389   [(set_attr "conds" "set")
8390    (set_attr "length" "16")])
8391
8392 ;; If there is no dominance in the comparison, then we can still save an
8393 ;; instruction in the AND case, since we can know that the second compare
8394 ;; need only zero the value if false (if true, then the value is already
8395 ;; correct).
8396 (define_insn_and_split "*and_scc_scc_nodom"
8397   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8398         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8399                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8400                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8401                 (match_operator:SI 6 "arm_comparison_operator"
8402                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8403                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8404    (clobber (reg:CC CC_REGNUM))]
8405   "TARGET_ARM
8406    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8407        == CCmode)"
8408   "#"
8409   "TARGET_ARM && reload_completed"
8410   [(parallel [(set (match_dup 0)
8411                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8412               (clobber (reg:CC CC_REGNUM))])
8413    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8414    (set (match_dup 0)
8415         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8416                          (match_dup 0)
8417                          (const_int 0)))]
8418   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8419                                               operands[4], operands[5]),
8420                               CC_REGNUM);
8421    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8422                                   operands[5]);"
8423   [(set_attr "conds" "clob")
8424    (set_attr "length" "20")])
8425
8426 (define_split
8427   [(set (reg:CC_NOOV CC_REGNUM)
8428         (compare:CC_NOOV (ior:SI
8429                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8430                                   (const_int 1))
8431                           (match_operator:SI 1 "comparison_operator"
8432                            [(match_operand:SI 2 "s_register_operand" "")
8433                             (match_operand:SI 3 "arm_add_operand" "")]))
8434                          (const_int 0)))
8435    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8436   "TARGET_ARM"
8437   [(set (match_dup 4)
8438         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8439                 (match_dup 0)))
8440    (set (reg:CC_NOOV CC_REGNUM)
8441         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8442                          (const_int 0)))]
8443   "")
8444
8445 (define_split
8446   [(set (reg:CC_NOOV CC_REGNUM)
8447         (compare:CC_NOOV (ior:SI
8448                           (match_operator:SI 1 "comparison_operator"
8449                            [(match_operand:SI 2 "s_register_operand" "")
8450                             (match_operand:SI 3 "arm_add_operand" "")])
8451                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8452                                   (const_int 1)))
8453                          (const_int 0)))
8454    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8455   "TARGET_ARM"
8456   [(set (match_dup 4)
8457         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8458                 (match_dup 0)))
8459    (set (reg:CC_NOOV CC_REGNUM)
8460         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8461                          (const_int 0)))]
8462   "")
8463
8464 (define_insn "*negscc"
8465   [(set (match_operand:SI 0 "s_register_operand" "=r")
8466         (neg:SI (match_operator 3 "arm_comparison_operator"
8467                  [(match_operand:SI 1 "s_register_operand" "r")
8468                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8469    (clobber (reg:CC CC_REGNUM))]
8470   "TARGET_ARM"
8471   "*
8472   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8473     return \"mov\\t%0, %1, asr #31\";
8474
8475   if (GET_CODE (operands[3]) == NE)
8476     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8477
8478   if (GET_CODE (operands[3]) == GT)
8479     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8480
8481   output_asm_insn (\"cmp\\t%1, %2\", operands);
8482   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8483   return \"mvn%d3\\t%0, #0\";
8484   "
8485   [(set_attr "conds" "clob")
8486    (set_attr "length" "12")]
8487 )
8488
8489 (define_insn "movcond"
8490   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8491         (if_then_else:SI
8492          (match_operator 5 "arm_comparison_operator"
8493           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8494            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8495          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8496          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8497    (clobber (reg:CC CC_REGNUM))]
8498   "TARGET_ARM"
8499   "*
8500   if (GET_CODE (operands[5]) == LT
8501       && (operands[4] == const0_rtx))
8502     {
8503       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8504         {
8505           if (operands[2] == const0_rtx)
8506             return \"and\\t%0, %1, %3, asr #31\";
8507           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8508         }
8509       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8510         {
8511           if (operands[1] == const0_rtx)
8512             return \"bic\\t%0, %2, %3, asr #31\";
8513           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8514         }
8515       /* The only case that falls through to here is when both ops 1 & 2
8516          are constants.  */
8517     }
8518
8519   if (GET_CODE (operands[5]) == GE
8520       && (operands[4] == const0_rtx))
8521     {
8522       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8523         {
8524           if (operands[2] == const0_rtx)
8525             return \"bic\\t%0, %1, %3, asr #31\";
8526           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8527         }
8528       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8529         {
8530           if (operands[1] == const0_rtx)
8531             return \"and\\t%0, %2, %3, asr #31\";
8532           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8533         }
8534       /* The only case that falls through to here is when both ops 1 & 2
8535          are constants.  */
8536     }
8537   if (GET_CODE (operands[4]) == CONST_INT
8538       && !const_ok_for_arm (INTVAL (operands[4])))
8539     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8540   else
8541     output_asm_insn (\"cmp\\t%3, %4\", operands);
8542   if (which_alternative != 0)
8543     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8544   if (which_alternative != 1)
8545     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8546   return \"\";
8547   "
8548   [(set_attr "conds" "clob")
8549    (set_attr "length" "8,8,12")]
8550 )
8551
8552 (define_insn "*ifcompare_plus_move"
8553   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8554         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8555                           [(match_operand:SI 4 "s_register_operand" "r,r")
8556                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8557                          (plus:SI
8558                           (match_operand:SI 2 "s_register_operand" "r,r")
8559                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8560                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8561    (clobber (reg:CC CC_REGNUM))]
8562   "TARGET_ARM"
8563   "#"
8564   [(set_attr "conds" "clob")
8565    (set_attr "length" "8,12")]
8566 )
8567
8568 (define_insn "*if_plus_move"
8569   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8570         (if_then_else:SI
8571          (match_operator 4 "arm_comparison_operator"
8572           [(match_operand 5 "cc_register" "") (const_int 0)])
8573          (plus:SI
8574           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8575           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8576          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8577   "TARGET_ARM"
8578   "@
8579    add%d4\\t%0, %2, %3
8580    sub%d4\\t%0, %2, #%n3
8581    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8582    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8583   [(set_attr "conds" "use")
8584    (set_attr "length" "4,4,8,8")
8585    (set_attr "type" "*,*,*,*")]
8586 )
8587
8588 (define_insn "*ifcompare_move_plus"
8589   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8590         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8591                           [(match_operand:SI 4 "s_register_operand" "r,r")
8592                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8593                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8594                          (plus:SI
8595                           (match_operand:SI 2 "s_register_operand" "r,r")
8596                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8597    (clobber (reg:CC CC_REGNUM))]
8598   "TARGET_ARM"
8599   "#"
8600   [(set_attr "conds" "clob")
8601    (set_attr "length" "8,12")]
8602 )
8603
8604 (define_insn "*if_move_plus"
8605   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8606         (if_then_else:SI
8607          (match_operator 4 "arm_comparison_operator"
8608           [(match_operand 5 "cc_register" "") (const_int 0)])
8609          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8610          (plus:SI
8611           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8612           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8613   "TARGET_ARM"
8614   "@
8615    add%D4\\t%0, %2, %3
8616    sub%D4\\t%0, %2, #%n3
8617    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8618    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8619   [(set_attr "conds" "use")
8620    (set_attr "length" "4,4,8,8")
8621    (set_attr "type" "*,*,*,*")]
8622 )
8623
8624 (define_insn "*ifcompare_arith_arith"
8625   [(set (match_operand:SI 0 "s_register_operand" "=r")
8626         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8627                           [(match_operand:SI 5 "s_register_operand" "r")
8628                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8629                          (match_operator:SI 8 "shiftable_operator"
8630                           [(match_operand:SI 1 "s_register_operand" "r")
8631                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8632                          (match_operator:SI 7 "shiftable_operator"
8633                           [(match_operand:SI 3 "s_register_operand" "r")
8634                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8635    (clobber (reg:CC CC_REGNUM))]
8636   "TARGET_ARM"
8637   "#"
8638   [(set_attr "conds" "clob")
8639    (set_attr "length" "12")]
8640 )
8641
8642 (define_insn "*if_arith_arith"
8643   [(set (match_operand:SI 0 "s_register_operand" "=r")
8644         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8645                           [(match_operand 8 "cc_register" "") (const_int 0)])
8646                          (match_operator:SI 6 "shiftable_operator"
8647                           [(match_operand:SI 1 "s_register_operand" "r")
8648                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8649                          (match_operator:SI 7 "shiftable_operator"
8650                           [(match_operand:SI 3 "s_register_operand" "r")
8651                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8652   "TARGET_ARM"
8653   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8654   [(set_attr "conds" "use")
8655    (set_attr "length" "8")]
8656 )
8657
8658 (define_insn "*ifcompare_arith_move"
8659   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8660         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8661                           [(match_operand:SI 2 "s_register_operand" "r,r")
8662                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8663                          (match_operator:SI 7 "shiftable_operator"
8664                           [(match_operand:SI 4 "s_register_operand" "r,r")
8665                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8666                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8667    (clobber (reg:CC CC_REGNUM))]
8668   "TARGET_ARM"
8669   "*
8670   /* If we have an operation where (op x 0) is the identity operation and
8671      the conditional operator is LT or GE and we are comparing against zero and
8672      everything is in registers then we can do this in two instructions.  */
8673   if (operands[3] == const0_rtx
8674       && GET_CODE (operands[7]) != AND
8675       && GET_CODE (operands[5]) == REG
8676       && GET_CODE (operands[1]) == REG 
8677       && REGNO (operands[1]) == REGNO (operands[4])
8678       && REGNO (operands[4]) != REGNO (operands[0]))
8679     {
8680       if (GET_CODE (operands[6]) == LT)
8681         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8682       else if (GET_CODE (operands[6]) == GE)
8683         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8684     }
8685   if (GET_CODE (operands[3]) == CONST_INT
8686       && !const_ok_for_arm (INTVAL (operands[3])))
8687     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8688   else
8689     output_asm_insn (\"cmp\\t%2, %3\", operands);
8690   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8691   if (which_alternative != 0)
8692     return \"mov%D6\\t%0, %1\";
8693   return \"\";
8694   "
8695   [(set_attr "conds" "clob")
8696    (set_attr "length" "8,12")]
8697 )
8698
8699 (define_insn "*if_arith_move"
8700   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8701         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8702                           [(match_operand 6 "cc_register" "") (const_int 0)])
8703                          (match_operator:SI 5 "shiftable_operator"
8704                           [(match_operand:SI 2 "s_register_operand" "r,r")
8705                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8706                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8707   "TARGET_ARM"
8708   "@
8709    %I5%d4\\t%0, %2, %3
8710    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8711   [(set_attr "conds" "use")
8712    (set_attr "length" "4,8")
8713    (set_attr "type" "*,*")]
8714 )
8715
8716 (define_insn "*ifcompare_move_arith"
8717   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8718         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8719                           [(match_operand:SI 4 "s_register_operand" "r,r")
8720                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8721                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8722                          (match_operator:SI 7 "shiftable_operator"
8723                           [(match_operand:SI 2 "s_register_operand" "r,r")
8724                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8725    (clobber (reg:CC CC_REGNUM))]
8726   "TARGET_ARM"
8727   "*
8728   /* If we have an operation where (op x 0) is the identity operation and
8729      the conditional operator is LT or GE and we are comparing against zero and
8730      everything is in registers then we can do this in two instructions */
8731   if (operands[5] == const0_rtx
8732       && GET_CODE (operands[7]) != AND
8733       && GET_CODE (operands[3]) == REG
8734       && GET_CODE (operands[1]) == REG 
8735       && REGNO (operands[1]) == REGNO (operands[2])
8736       && REGNO (operands[2]) != REGNO (operands[0]))
8737     {
8738       if (GET_CODE (operands[6]) == GE)
8739         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8740       else if (GET_CODE (operands[6]) == LT)
8741         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8742     }
8743
8744   if (GET_CODE (operands[5]) == CONST_INT
8745       && !const_ok_for_arm (INTVAL (operands[5])))
8746     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8747   else
8748     output_asm_insn (\"cmp\\t%4, %5\", operands);
8749
8750   if (which_alternative != 0)
8751     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8752   return \"%I7%D6\\t%0, %2, %3\";
8753   "
8754   [(set_attr "conds" "clob")
8755    (set_attr "length" "8,12")]
8756 )
8757
8758 (define_insn "*if_move_arith"
8759   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8760         (if_then_else:SI
8761          (match_operator 4 "arm_comparison_operator"
8762           [(match_operand 6 "cc_register" "") (const_int 0)])
8763          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8764          (match_operator:SI 5 "shiftable_operator"
8765           [(match_operand:SI 2 "s_register_operand" "r,r")
8766            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8767   "TARGET_ARM"
8768   "@
8769    %I5%D4\\t%0, %2, %3
8770    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8771   [(set_attr "conds" "use")
8772    (set_attr "length" "4,8")
8773    (set_attr "type" "*,*")]
8774 )
8775
8776 (define_insn "*ifcompare_move_not"
8777   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8778         (if_then_else:SI
8779          (match_operator 5 "arm_comparison_operator"
8780           [(match_operand:SI 3 "s_register_operand" "r,r")
8781            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8782          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8783          (not:SI
8784           (match_operand:SI 2 "s_register_operand" "r,r"))))
8785    (clobber (reg:CC CC_REGNUM))]
8786   "TARGET_ARM"
8787   "#"
8788   [(set_attr "conds" "clob")
8789    (set_attr "length" "8,12")]
8790 )
8791
8792 (define_insn "*if_move_not"
8793   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8794         (if_then_else:SI
8795          (match_operator 4 "arm_comparison_operator"
8796           [(match_operand 3 "cc_register" "") (const_int 0)])
8797          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8798          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8799   "TARGET_ARM"
8800   "@
8801    mvn%D4\\t%0, %2
8802    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8803    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8804   [(set_attr "conds" "use")
8805    (set_attr "length" "4,8,8")]
8806 )
8807
8808 (define_insn "*ifcompare_not_move"
8809   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8810         (if_then_else:SI 
8811          (match_operator 5 "arm_comparison_operator"
8812           [(match_operand:SI 3 "s_register_operand" "r,r")
8813            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8814          (not:SI
8815           (match_operand:SI 2 "s_register_operand" "r,r"))
8816          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8817    (clobber (reg:CC CC_REGNUM))]
8818   "TARGET_ARM"
8819   "#"
8820   [(set_attr "conds" "clob")
8821    (set_attr "length" "8,12")]
8822 )
8823
8824 (define_insn "*if_not_move"
8825   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8826         (if_then_else:SI
8827          (match_operator 4 "arm_comparison_operator"
8828           [(match_operand 3 "cc_register" "") (const_int 0)])
8829          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8830          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8831   "TARGET_ARM"
8832   "@
8833    mvn%d4\\t%0, %2
8834    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8835    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8836   [(set_attr "conds" "use")
8837    (set_attr "length" "4,8,8")]
8838 )
8839
8840 (define_insn "*ifcompare_shift_move"
8841   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8842         (if_then_else:SI
8843          (match_operator 6 "arm_comparison_operator"
8844           [(match_operand:SI 4 "s_register_operand" "r,r")
8845            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8846          (match_operator:SI 7 "shift_operator"
8847           [(match_operand:SI 2 "s_register_operand" "r,r")
8848            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8849          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8850    (clobber (reg:CC CC_REGNUM))]
8851   "TARGET_ARM"
8852   "#"
8853   [(set_attr "conds" "clob")
8854    (set_attr "length" "8,12")]
8855 )
8856
8857 (define_insn "*if_shift_move"
8858   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8859         (if_then_else:SI
8860          (match_operator 5 "arm_comparison_operator"
8861           [(match_operand 6 "cc_register" "") (const_int 0)])
8862          (match_operator:SI 4 "shift_operator"
8863           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8864            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8865          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8866   "TARGET_ARM"
8867   "@
8868    mov%d5\\t%0, %2%S4
8869    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8870    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8871   [(set_attr "conds" "use")
8872    (set_attr "shift" "2")
8873    (set_attr "length" "4,8,8")
8874    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8875                       (const_string "alu_shift")
8876                       (const_string "alu_shift_reg")))]
8877 )
8878
8879 (define_insn "*ifcompare_move_shift"
8880   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8881         (if_then_else:SI
8882          (match_operator 6 "arm_comparison_operator"
8883           [(match_operand:SI 4 "s_register_operand" "r,r")
8884            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8885          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8886          (match_operator:SI 7 "shift_operator"
8887           [(match_operand:SI 2 "s_register_operand" "r,r")
8888            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8889    (clobber (reg:CC CC_REGNUM))]
8890   "TARGET_ARM"
8891   "#"
8892   [(set_attr "conds" "clob")
8893    (set_attr "length" "8,12")]
8894 )
8895
8896 (define_insn "*if_move_shift"
8897   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8898         (if_then_else:SI
8899          (match_operator 5 "arm_comparison_operator"
8900           [(match_operand 6 "cc_register" "") (const_int 0)])
8901          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8902          (match_operator:SI 4 "shift_operator"
8903           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8904            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8905   "TARGET_ARM"
8906   "@
8907    mov%D5\\t%0, %2%S4
8908    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8909    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8910   [(set_attr "conds" "use")
8911    (set_attr "shift" "2")
8912    (set_attr "length" "4,8,8")
8913    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8914                       (const_string "alu_shift")
8915                       (const_string "alu_shift_reg")))]
8916 )
8917
8918 (define_insn "*ifcompare_shift_shift"
8919   [(set (match_operand:SI 0 "s_register_operand" "=r")
8920         (if_then_else:SI
8921          (match_operator 7 "arm_comparison_operator"
8922           [(match_operand:SI 5 "s_register_operand" "r")
8923            (match_operand:SI 6 "arm_add_operand" "rIL")])
8924          (match_operator:SI 8 "shift_operator"
8925           [(match_operand:SI 1 "s_register_operand" "r")
8926            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8927          (match_operator:SI 9 "shift_operator"
8928           [(match_operand:SI 3 "s_register_operand" "r")
8929            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8930    (clobber (reg:CC CC_REGNUM))]
8931   "TARGET_ARM"
8932   "#"
8933   [(set_attr "conds" "clob")
8934    (set_attr "length" "12")]
8935 )
8936
8937 (define_insn "*if_shift_shift"
8938   [(set (match_operand:SI 0 "s_register_operand" "=r")
8939         (if_then_else:SI
8940          (match_operator 5 "arm_comparison_operator"
8941           [(match_operand 8 "cc_register" "") (const_int 0)])
8942          (match_operator:SI 6 "shift_operator"
8943           [(match_operand:SI 1 "s_register_operand" "r")
8944            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8945          (match_operator:SI 7 "shift_operator"
8946           [(match_operand:SI 3 "s_register_operand" "r")
8947            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8948   "TARGET_ARM"
8949   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8950   [(set_attr "conds" "use")
8951    (set_attr "shift" "1")
8952    (set_attr "length" "8")
8953    (set (attr "type") (if_then_else
8954                         (and (match_operand 2 "const_int_operand" "")
8955                              (match_operand 4 "const_int_operand" ""))
8956                       (const_string "alu_shift")
8957                       (const_string "alu_shift_reg")))]
8958 )
8959
8960 (define_insn "*ifcompare_not_arith"
8961   [(set (match_operand:SI 0 "s_register_operand" "=r")
8962         (if_then_else:SI
8963          (match_operator 6 "arm_comparison_operator"
8964           [(match_operand:SI 4 "s_register_operand" "r")
8965            (match_operand:SI 5 "arm_add_operand" "rIL")])
8966          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8967          (match_operator:SI 7 "shiftable_operator"
8968           [(match_operand:SI 2 "s_register_operand" "r")
8969            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8970    (clobber (reg:CC CC_REGNUM))]
8971   "TARGET_ARM"
8972   "#"
8973   [(set_attr "conds" "clob")
8974    (set_attr "length" "12")]
8975 )
8976
8977 (define_insn "*if_not_arith"
8978   [(set (match_operand:SI 0 "s_register_operand" "=r")
8979         (if_then_else:SI
8980          (match_operator 5 "arm_comparison_operator"
8981           [(match_operand 4 "cc_register" "") (const_int 0)])
8982          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8983          (match_operator:SI 6 "shiftable_operator"
8984           [(match_operand:SI 2 "s_register_operand" "r")
8985            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8986   "TARGET_ARM"
8987   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8988   [(set_attr "conds" "use")
8989    (set_attr "length" "8")]
8990 )
8991
8992 (define_insn "*ifcompare_arith_not"
8993   [(set (match_operand:SI 0 "s_register_operand" "=r")
8994         (if_then_else:SI
8995          (match_operator 6 "arm_comparison_operator"
8996           [(match_operand:SI 4 "s_register_operand" "r")
8997            (match_operand:SI 5 "arm_add_operand" "rIL")])
8998          (match_operator:SI 7 "shiftable_operator"
8999           [(match_operand:SI 2 "s_register_operand" "r")
9000            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9001          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9002    (clobber (reg:CC CC_REGNUM))]
9003   "TARGET_ARM"
9004   "#"
9005   [(set_attr "conds" "clob")
9006    (set_attr "length" "12")]
9007 )
9008
9009 (define_insn "*if_arith_not"
9010   [(set (match_operand:SI 0 "s_register_operand" "=r")
9011         (if_then_else:SI
9012          (match_operator 5 "arm_comparison_operator"
9013           [(match_operand 4 "cc_register" "") (const_int 0)])
9014          (match_operator:SI 6 "shiftable_operator"
9015           [(match_operand:SI 2 "s_register_operand" "r")
9016            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9017          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9018   "TARGET_ARM"
9019   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9020   [(set_attr "conds" "use")
9021    (set_attr "length" "8")]
9022 )
9023
9024 (define_insn "*ifcompare_neg_move"
9025   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9026         (if_then_else:SI
9027          (match_operator 5 "arm_comparison_operator"
9028           [(match_operand:SI 3 "s_register_operand" "r,r")
9029            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9030          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9031          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9032    (clobber (reg:CC CC_REGNUM))]
9033   "TARGET_ARM"
9034   "#"
9035   [(set_attr "conds" "clob")
9036    (set_attr "length" "8,12")]
9037 )
9038
9039 (define_insn "*if_neg_move"
9040   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9041         (if_then_else:SI
9042          (match_operator 4 "arm_comparison_operator"
9043           [(match_operand 3 "cc_register" "") (const_int 0)])
9044          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9045          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9046   "TARGET_ARM"
9047   "@
9048    rsb%d4\\t%0, %2, #0
9049    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9050    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9051   [(set_attr "conds" "use")
9052    (set_attr "length" "4,8,8")]
9053 )
9054
9055 (define_insn "*ifcompare_move_neg"
9056   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9057         (if_then_else:SI
9058          (match_operator 5 "arm_comparison_operator"
9059           [(match_operand:SI 3 "s_register_operand" "r,r")
9060            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9061          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9062          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9063    (clobber (reg:CC CC_REGNUM))]
9064   "TARGET_ARM"
9065   "#"
9066   [(set_attr "conds" "clob")
9067    (set_attr "length" "8,12")]
9068 )
9069
9070 (define_insn "*if_move_neg"
9071   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9072         (if_then_else:SI
9073          (match_operator 4 "arm_comparison_operator"
9074           [(match_operand 3 "cc_register" "") (const_int 0)])
9075          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9076          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9077   "TARGET_ARM"
9078   "@
9079    rsb%D4\\t%0, %2, #0
9080    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9081    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9082   [(set_attr "conds" "use")
9083    (set_attr "length" "4,8,8")]
9084 )
9085
9086 (define_insn "*arith_adjacentmem"
9087   [(set (match_operand:SI 0 "s_register_operand" "=r")
9088         (match_operator:SI 1 "shiftable_operator"
9089          [(match_operand:SI 2 "memory_operand" "m")
9090           (match_operand:SI 3 "memory_operand" "m")]))
9091    (clobber (match_scratch:SI 4 "=r"))]
9092   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9093   "*
9094   {
9095     rtx ldm[3];
9096     rtx arith[4];
9097     int val1 = 0, val2 = 0;
9098
9099     if (REGNO (operands[0]) > REGNO (operands[4]))
9100       {
9101         ldm[1] = operands[4];
9102         ldm[2] = operands[0];
9103       }
9104     else
9105       {
9106         ldm[1] = operands[0];
9107         ldm[2] = operands[4];
9108       }
9109     if (GET_CODE (XEXP (operands[2], 0)) != REG)
9110       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9111     if (GET_CODE (XEXP (operands[3], 0)) != REG)
9112       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9113     arith[0] = operands[0];
9114     arith[3] = operands[1];
9115     if (val1 < val2)
9116       {
9117         arith[1] = ldm[1];
9118         arith[2] = ldm[2];
9119       }
9120     else
9121       {
9122         arith[1] = ldm[2];
9123         arith[2] = ldm[1];
9124       }
9125    if (val1 && val2)
9126       {
9127         rtx ops[3];
9128         ldm[0] = ops[0] = operands[4];
9129         ops[1] = XEXP (XEXP (operands[2], 0), 0);
9130         ops[2] = XEXP (XEXP (operands[2], 0), 1);
9131         output_add_immediate (ops);
9132         if (val1 < val2)
9133           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9134         else
9135           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9136       }
9137     else if (val1)
9138       {
9139         ldm[0] = XEXP (operands[3], 0);
9140         if (val1 < val2)
9141           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9142         else
9143           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9144       }
9145     else
9146       {
9147         ldm[0] = XEXP (operands[2], 0);
9148         if (val1 < val2)
9149           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9150         else
9151           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9152       }
9153     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9154     return \"\";
9155   }"
9156   [(set_attr "length" "12")
9157    (set_attr "predicable" "yes")
9158    (set_attr "type" "load1")]
9159 )
9160
9161 ;; the arm can support extended pre-inc instructions
9162
9163 ;; In all these cases, we use operands 0 and 1 for the register being
9164 ;; incremented because those are the operands that local-alloc will
9165 ;; tie and these are the pair most likely to be tieable (and the ones
9166 ;; that will benefit the most).
9167
9168 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9169 ;; elimination will cause too many headaches.
9170
9171 (define_insn "*strqi_preinc"
9172   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9173                          (match_operand:SI 2 "index_operand" "rJ")))
9174         (match_operand:QI 3 "s_register_operand" "r"))
9175    (set (match_operand:SI 0 "s_register_operand" "=r")
9176         (plus:SI (match_dup 1) (match_dup 2)))]
9177   "TARGET_ARM
9178    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9179    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9180    && (GET_CODE (operands[2]) != REG
9181        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9182   "str%?b\\t%3, [%0, %2]!"
9183   [(set_attr "type" "store1")
9184    (set_attr "predicable" "yes")]
9185 )
9186
9187 (define_insn "*strqi_predec"
9188   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9189                           (match_operand:SI 2 "s_register_operand" "r")))
9190         (match_operand:QI 3 "s_register_operand" "r"))
9191    (set (match_operand:SI 0 "s_register_operand" "=r")
9192         (minus:SI (match_dup 1) (match_dup 2)))]
9193   "TARGET_ARM
9194    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9195    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9196    && (GET_CODE (operands[2]) != REG
9197        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9198   "str%?b\\t%3, [%0, -%2]!"
9199   [(set_attr "type" "store1")
9200    (set_attr "predicable" "yes")]
9201 )
9202
9203 (define_insn "*loadqi_preinc"
9204   [(set (match_operand:QI 3 "s_register_operand" "=r")
9205         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9206                          (match_operand:SI 2 "index_operand" "rJ"))))
9207    (set (match_operand:SI 0 "s_register_operand" "=r")
9208         (plus:SI (match_dup 1) (match_dup 2)))]
9209   "TARGET_ARM
9210    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9211    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9212    && (GET_CODE (operands[2]) != REG
9213        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9214   "ldr%?b\\t%3, [%0, %2]!"
9215   [(set_attr "type" "load_byte")
9216    (set_attr "predicable" "yes")]
9217 )
9218
9219 (define_insn "*loadqi_predec"
9220   [(set (match_operand:QI 3 "s_register_operand" "=r")
9221         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9222                           (match_operand:SI 2 "s_register_operand" "r"))))
9223    (set (match_operand:SI 0 "s_register_operand" "=r")
9224         (minus:SI (match_dup 1) (match_dup 2)))]
9225   "TARGET_ARM
9226    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9227    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9228    && (GET_CODE (operands[2]) != REG
9229        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9230   "ldr%?b\\t%3, [%0, -%2]!"
9231   [(set_attr "type" "load_byte")
9232    (set_attr "predicable" "yes")]
9233 )
9234
9235 (define_insn "*loadqisi_preinc"
9236   [(set (match_operand:SI 3 "s_register_operand" "=r")
9237         (zero_extend:SI
9238          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9239                           (match_operand:SI 2 "index_operand" "rJ")))))
9240    (set (match_operand:SI 0 "s_register_operand" "=r")
9241         (plus:SI (match_dup 1) (match_dup 2)))]
9242   "TARGET_ARM
9243    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9244    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9245    && (GET_CODE (operands[2]) != REG
9246        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9247   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9248   [(set_attr "type" "load_byte")
9249    (set_attr "predicable" "yes")]
9250 )
9251
9252 (define_insn "*loadqisi_predec"
9253   [(set (match_operand:SI 3 "s_register_operand" "=r")
9254         (zero_extend:SI
9255          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9256                            (match_operand:SI 2 "s_register_operand" "r")))))
9257    (set (match_operand:SI 0 "s_register_operand" "=r")
9258         (minus:SI (match_dup 1) (match_dup 2)))]
9259   "TARGET_ARM
9260    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9261    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9262    && (GET_CODE (operands[2]) != REG
9263        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9264   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9265   [(set_attr "type" "load_byte")
9266    (set_attr "predicable" "yes")]
9267 )
9268
9269 (define_insn "*strsi_preinc"
9270   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9271                          (match_operand:SI 2 "index_operand" "rJ")))
9272         (match_operand:SI 3 "s_register_operand" "r"))
9273    (set (match_operand:SI 0 "s_register_operand" "=r")
9274         (plus:SI (match_dup 1) (match_dup 2)))]
9275   "TARGET_ARM
9276    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9277    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9278    && (GET_CODE (operands[2]) != REG
9279        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9280   "str%?\\t%3, [%0, %2]!"
9281   [(set_attr "type" "store1")
9282    (set_attr "predicable" "yes")]
9283 )
9284
9285 (define_insn "*strsi_predec"
9286   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9287                           (match_operand:SI 2 "s_register_operand" "r")))
9288         (match_operand:SI 3 "s_register_operand" "r"))
9289    (set (match_operand:SI 0 "s_register_operand" "=r")
9290         (minus:SI (match_dup 1) (match_dup 2)))]
9291   "TARGET_ARM
9292    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9293    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9294    && (GET_CODE (operands[2]) != REG
9295        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9296   "str%?\\t%3, [%0, -%2]!"
9297   [(set_attr "type" "store1")
9298    (set_attr "predicable" "yes")]
9299 )
9300
9301 (define_insn "*loadsi_preinc"
9302   [(set (match_operand:SI 3 "s_register_operand" "=r")
9303         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9304                          (match_operand:SI 2 "index_operand" "rJ"))))
9305    (set (match_operand:SI 0 "s_register_operand" "=r")
9306         (plus:SI (match_dup 1) (match_dup 2)))]
9307   "TARGET_ARM
9308    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9309    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9310    && (GET_CODE (operands[2]) != REG
9311        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9312   "ldr%?\\t%3, [%0, %2]!"
9313   [(set_attr "type" "load1")
9314    (set_attr "predicable" "yes")]
9315 )
9316
9317 (define_insn "*loadsi_predec"
9318   [(set (match_operand:SI 3 "s_register_operand" "=r")
9319         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9320                           (match_operand:SI 2 "s_register_operand" "r"))))
9321    (set (match_operand:SI 0 "s_register_operand" "=r")
9322         (minus:SI (match_dup 1) (match_dup 2)))]
9323   "TARGET_ARM
9324    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9325    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9326    && (GET_CODE (operands[2]) != REG
9327        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9328   "ldr%?\\t%3, [%0, -%2]!"
9329   [(set_attr "type" "load1")
9330    (set_attr "predicable" "yes")]
9331 )
9332
9333 (define_insn "*strqi_shiftpreinc"
9334   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9335                           [(match_operand:SI 3 "s_register_operand" "r")
9336                            (match_operand:SI 4 "const_shift_operand" "n")])
9337                          (match_operand:SI 1 "s_register_operand" "0")))
9338         (match_operand:QI 5 "s_register_operand" "r"))
9339    (set (match_operand:SI 0 "s_register_operand" "=r")
9340         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9341                  (match_dup 1)))]
9342   "TARGET_ARM
9343    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9344    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9345    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9346   "str%?b\\t%5, [%0, %3%S2]!"
9347   [(set_attr "type" "store1")
9348    (set_attr "predicable" "yes")]
9349 )
9350
9351 (define_insn "*strqi_shiftpredec"
9352   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9353                           (match_operator:SI 2 "shift_operator"
9354                            [(match_operand:SI 3 "s_register_operand" "r")
9355                             (match_operand:SI 4 "const_shift_operand" "n")])))
9356         (match_operand:QI 5 "s_register_operand" "r"))
9357    (set (match_operand:SI 0 "s_register_operand" "=r")
9358         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9359                                                  (match_dup 4)])))]
9360   "TARGET_ARM
9361    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9362    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9363    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9364   "str%?b\\t%5, [%0, -%3%S2]!"
9365   [(set_attr "type" "store1")
9366    (set_attr "predicable" "yes")]
9367 )
9368
9369 (define_insn "*loadqi_shiftpreinc"
9370   [(set (match_operand:QI 5 "s_register_operand" "=r")
9371         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9372                           [(match_operand:SI 3 "s_register_operand" "r")
9373                            (match_operand:SI 4 "const_shift_operand" "n")])
9374                          (match_operand:SI 1 "s_register_operand" "0"))))
9375    (set (match_operand:SI 0 "s_register_operand" "=r")
9376         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9377                  (match_dup 1)))]
9378   "TARGET_ARM
9379    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9380    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9381    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9382   "ldr%?b\\t%5, [%0, %3%S2]!"
9383   [(set_attr "type" "load_byte")
9384    (set_attr "predicable" "yes")]
9385 )
9386
9387 (define_insn "*loadqi_shiftpredec"
9388   [(set (match_operand:QI 5 "s_register_operand" "=r")
9389         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9390                           (match_operator:SI 2 "shift_operator"
9391                            [(match_operand:SI 3 "s_register_operand" "r")
9392                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9393    (set (match_operand:SI 0 "s_register_operand" "=r")
9394         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9395                                                  (match_dup 4)])))]
9396   "TARGET_ARM
9397    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9398    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9399    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9400   "ldr%?b\\t%5, [%0, -%3%S2]!"
9401   [(set_attr "type" "load_byte")
9402    (set_attr "predicable" "yes")]
9403 )
9404
9405 (define_insn "*strsi_shiftpreinc"
9406   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9407                           [(match_operand:SI 3 "s_register_operand" "r")
9408                            (match_operand:SI 4 "const_shift_operand" "n")])
9409                          (match_operand:SI 1 "s_register_operand" "0")))
9410         (match_operand:SI 5 "s_register_operand" "r"))
9411    (set (match_operand:SI 0 "s_register_operand" "=r")
9412         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9413                  (match_dup 1)))]
9414   "TARGET_ARM
9415    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9416    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9417    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9418   "str%?\\t%5, [%0, %3%S2]!"
9419   [(set_attr "type" "store1")
9420    (set_attr "predicable" "yes")]
9421 )
9422
9423 (define_insn "*strsi_shiftpredec"
9424   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9425                           (match_operator:SI 2 "shift_operator"
9426                            [(match_operand:SI 3 "s_register_operand" "r")
9427                             (match_operand:SI 4 "const_shift_operand" "n")])))
9428         (match_operand:SI 5 "s_register_operand" "r"))
9429    (set (match_operand:SI 0 "s_register_operand" "=r")
9430         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9431                                                  (match_dup 4)])))]
9432   "TARGET_ARM
9433    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9434    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9435    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9436   "str%?\\t%5, [%0, -%3%S2]!"
9437   [(set_attr "type" "store1")
9438    (set_attr "predicable" "yes")]
9439 )
9440
9441 (define_insn "*loadsi_shiftpreinc"
9442   [(set (match_operand:SI 5 "s_register_operand" "=r")
9443         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9444                           [(match_operand:SI 3 "s_register_operand" "r")
9445                            (match_operand:SI 4 "const_shift_operand" "n")])
9446                          (match_operand:SI 1 "s_register_operand" "0"))))
9447    (set (match_operand:SI 0 "s_register_operand" "=r")
9448         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9449                  (match_dup 1)))]
9450   "TARGET_ARM
9451    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9452    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9453    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9454   "ldr%?\\t%5, [%0, %3%S2]!"
9455   [(set_attr "type" "load1")
9456    (set_attr "predicable" "yes")]
9457 )
9458
9459 (define_insn "*loadsi_shiftpredec"
9460   [(set (match_operand:SI 5 "s_register_operand" "=r")
9461         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9462                           (match_operator:SI 2 "shift_operator"
9463                            [(match_operand:SI 3 "s_register_operand" "r")
9464                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9465    (set (match_operand:SI 0 "s_register_operand" "=r")
9466         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9467                                                  (match_dup 4)])))]
9468   "TARGET_ARM
9469    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9470    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9471    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9472   "ldr%?\\t%5, [%0, -%3%S2]!"
9473   [(set_attr "type" "load1")
9474    (set_attr "predicable" "yes")])
9475
9476 ; It can also support extended post-inc expressions, but combine doesn't
9477 ; try these....
9478 ; It doesn't seem worth adding peepholes for anything but the most common
9479 ; cases since, unlike combine, the increment must immediately follow the load
9480 ; for this pattern to match.
9481 ; We must watch to see that the source/destination register isn't also the
9482 ; same as the base address register, and that if the index is a register,
9483 ; that it is not the same as the base address register.  In such cases the
9484 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9485 ; we cannot use it.
9486
9487 (define_peephole
9488   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9489         (match_operand:QI 2 "s_register_operand" "r"))
9490    (set (match_dup 0)
9491         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9492   "TARGET_ARM
9493    && (REGNO (operands[2]) != REGNO (operands[0]))
9494    && (GET_CODE (operands[1]) != REG
9495        || (REGNO (operands[1]) != REGNO (operands[0])))"
9496   "str%?b\\t%2, [%0], %1"
9497 )
9498
9499 (define_peephole
9500   [(set (match_operand:QI 0 "s_register_operand" "=r")
9501         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9502    (set (match_dup 1)
9503         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9504   "TARGET_ARM
9505    && REGNO (operands[0]) != REGNO(operands[1])
9506    && (GET_CODE (operands[2]) != REG
9507        || REGNO(operands[0]) != REGNO (operands[2]))"
9508   "ldr%?b\\t%0, [%1], %2"
9509 )
9510
9511 (define_peephole
9512   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9513         (match_operand:SI 2 "s_register_operand" "r"))
9514    (set (match_dup 0)
9515         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9516   "TARGET_ARM
9517    && (REGNO (operands[2]) != REGNO (operands[0]))
9518    && (GET_CODE (operands[1]) != REG
9519        || (REGNO (operands[1]) != REGNO (operands[0])))"
9520   "str%?\\t%2, [%0], %1"
9521 )
9522
9523 (define_peephole
9524   [(set (match_operand:SI 0 "s_register_operand" "=r")
9525         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9526    (set (match_dup 1)
9527         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9528   "TARGET_ARM
9529    && REGNO (operands[0]) != REGNO(operands[1])
9530    && (GET_CODE (operands[2]) != REG
9531        || REGNO(operands[0]) != REGNO (operands[2]))"
9532   "ldr%?\\t%0, [%1], %2"
9533 )
9534
9535 (define_peephole
9536   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9537                          (match_operand:SI 1 "index_operand" "rJ")))
9538         (match_operand:QI 2 "s_register_operand" "r"))
9539    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9540   "TARGET_ARM
9541    && (REGNO (operands[2]) != REGNO (operands[0]))
9542    && (GET_CODE (operands[1]) != REG
9543        || (REGNO (operands[1]) != REGNO (operands[0])))"
9544   "str%?b\\t%2, [%0, %1]!"
9545 )
9546
9547 (define_peephole
9548   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9549                           [(match_operand:SI 0 "s_register_operand" "r")
9550                            (match_operand:SI 1 "const_int_operand" "n")])
9551                          (match_operand:SI 2 "s_register_operand" "+r")))
9552         (match_operand:QI 3 "s_register_operand" "r"))
9553    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9554                                (match_dup 2)))]
9555   "TARGET_ARM
9556    && (REGNO (operands[3]) != REGNO (operands[2]))
9557    && (REGNO (operands[0]) != REGNO (operands[2]))"
9558   "str%?b\\t%3, [%2, %0%S4]!"
9559 )
9560
9561 ; This pattern is never tried by combine, so do it as a peephole
9562
9563 (define_peephole2
9564   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9565         (match_operand:SI 1 "arm_general_register_operand" ""))
9566    (set (reg:CC CC_REGNUM)
9567         (compare:CC (match_dup 1) (const_int 0)))]
9568   "TARGET_ARM"
9569   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9570               (set (match_dup 0) (match_dup 1))])]
9571   ""
9572 )
9573
9574 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9575 ; reversed, check that the memory references aren't volatile.
9576
9577 (define_peephole
9578   [(set (match_operand:SI 0 "s_register_operand" "=r")
9579         (match_operand:SI 4 "memory_operand" "m"))
9580    (set (match_operand:SI 1 "s_register_operand" "=r")
9581         (match_operand:SI 5 "memory_operand" "m"))
9582    (set (match_operand:SI 2 "s_register_operand" "=r")
9583         (match_operand:SI 6 "memory_operand" "m"))
9584    (set (match_operand:SI 3 "s_register_operand" "=r")
9585         (match_operand:SI 7 "memory_operand" "m"))]
9586   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9587   "*
9588   return emit_ldm_seq (operands, 4);
9589   "
9590 )
9591
9592 (define_peephole
9593   [(set (match_operand:SI 0 "s_register_operand" "=r")
9594         (match_operand:SI 3 "memory_operand" "m"))
9595    (set (match_operand:SI 1 "s_register_operand" "=r")
9596         (match_operand:SI 4 "memory_operand" "m"))
9597    (set (match_operand:SI 2 "s_register_operand" "=r")
9598         (match_operand:SI 5 "memory_operand" "m"))]
9599   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9600   "*
9601   return emit_ldm_seq (operands, 3);
9602   "
9603 )
9604
9605 (define_peephole
9606   [(set (match_operand:SI 0 "s_register_operand" "=r")
9607         (match_operand:SI 2 "memory_operand" "m"))
9608    (set (match_operand:SI 1 "s_register_operand" "=r")
9609         (match_operand:SI 3 "memory_operand" "m"))]
9610   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9611   "*
9612   return emit_ldm_seq (operands, 2);
9613   "
9614 )
9615
9616 (define_peephole
9617   [(set (match_operand:SI 4 "memory_operand" "=m")
9618         (match_operand:SI 0 "s_register_operand" "r"))
9619    (set (match_operand:SI 5 "memory_operand" "=m")
9620         (match_operand:SI 1 "s_register_operand" "r"))
9621    (set (match_operand:SI 6 "memory_operand" "=m")
9622         (match_operand:SI 2 "s_register_operand" "r"))
9623    (set (match_operand:SI 7 "memory_operand" "=m")
9624         (match_operand:SI 3 "s_register_operand" "r"))]
9625   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9626   "*
9627   return emit_stm_seq (operands, 4);
9628   "
9629 )
9630
9631 (define_peephole
9632   [(set (match_operand:SI 3 "memory_operand" "=m")
9633         (match_operand:SI 0 "s_register_operand" "r"))
9634    (set (match_operand:SI 4 "memory_operand" "=m")
9635         (match_operand:SI 1 "s_register_operand" "r"))
9636    (set (match_operand:SI 5 "memory_operand" "=m")
9637         (match_operand:SI 2 "s_register_operand" "r"))]
9638   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9639   "*
9640   return emit_stm_seq (operands, 3);
9641   "
9642 )
9643
9644 (define_peephole
9645   [(set (match_operand:SI 2 "memory_operand" "=m")
9646         (match_operand:SI 0 "s_register_operand" "r"))
9647    (set (match_operand:SI 3 "memory_operand" "=m")
9648         (match_operand:SI 1 "s_register_operand" "r"))]
9649   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9650   "*
9651   return emit_stm_seq (operands, 2);
9652   "
9653 )
9654
9655 (define_split
9656   [(set (match_operand:SI 0 "s_register_operand" "")
9657         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9658                        (const_int 0))
9659                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9660                          [(match_operand:SI 3 "s_register_operand" "")
9661                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9662    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9663   "TARGET_ARM"
9664   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9665    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9666                               (match_dup 5)))]
9667   ""
9668 )
9669
9670 ;; This split can be used because CC_Z mode implies that the following
9671 ;; branch will be an equality, or an unsigned inequality, so the sign
9672 ;; extension is not needed.
9673
9674 (define_split
9675   [(set (reg:CC_Z CC_REGNUM)
9676         (compare:CC_Z
9677          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9678                     (const_int 24))
9679          (match_operand 1 "const_int_operand" "")))
9680    (clobber (match_scratch:SI 2 ""))]
9681   "TARGET_ARM
9682    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9683        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9684   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9685    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9686   "
9687   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9688   "
9689 )
9690
9691 (define_expand "prologue"
9692   [(clobber (const_int 0))]
9693   "TARGET_EITHER"
9694   "if (TARGET_ARM)
9695      arm_expand_prologue ();
9696    else
9697      thumb_expand_prologue ();
9698   DONE;
9699   "
9700 )
9701
9702 (define_expand "epilogue"
9703   [(clobber (const_int 0))]
9704   "TARGET_EITHER"
9705   "
9706   if (current_function_calls_eh_return)
9707     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9708   if (TARGET_THUMB)
9709     thumb_expand_epilogue ();
9710   else if (USE_RETURN_INSN (FALSE))
9711     {
9712       emit_jump_insn (gen_return ());
9713       DONE;
9714     }
9715   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9716         gen_rtvec (1,
9717                 gen_rtx_RETURN (VOIDmode)),
9718         VUNSPEC_EPILOGUE));
9719   DONE;
9720   "
9721 )
9722
9723 ;; Note - although unspec_volatile's USE all hard registers,
9724 ;; USEs are ignored after relaod has completed.  Thus we need
9725 ;; to add an unspec of the link register to ensure that flow
9726 ;; does not think that it is unused by the sibcall branch that
9727 ;; will replace the standard function epilogue.
9728 (define_insn "sibcall_epilogue"
9729   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9730               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9731   "TARGET_ARM"
9732   "*
9733   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9734     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9735   return arm_output_epilogue (next_nonnote_insn (insn));
9736   "
9737 ;; Length is absolute worst case
9738   [(set_attr "length" "44")
9739    (set_attr "type" "block")
9740    ;; We don't clobber the conditions, but the potential length of this
9741    ;; operation is sufficient to make conditionalizing the sequence 
9742    ;; unlikely to be profitable.
9743    (set_attr "conds" "clob")]
9744 )
9745
9746 (define_insn "*epilogue_insns"
9747   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9748   "TARGET_EITHER"
9749   "*
9750   if (TARGET_ARM)
9751     return arm_output_epilogue (NULL);
9752   else /* TARGET_THUMB */
9753     return thumb_unexpanded_epilogue ();
9754   "
9755   ; Length is absolute worst case
9756   [(set_attr "length" "44")
9757    (set_attr "type" "block")
9758    ;; We don't clobber the conditions, but the potential length of this
9759    ;; operation is sufficient to make conditionalizing the sequence 
9760    ;; unlikely to be profitable.
9761    (set_attr "conds" "clob")]
9762 )
9763
9764 (define_expand "eh_epilogue"
9765   [(use (match_operand:SI 0 "register_operand" ""))
9766    (use (match_operand:SI 1 "register_operand" ""))
9767    (use (match_operand:SI 2 "register_operand" ""))]
9768   "TARGET_EITHER"
9769   "
9770   {
9771     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9772     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9773       {
9774         rtx ra = gen_rtx_REG (Pmode, 2);
9775
9776         emit_move_insn (ra, operands[2]);
9777         operands[2] = ra;
9778       }
9779     /* This is a hack -- we may have crystalized the function type too
9780        early.  */
9781     cfun->machine->func_type = 0;
9782   }"
9783 )
9784
9785 ;; This split is only used during output to reduce the number of patterns
9786 ;; that need assembler instructions adding to them.  We allowed the setting
9787 ;; of the conditions to be implicit during rtl generation so that
9788 ;; the conditional compare patterns would work.  However this conflicts to
9789 ;; some extent with the conditional data operations, so we have to split them
9790 ;; up again here.
9791
9792 (define_split
9793   [(set (match_operand:SI 0 "s_register_operand" "")
9794         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9795                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9796                          (match_dup 0)
9797                          (match_operand 4 "" "")))
9798    (clobber (reg:CC CC_REGNUM))]
9799   "TARGET_ARM && reload_completed"
9800   [(set (match_dup 5) (match_dup 6))
9801    (cond_exec (match_dup 7)
9802               (set (match_dup 0) (match_dup 4)))]
9803   "
9804   {
9805     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9806                                              operands[2], operands[3]);
9807     enum rtx_code rc = GET_CODE (operands[1]);
9808
9809     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9810     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9811     if (mode == CCFPmode || mode == CCFPEmode)
9812       rc = reverse_condition_maybe_unordered (rc);
9813     else
9814       rc = reverse_condition (rc);
9815
9816     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9817   }"
9818 )
9819
9820 (define_split
9821   [(set (match_operand:SI 0 "s_register_operand" "")
9822         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9823                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9824                          (match_operand 4 "" "")
9825                          (match_dup 0)))
9826    (clobber (reg:CC CC_REGNUM))]
9827   "TARGET_ARM && reload_completed"
9828   [(set (match_dup 5) (match_dup 6))
9829    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9830               (set (match_dup 0) (match_dup 4)))]
9831   "
9832   {
9833     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9834                                              operands[2], operands[3]);
9835
9836     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9837     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9838   }"
9839 )
9840
9841 (define_split
9842   [(set (match_operand:SI 0 "s_register_operand" "")
9843         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9844                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9845                          (match_operand 4 "" "")
9846                          (match_operand 5 "" "")))
9847    (clobber (reg:CC CC_REGNUM))]
9848   "TARGET_ARM && reload_completed"
9849   [(set (match_dup 6) (match_dup 7))
9850    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9851               (set (match_dup 0) (match_dup 4)))
9852    (cond_exec (match_dup 8)
9853               (set (match_dup 0) (match_dup 5)))]
9854   "
9855   {
9856     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9857                                              operands[2], operands[3]);
9858     enum rtx_code rc = GET_CODE (operands[1]);
9859
9860     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9861     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9862     if (mode == CCFPmode || mode == CCFPEmode)
9863       rc = reverse_condition_maybe_unordered (rc);
9864     else
9865       rc = reverse_condition (rc);
9866
9867     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9868   }"
9869 )
9870
9871 (define_split
9872   [(set (match_operand:SI 0 "s_register_operand" "")
9873         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9874                           [(match_operand:SI 2 "s_register_operand" "")
9875                            (match_operand:SI 3 "arm_add_operand" "")])
9876                          (match_operand:SI 4 "arm_rhs_operand" "")
9877                          (not:SI
9878                           (match_operand:SI 5 "s_register_operand" ""))))
9879    (clobber (reg:CC CC_REGNUM))]
9880   "TARGET_ARM && reload_completed"
9881   [(set (match_dup 6) (match_dup 7))
9882    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9883               (set (match_dup 0) (match_dup 4)))
9884    (cond_exec (match_dup 8)
9885               (set (match_dup 0) (not:SI (match_dup 5))))]
9886   "
9887   {
9888     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9889                                              operands[2], operands[3]);
9890     enum rtx_code rc = GET_CODE (operands[1]);
9891
9892     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9893     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9894     if (mode == CCFPmode || mode == CCFPEmode)
9895       rc = reverse_condition_maybe_unordered (rc);
9896     else
9897       rc = reverse_condition (rc);
9898
9899     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9900   }"
9901 )
9902
9903 (define_insn "*cond_move_not"
9904   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9905         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9906                           [(match_operand 3 "cc_register" "") (const_int 0)])
9907                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9908                          (not:SI
9909                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9910   "TARGET_ARM"
9911   "@
9912    mvn%D4\\t%0, %2
9913    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9914   [(set_attr "conds" "use")
9915    (set_attr "length" "4,8")]
9916 )
9917
9918 ;; The next two patterns occur when an AND operation is followed by a
9919 ;; scc insn sequence 
9920
9921 (define_insn "*sign_extract_onebit"
9922   [(set (match_operand:SI 0 "s_register_operand" "=r")
9923         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9924                          (const_int 1)
9925                          (match_operand:SI 2 "const_int_operand" "n")))
9926     (clobber (reg:CC CC_REGNUM))]
9927   "TARGET_ARM"
9928   "*
9929     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9930     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9931     return \"mvnne\\t%0, #0\";
9932   "
9933   [(set_attr "conds" "clob")
9934    (set_attr "length" "8")]
9935 )
9936
9937 (define_insn "*not_signextract_onebit"
9938   [(set (match_operand:SI 0 "s_register_operand" "=r")
9939         (not:SI
9940          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9941                           (const_int 1)
9942                           (match_operand:SI 2 "const_int_operand" "n"))))
9943    (clobber (reg:CC CC_REGNUM))]
9944   "TARGET_ARM"
9945   "*
9946     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9947     output_asm_insn (\"tst\\t%1, %2\", operands);
9948     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9949     return \"movne\\t%0, #0\";
9950   "
9951   [(set_attr "conds" "clob")
9952    (set_attr "length" "12")]
9953 )
9954
9955 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9956 ;; expressions.  For simplicity, the first register is also in the unspec
9957 ;; part.
9958 (define_insn "*push_multi"
9959   [(match_parallel 2 "multi_register_push"
9960     [(set (match_operand:BLK 0 "memory_operand" "=m")
9961           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9962                       UNSPEC_PUSH_MULT))])]
9963   "TARGET_ARM"
9964   "*
9965   {
9966     int num_saves = XVECLEN (operands[2], 0);
9967      
9968     /* For the StrongARM at least it is faster to
9969        use STR to store only a single register.  */
9970     if (num_saves == 1)
9971       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9972     else
9973       {
9974         int i;
9975         char pattern[100];
9976
9977         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9978
9979         for (i = 1; i < num_saves; i++)
9980           {
9981             strcat (pattern, \", %|\");
9982             strcat (pattern,
9983                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9984           }
9985
9986         strcat (pattern, \"}\");
9987         output_asm_insn (pattern, operands);
9988       }
9989
9990     return \"\";
9991   }"
9992   [(set_attr "type" "store4")]
9993 )
9994
9995 (define_insn "stack_tie"
9996   [(set (mem:BLK (scratch))
9997         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9998                      (match_operand:SI 1 "s_register_operand" "r")]
9999                     UNSPEC_PRLG_STK))]
10000   ""
10001   ""
10002   [(set_attr "length" "0")]
10003 )
10004
10005 ;; Similarly for the floating point registers
10006 (define_insn "*push_fp_multi"
10007   [(match_parallel 2 "multi_register_push"
10008     [(set (match_operand:BLK 0 "memory_operand" "=m")
10009           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10010                       UNSPEC_PUSH_MULT))])]
10011   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10012   "*
10013   {
10014     char pattern[100];
10015
10016     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10017     output_asm_insn (pattern, operands);
10018     return \"\";
10019   }"
10020   [(set_attr "type" "f_store")]
10021 )
10022
10023 ;; Special patterns for dealing with the constant pool
10024
10025 (define_insn "align_4"
10026   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10027   "TARGET_EITHER"
10028   "*
10029   assemble_align (32);
10030   return \"\";
10031   "
10032 )
10033
10034 (define_insn "align_8"
10035   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10036   "TARGET_EITHER"
10037   "*
10038   assemble_align (64);
10039   return \"\";
10040   "
10041 )
10042
10043 (define_insn "consttable_end"
10044   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10045   "TARGET_EITHER"
10046   "*
10047   making_const_table = FALSE;
10048   return \"\";
10049   "
10050 )
10051
10052 (define_insn "consttable_1"
10053   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10054   "TARGET_THUMB"
10055   "*
10056   making_const_table = TRUE;
10057   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10058   assemble_zeros (3);
10059   return \"\";
10060   "
10061   [(set_attr "length" "4")]
10062 )
10063
10064 (define_insn "consttable_2"
10065   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10066   "TARGET_THUMB"
10067   "*
10068   making_const_table = TRUE;
10069   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10070   assemble_zeros (2);
10071   return \"\";
10072   "
10073   [(set_attr "length" "4")]
10074 )
10075
10076 (define_insn "consttable_4"
10077   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10078   "TARGET_EITHER"
10079   "*
10080   {
10081     making_const_table = TRUE;
10082     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10083       {
10084       case MODE_FLOAT:
10085       {
10086         REAL_VALUE_TYPE r;
10087         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10088         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10089         break;
10090       }
10091       default:
10092         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10093         break;
10094       }
10095     return \"\";
10096   }"
10097   [(set_attr "length" "4")]
10098 )
10099
10100 (define_insn "consttable_8"
10101   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10102   "TARGET_EITHER"
10103   "*
10104   {
10105     making_const_table = TRUE;
10106     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10107       {
10108        case MODE_FLOAT:
10109         {
10110           REAL_VALUE_TYPE r;
10111           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10112           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10113           break;
10114         }
10115       default:
10116         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10117         break;
10118       }
10119     return \"\";
10120   }"
10121   [(set_attr "length" "8")]
10122 )
10123
10124 ;; Miscellaneous Thumb patterns
10125
10126 (define_expand "tablejump"
10127   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10128               (use (label_ref (match_operand 1 "" "")))])]
10129   "TARGET_THUMB"
10130   "
10131   if (flag_pic)
10132     {
10133       /* Hopefully, CSE will eliminate this copy.  */
10134       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10135       rtx reg2 = gen_reg_rtx (SImode);
10136
10137       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10138       operands[0] = reg2;
10139     }
10140   "
10141 )
10142
10143 ;; NB never uses BX.
10144 (define_insn "*thumb_tablejump"
10145   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10146    (use (label_ref (match_operand 1 "" "")))]
10147   "TARGET_THUMB"
10148   "mov\\t%|pc, %0"
10149   [(set_attr "length" "2")]
10150 )
10151
10152 ;; V5 Instructions,
10153
10154 (define_insn "clzsi2"
10155   [(set (match_operand:SI 0 "s_register_operand" "=r")
10156         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10157   "TARGET_ARM && arm_arch5"
10158   "clz%?\\t%0, %1"
10159   [(set_attr "predicable" "yes")])
10160
10161 (define_expand "ffssi2"
10162   [(set (match_operand:SI 0 "s_register_operand" "")
10163         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10164   "TARGET_ARM && arm_arch5"
10165   "
10166   {
10167     rtx t1, t2, t3;
10168
10169     t1 = gen_reg_rtx (SImode);
10170     t2 = gen_reg_rtx (SImode);
10171     t3 = gen_reg_rtx (SImode);
10172
10173     emit_insn (gen_negsi2 (t1, operands[1]));
10174     emit_insn (gen_andsi3 (t2, operands[1], t1));
10175     emit_insn (gen_clzsi2 (t3, t2));
10176     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10177     DONE;
10178   }"
10179 )
10180
10181 (define_expand "ctzsi2"
10182   [(set (match_operand:SI 0 "s_register_operand" "")
10183         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10184   "TARGET_ARM && arm_arch5"
10185   "
10186   {
10187     rtx t1, t2, t3;
10188
10189     t1 = gen_reg_rtx (SImode);
10190     t2 = gen_reg_rtx (SImode);
10191     t3 = gen_reg_rtx (SImode);
10192
10193     emit_insn (gen_negsi2 (t1, operands[1]));
10194     emit_insn (gen_andsi3 (t2, operands[1], t1));
10195     emit_insn (gen_clzsi2 (t3, t2));
10196     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10197     DONE;
10198   }"
10199 )
10200
10201 ;; V5E instructions.
10202
10203 (define_insn "prefetch"
10204   [(prefetch (match_operand:SI 0 "address_operand" "p")
10205              (match_operand:SI 1 "" "")
10206              (match_operand:SI 2 "" ""))]
10207   "TARGET_ARM && arm_arch5e"
10208   "pld\\t%a0")
10209
10210 ;; General predication pattern
10211
10212 (define_cond_exec
10213   [(match_operator 0 "arm_comparison_operator"
10214     [(match_operand 1 "cc_register" "")
10215      (const_int 0)])]
10216   "TARGET_ARM"
10217   ""
10218 )
10219
10220 (define_insn "prologue_use"
10221   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10222   ""
10223   "%@ %0 needed for prologue"
10224 )
10225
10226
10227 ;; Patterns for exception handling
10228
10229 (define_expand "eh_return"
10230   [(use (match_operand 0 "general_operand" ""))]
10231   "TARGET_EITHER"
10232   "
10233   {
10234     if (TARGET_ARM)
10235       emit_insn (gen_arm_eh_return (operands[0]));
10236     else
10237       emit_insn (gen_thumb_eh_return (operands[0]));
10238     DONE;
10239   }"
10240 )
10241                                    
10242 ;; We can't expand this before we know where the link register is stored.
10243 (define_insn_and_split "arm_eh_return"
10244   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10245                     VUNSPEC_EH_RETURN)
10246    (clobber (match_scratch:SI 1 "=&r"))]
10247   "TARGET_ARM"
10248   "#"
10249   "&& reload_completed"
10250   [(const_int 0)]
10251   "
10252   {
10253     arm_set_return_address (operands[0], operands[1]);
10254     DONE;
10255   }"
10256 )
10257
10258 (define_insn_and_split "thumb_eh_return"
10259   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10260                     VUNSPEC_EH_RETURN)
10261    (clobber (match_scratch:SI 1 "=&l"))]
10262   "TARGET_THUMB"
10263   "#"
10264   "&& reload_completed"
10265   [(const_int 0)]
10266   "
10267   {
10268     thumb_set_return_address (operands[0], operands[1]);
10269     DONE;
10270   }"
10271 )
10272
10273 ;; Load the FPA co-processor patterns
10274 (include "fpa.md")
10275 ;; Load the Maverick co-processor patterns
10276 (include "cirrus.md")
10277 ;; Load the Intel Wireless Multimedia Extension patterns
10278 (include "iwmmxt.md")
10279 ;; Load the VFP co-processor patterns
10280 (include "vfp.md")
10281