OSDN Git Service

* config/mips/mips.md (load_call[sd]i): Redefine using :P. Add mode
[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 ;;---------------------------------------------------------------------------
290 ;; Pipeline descriptions
291
292 ;; Processor type.  This is created automatically from arm-cores.def.
293 (include "arm-tune.md")
294
295 ;; True if the generic scheduling description should be used.
296
297 (define_attr "generic_sched" "yes,no"
298         (if_then_else 
299          (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
300          (const_string "no")
301          (const_string "yes")))
302         
303 (include "arm-generic.md")
304 (include "arm926ejs.md")
305 (include "arm1026ejs.md")
306 (include "arm1136jfs.md")
307
308 \f
309 ;;---------------------------------------------------------------------------
310 ;; Insn patterns
311 ;;
312 ;; Addition insns.
313
314 ;; Note: For DImode insns, there is normally no reason why operands should
315 ;; not be in the same register, what we don't want is for something being
316 ;; written to partially overlap something that is an input.
317 ;; Cirrus 64bit additions should not be split because we have a native
318 ;; 64bit addition instructions.
319
320 (define_expand "adddi3"
321  [(parallel
322    [(set (match_operand:DI           0 "s_register_operand" "")
323           (plus:DI (match_operand:DI 1 "s_register_operand" "")
324                    (match_operand:DI 2 "s_register_operand" "")))
325     (clobber (reg:CC CC_REGNUM))])]
326   "TARGET_EITHER"
327   "
328   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
329     {
330       if (!cirrus_fp_register (operands[0], DImode))
331         operands[0] = force_reg (DImode, operands[0]);
332       if (!cirrus_fp_register (operands[1], DImode))
333         operands[1] = force_reg (DImode, operands[1]);
334       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
335       DONE;
336     }
337
338   if (TARGET_THUMB)
339     {
340       if (GET_CODE (operands[1]) != REG)
341         operands[1] = force_reg (SImode, operands[1]);
342       if (GET_CODE (operands[2]) != REG)
343         operands[2] = force_reg (SImode, operands[2]);
344      }
345   "
346 )
347
348 (define_insn "*thumb_adddi3"
349   [(set (match_operand:DI          0 "register_operand" "=l")
350         (plus:DI (match_operand:DI 1 "register_operand" "%0")
351                  (match_operand:DI 2 "register_operand" "l")))
352    (clobber (reg:CC CC_REGNUM))
353   ]
354   "TARGET_THUMB"
355   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
356   [(set_attr "length" "4")]
357 )
358
359 (define_insn_and_split "*arm_adddi3"
360   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
361         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
362                  (match_operand:DI 2 "s_register_operand" "r,  0")))
363    (clobber (reg:CC CC_REGNUM))]
364   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
365   "#"
366   "TARGET_ARM && reload_completed"
367   [(parallel [(set (reg:CC_C CC_REGNUM)
368                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
369                                  (match_dup 1)))
370               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
371    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
372                                (plus:SI (match_dup 4) (match_dup 5))))]
373   "
374   {
375     operands[3] = gen_highpart (SImode, operands[0]);
376     operands[0] = gen_lowpart (SImode, operands[0]);
377     operands[4] = gen_highpart (SImode, operands[1]);
378     operands[1] = gen_lowpart (SImode, operands[1]);
379     operands[5] = gen_highpart (SImode, operands[2]);
380     operands[2] = gen_lowpart (SImode, operands[2]);
381   }"
382   [(set_attr "conds" "clob")
383    (set_attr "length" "8")]
384 )
385
386 (define_insn_and_split "*adddi_sesidi_di"
387   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
388         (plus:DI (sign_extend:DI
389                   (match_operand:SI 2 "s_register_operand" "r,r"))
390                  (match_operand:DI 1 "s_register_operand" "r,0")))
391    (clobber (reg:CC CC_REGNUM))]
392   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
393   "#"
394   "TARGET_ARM && reload_completed"
395   [(parallel [(set (reg:CC_C CC_REGNUM)
396                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
397                                  (match_dup 1)))
398               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
399    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
400                                (plus:SI (ashiftrt:SI (match_dup 2)
401                                                      (const_int 31))
402                                         (match_dup 4))))]
403   "
404   {
405     operands[3] = gen_highpart (SImode, operands[0]);
406     operands[0] = gen_lowpart (SImode, operands[0]);
407     operands[4] = gen_highpart (SImode, operands[1]);
408     operands[1] = gen_lowpart (SImode, operands[1]);
409     operands[2] = gen_lowpart (SImode, operands[2]);
410   }"
411   [(set_attr "conds" "clob")
412    (set_attr "length" "8")]
413 )
414
415 (define_insn_and_split "*adddi_zesidi_di"
416   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
417         (plus:DI (zero_extend:DI
418                   (match_operand:SI 2 "s_register_operand" "r,r"))
419                  (match_operand:DI 1 "s_register_operand" "r,0")))
420    (clobber (reg:CC CC_REGNUM))]
421   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
422   "#"
423   "TARGET_ARM && reload_completed"
424   [(parallel [(set (reg:CC_C CC_REGNUM)
425                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
426                                  (match_dup 1)))
427               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
428    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
429                                (plus:SI (match_dup 4) (const_int 0))))]
430   "
431   {
432     operands[3] = gen_highpart (SImode, operands[0]);
433     operands[0] = gen_lowpart (SImode, operands[0]);
434     operands[4] = gen_highpart (SImode, operands[1]);
435     operands[1] = gen_lowpart (SImode, operands[1]);
436     operands[2] = gen_lowpart (SImode, operands[2]);
437   }"
438   [(set_attr "conds" "clob")
439    (set_attr "length" "8")]
440 )
441
442 (define_expand "addsi3"
443   [(set (match_operand:SI          0 "s_register_operand" "")
444         (plus:SI (match_operand:SI 1 "s_register_operand" "")
445                  (match_operand:SI 2 "reg_or_int_operand" "")))]
446   "TARGET_EITHER"
447   "
448   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
449     {
450       arm_split_constant (PLUS, SImode, NULL_RTX,
451                           INTVAL (operands[2]), operands[0], operands[1],
452                           optimize && !no_new_pseudos);
453       DONE;
454     }
455   "
456 )
457
458 ; If there is a scratch available, this will be faster than synthesizing the
459 ; addition.
460 (define_peephole2
461   [(match_scratch:SI 3 "r")
462    (set (match_operand:SI          0 "arm_general_register_operand" "")
463         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
464                  (match_operand:SI 2 "const_int_operand"  "")))]
465   "TARGET_ARM &&
466    !(const_ok_for_arm (INTVAL (operands[2]))
467      || const_ok_for_arm (-INTVAL (operands[2])))
468     && const_ok_for_arm (~INTVAL (operands[2]))"
469   [(set (match_dup 3) (match_dup 2))
470    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
471   ""
472 )
473
474 (define_insn_and_split "*arm_addsi3"
475   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
476         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
477                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
478   "TARGET_ARM"
479   "@
480    add%?\\t%0, %1, %2
481    sub%?\\t%0, %1, #%n2
482    #"
483   "TARGET_ARM &&
484    GET_CODE (operands[2]) == CONST_INT
485    && !(const_ok_for_arm (INTVAL (operands[2]))
486         || const_ok_for_arm (-INTVAL (operands[2])))"
487   [(clobber (const_int 0))]
488   "
489   arm_split_constant (PLUS, SImode, curr_insn,
490                       INTVAL (operands[2]), operands[0],
491                       operands[1], 0);
492   DONE;
493   "
494   [(set_attr "length" "4,4,16")
495    (set_attr "predicable" "yes")]
496 )
497
498 ;; Register group 'k' is a single register group containing only the stack
499 ;; register.  Trying to reload it will always fail catastrophically,
500 ;; so never allow those alternatives to match if reloading is needed.
501
502 (define_insn "*thumb_addsi3"
503   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
504         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
505                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
506   "TARGET_THUMB"
507   "*
508    static const char * const asms[] = 
509    {
510      \"add\\t%0, %0, %2\",
511      \"sub\\t%0, %0, #%n2\",
512      \"add\\t%0, %1, %2\",
513      \"add\\t%0, %0, %2\",
514      \"add\\t%0, %0, %2\",
515      \"add\\t%0, %1, %2\",
516      \"add\\t%0, %1, %2\"
517    };
518    if ((which_alternative == 2 || which_alternative == 6)
519        && GET_CODE (operands[2]) == CONST_INT
520        && INTVAL (operands[2]) < 0)
521      return \"sub\\t%0, %1, #%n2\";
522    return asms[which_alternative];
523   "
524   [(set_attr "length" "2")]
525 )
526
527 ;; Reloading and elimination of the frame pointer can
528 ;; sometimes cause this optimization to be missed.
529 (define_peephole2
530   [(set (match_operand:SI 0 "arm_general_register_operand" "")
531         (match_operand:SI 1 "const_int_operand" ""))
532    (set (match_dup 0)
533         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
534   "TARGET_THUMB
535    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
536    && (INTVAL (operands[1]) & 3) == 0"
537   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
538   ""
539 )
540
541 (define_insn "*addsi3_compare0"
542   [(set (reg:CC_NOOV CC_REGNUM)
543         (compare:CC_NOOV
544          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
545                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
546          (const_int 0)))
547    (set (match_operand:SI 0 "s_register_operand" "=r,r")
548         (plus:SI (match_dup 1) (match_dup 2)))]
549   "TARGET_ARM"
550   "@
551    add%?s\\t%0, %1, %2
552    sub%?s\\t%0, %1, #%n2"
553   [(set_attr "conds" "set")]
554 )
555
556 (define_insn "*addsi3_compare0_scratch"
557   [(set (reg:CC_NOOV CC_REGNUM)
558         (compare:CC_NOOV
559          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
560                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
561          (const_int 0)))]
562   "TARGET_ARM"
563   "@
564    cmn%?\\t%0, %1
565    cmp%?\\t%0, #%n1"
566   [(set_attr "conds" "set")]
567 )
568
569 ;; These patterns are the same ones as the two regular addsi3_compare0
570 ;; patterns, except we write them slightly different - the combiner
571 ;; tends to generate them this way.
572 (define_insn "*addsi3_compare0_for_combiner"
573   [(set (reg:CC CC_REGNUM)
574         (compare:CC
575          (match_operand:SI 1 "s_register_operand" "r,r")
576          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
577    (set (match_operand:SI 0 "s_register_operand" "=r,r")
578         (plus:SI (match_dup 1) (match_dup 2)))]
579   "TARGET_ARM"
580   "@
581    add%?s\\t%0, %1, %2
582    sub%?s\\t%0, %1, #%n2"
583   [(set_attr "conds" "set")]
584 )
585
586 (define_insn "*addsi3_compare0_scratch_for_combiner"
587   [(set (reg:CC CC_REGNUM)
588         (compare:CC
589          (match_operand:SI 0 "s_register_operand" "r,r")
590          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
591   "TARGET_ARM"
592   "@
593    cmn%?\\t%0, %1
594    cmp%?\\t%0, #%n1"
595   [(set_attr "conds" "set")]
596 )
597
598 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
599 ;; addend is a constant.
600 (define_insn "*cmpsi2_addneg"
601   [(set (reg:CC CC_REGNUM)
602         (compare:CC
603          (match_operand:SI 1 "s_register_operand" "r,r")
604          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
605    (set (match_operand:SI 0 "s_register_operand" "=r,r")
606         (plus:SI (match_dup 1)
607                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
608   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
609   "@
610    sub%?s\\t%0, %1, %2
611    add%?s\\t%0, %1, #%n2"
612   [(set_attr "conds" "set")]
613 )
614
615 ;; Convert the sequence
616 ;;  sub  rd, rn, #1
617 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
618 ;;  bne  dest
619 ;; into
620 ;;  subs rd, rn, #1
621 ;;  bcs  dest   ((unsigned)rn >= 1)
622 ;; similarly for the beq variant using bcc.
623 ;; This is a common looping idiom (while (n--))
624 (define_peephole2
625   [(set (match_operand:SI 0 "arm_general_register_operand" "")
626         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
627                  (const_int -1)))
628    (set (match_operand 2 "cc_register" "")
629         (compare (match_dup 0) (const_int -1)))
630    (set (pc)
631         (if_then_else (match_operator 3 "equality_operator"
632                        [(match_dup 2) (const_int 0)])
633                       (match_operand 4 "" "")
634                       (match_operand 5 "" "")))]
635   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
636   [(parallel[
637     (set (match_dup 2)
638          (compare:CC
639           (match_dup 1) (const_int 1)))
640     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
641    (set (pc)
642         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
643                       (match_dup 4)
644                       (match_dup 5)))]
645   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
646    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
647                                   ? GEU : LTU),
648                                  VOIDmode, 
649                                  operands[2], const0_rtx);"
650 )
651
652 ;; The next four insns work because they compare the result with one of
653 ;; the operands, and we know that the use of the condition code is
654 ;; either GEU or LTU, so we can use the carry flag from the addition
655 ;; instead of doing the compare a second time.
656 (define_insn "*addsi3_compare_op1"
657   [(set (reg:CC_C CC_REGNUM)
658         (compare:CC_C
659          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
660                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
661          (match_dup 1)))
662    (set (match_operand:SI 0 "s_register_operand" "=r,r")
663         (plus:SI (match_dup 1) (match_dup 2)))]
664   "TARGET_ARM"
665   "@
666    add%?s\\t%0, %1, %2
667    sub%?s\\t%0, %1, #%n2"
668   [(set_attr "conds" "set")]
669 )
670
671 (define_insn "*addsi3_compare_op2"
672   [(set (reg:CC_C CC_REGNUM)
673         (compare:CC_C
674          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
675                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
676          (match_dup 2)))
677    (set (match_operand:SI 0 "s_register_operand" "=r,r")
678         (plus:SI (match_dup 1) (match_dup 2)))]
679   "TARGET_ARM"
680   "@
681    add%?s\\t%0, %1, %2
682    sub%?s\\t%0, %1, #%n2"
683   [(set_attr "conds" "set")]
684 )
685
686 (define_insn "*compare_addsi2_op0"
687   [(set (reg:CC_C CC_REGNUM)
688         (compare:CC_C
689          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
690                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
691          (match_dup 0)))]
692   "TARGET_ARM"
693   "@
694    cmn%?\\t%0, %1
695    cmp%?\\t%0, #%n1"
696   [(set_attr "conds" "set")]
697 )
698
699 (define_insn "*compare_addsi2_op1"
700   [(set (reg:CC_C CC_REGNUM)
701         (compare:CC_C
702          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
704          (match_dup 1)))]
705   "TARGET_ARM"
706   "@
707    cmn%?\\t%0, %1
708    cmp%?\\t%0, #%n1"
709   [(set_attr "conds" "set")]
710 )
711
712 (define_insn "*addsi3_carryin"
713   [(set (match_operand:SI 0 "s_register_operand" "=r")
714         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
715                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
716                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
717   "TARGET_ARM"
718   "adc%?\\t%0, %1, %2"
719   [(set_attr "conds" "use")]
720 )
721
722 (define_insn "*addsi3_carryin_shift"
723   [(set (match_operand:SI 0 "s_register_operand" "=r")
724         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
725                  (plus:SI
726                    (match_operator:SI 2 "shift_operator"
727                       [(match_operand:SI 3 "s_register_operand" "r")
728                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
729                     (match_operand:SI 1 "s_register_operand" "r"))))]
730   "TARGET_ARM"
731   "adc%?\\t%0, %1, %3%S2"
732   [(set_attr "conds" "use")
733    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
734                       (const_string "alu_shift")
735                       (const_string "alu_shift_reg")))]
736 )
737
738 (define_insn "*addsi3_carryin_alt1"
739   [(set (match_operand:SI 0 "s_register_operand" "=r")
740         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
741                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
742                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
743   "TARGET_ARM"
744   "adc%?\\t%0, %1, %2"
745   [(set_attr "conds" "use")]
746 )
747
748 (define_insn "*addsi3_carryin_alt2"
749   [(set (match_operand:SI 0 "s_register_operand" "=r")
750         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
751                           (match_operand:SI 1 "s_register_operand" "r"))
752                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
753   "TARGET_ARM"
754   "adc%?\\t%0, %1, %2"
755   [(set_attr "conds" "use")]
756 )
757
758 (define_insn "*addsi3_carryin_alt3"
759   [(set (match_operand:SI 0 "s_register_operand" "=r")
760         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
761                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
762                  (match_operand:SI 1 "s_register_operand" "r")))]
763   "TARGET_ARM"
764   "adc%?\\t%0, %1, %2"
765   [(set_attr "conds" "use")]
766 )
767
768 (define_insn "incscc"
769   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
770         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
771                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
772                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
773   "TARGET_ARM"
774   "@
775   add%d2\\t%0, %1, #1
776   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
777   [(set_attr "conds" "use")
778    (set_attr "length" "4,8")]
779 )
780
781 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
782 (define_split
783   [(set (match_operand:SI 0 "s_register_operand" "")
784         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
785                             (match_operand:SI 2 "s_register_operand" ""))
786                  (const_int -1)))
787    (clobber (match_operand:SI 3 "s_register_operand" ""))]
788   "TARGET_ARM"
789   [(set (match_dup 3) (match_dup 1))
790    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
791   "
792   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
793 ")
794
795 (define_expand "addsf3"
796   [(set (match_operand:SF          0 "s_register_operand" "")
797         (plus:SF (match_operand:SF 1 "s_register_operand" "")
798                  (match_operand:SF 2 "arm_float_add_operand" "")))]
799   "TARGET_ARM && TARGET_HARD_FLOAT"
800   "
801   if (TARGET_MAVERICK
802       && !cirrus_fp_register (operands[2], SFmode))
803     operands[2] = force_reg (SFmode, operands[2]);
804 ")
805
806 (define_expand "adddf3"
807   [(set (match_operand:DF          0 "s_register_operand" "")
808         (plus:DF (match_operand:DF 1 "s_register_operand" "")
809                  (match_operand:DF 2 "arm_float_add_operand" "")))]
810   "TARGET_ARM && TARGET_HARD_FLOAT"
811   "
812   if (TARGET_MAVERICK
813       && !cirrus_fp_register (operands[2], DFmode))
814     operands[2] = force_reg (DFmode, operands[2]);
815 ")
816
817 (define_expand "subdi3"
818  [(parallel
819    [(set (match_operand:DI            0 "s_register_operand" "")
820           (minus:DI (match_operand:DI 1 "s_register_operand" "")
821                     (match_operand:DI 2 "s_register_operand" "")))
822     (clobber (reg:CC CC_REGNUM))])]
823   "TARGET_EITHER"
824   "
825   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
826       && TARGET_ARM
827       && cirrus_fp_register (operands[0], DImode)
828       && cirrus_fp_register (operands[1], DImode))
829     {
830       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
831       DONE;
832     }
833
834   if (TARGET_THUMB)
835     {
836       if (GET_CODE (operands[1]) != REG)
837         operands[1] = force_reg (SImode, operands[1]);
838       if (GET_CODE (operands[2]) != REG)
839         operands[2] = force_reg (SImode, operands[2]);
840      }  
841   "
842 )
843
844 (define_insn "*arm_subdi3"
845   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
846         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
847                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
848    (clobber (reg:CC CC_REGNUM))]
849   "TARGET_ARM"
850   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
851   [(set_attr "conds" "clob")
852    (set_attr "length" "8")]
853 )
854
855 (define_insn "*thumb_subdi3"
856   [(set (match_operand:DI           0 "register_operand" "=l")
857         (minus:DI (match_operand:DI 1 "register_operand"  "0")
858                   (match_operand:DI 2 "register_operand"  "l")))
859    (clobber (reg:CC CC_REGNUM))]
860   "TARGET_THUMB"
861   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
862   [(set_attr "length" "4")]
863 )
864
865 (define_insn "*subdi_di_zesidi"
866   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
867         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
868                   (zero_extend:DI
869                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
870    (clobber (reg:CC CC_REGNUM))]
871   "TARGET_ARM"
872   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
873   [(set_attr "conds" "clob")
874    (set_attr "length" "8")]
875 )
876
877 (define_insn "*subdi_di_sesidi"
878   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
879         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
880                   (sign_extend:DI
881                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
882    (clobber (reg:CC CC_REGNUM))]
883   "TARGET_ARM"
884   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
885   [(set_attr "conds" "clob")
886    (set_attr "length" "8")]
887 )
888
889 (define_insn "*subdi_zesidi_di"
890   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
891         (minus:DI (zero_extend:DI
892                    (match_operand:SI 2 "s_register_operand"  "r,r"))
893                   (match_operand:DI  1 "s_register_operand" "?r,0")))
894    (clobber (reg:CC CC_REGNUM))]
895   "TARGET_ARM"
896   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
897   [(set_attr "conds" "clob")
898    (set_attr "length" "8")]
899 )
900
901 (define_insn "*subdi_sesidi_di"
902   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
903         (minus:DI (sign_extend:DI
904                    (match_operand:SI 2 "s_register_operand"   "r,r"))
905                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
906    (clobber (reg:CC CC_REGNUM))]
907   "TARGET_ARM"
908   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
909   [(set_attr "conds" "clob")
910    (set_attr "length" "8")]
911 )
912
913 (define_insn "*subdi_zesidi_zesidi"
914   [(set (match_operand:DI            0 "s_register_operand" "=r")
915         (minus:DI (zero_extend:DI
916                    (match_operand:SI 1 "s_register_operand"  "r"))
917                   (zero_extend:DI
918                    (match_operand:SI 2 "s_register_operand"  "r"))))
919    (clobber (reg:CC CC_REGNUM))]
920   "TARGET_ARM"
921   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
922   [(set_attr "conds" "clob")
923    (set_attr "length" "8")]
924 )
925
926 (define_expand "subsi3"
927   [(set (match_operand:SI           0 "s_register_operand" "")
928         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
929                   (match_operand:SI 2 "s_register_operand" "")))]
930   "TARGET_EITHER"
931   "
932   if (GET_CODE (operands[1]) == CONST_INT)
933     {
934       if (TARGET_ARM)
935         {
936           arm_split_constant (MINUS, SImode, NULL_RTX,
937                               INTVAL (operands[1]), operands[0],
938                               operands[2], optimize && !no_new_pseudos);
939           DONE;
940         }
941       else /* TARGET_THUMB */
942         operands[1] = force_reg (SImode, operands[1]);
943     }
944   "
945 )
946
947 (define_insn "*thumb_subsi3_insn"
948   [(set (match_operand:SI           0 "register_operand" "=l")
949         (minus:SI (match_operand:SI 1 "register_operand" "l")
950                   (match_operand:SI 2 "register_operand" "l")))]
951   "TARGET_THUMB"
952   "sub\\t%0, %1, %2"
953   [(set_attr "length" "2")]
954 )
955
956 (define_insn_and_split "*arm_subsi3_insn"
957   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
958         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
959                   (match_operand:SI 2 "s_register_operand" "r,r")))]
960   "TARGET_ARM"
961   "@
962    rsb%?\\t%0, %2, %1
963    #"
964   "TARGET_ARM
965    && GET_CODE (operands[1]) == CONST_INT
966    && !const_ok_for_arm (INTVAL (operands[1]))"
967   [(clobber (const_int 0))]
968   "
969   arm_split_constant (MINUS, SImode, curr_insn,
970                       INTVAL (operands[1]), operands[0], operands[2], 0);
971   DONE;
972   "
973   [(set_attr "length" "4,16")
974    (set_attr "predicable" "yes")]
975 )
976
977 (define_peephole2
978   [(match_scratch:SI 3 "r")
979    (set (match_operand:SI 0 "arm_general_register_operand" "")
980         (minus:SI (match_operand:SI 1 "const_int_operand" "")
981                   (match_operand:SI 2 "arm_general_register_operand" "")))]
982   "TARGET_ARM
983    && !const_ok_for_arm (INTVAL (operands[1]))
984    && const_ok_for_arm (~INTVAL (operands[1]))"
985   [(set (match_dup 3) (match_dup 1))
986    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
987   ""
988 )
989
990 (define_insn "*subsi3_compare0"
991   [(set (reg:CC_NOOV CC_REGNUM)
992         (compare:CC_NOOV
993          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
994                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
995          (const_int 0)))
996    (set (match_operand:SI 0 "s_register_operand" "=r,r")
997         (minus:SI (match_dup 1) (match_dup 2)))]
998   "TARGET_ARM"
999   "@
1000    sub%?s\\t%0, %1, %2
1001    rsb%?s\\t%0, %2, %1"
1002   [(set_attr "conds" "set")]
1003 )
1004
1005 (define_insn "decscc"
1006   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1007         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1008                   (match_operator:SI 2 "arm_comparison_operator"
1009                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1010   "TARGET_ARM"
1011   "@
1012    sub%d2\\t%0, %1, #1
1013    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1014   [(set_attr "conds" "use")
1015    (set_attr "length" "*,8")]
1016 )
1017
1018 (define_expand "subsf3"
1019   [(set (match_operand:SF           0 "s_register_operand" "")
1020         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1021                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1022   "TARGET_ARM && TARGET_HARD_FLOAT"
1023   "
1024   if (TARGET_MAVERICK)
1025     {
1026       if (!cirrus_fp_register (operands[1], SFmode))
1027         operands[1] = force_reg (SFmode, operands[1]);
1028       if (!cirrus_fp_register (operands[2], SFmode))
1029         operands[2] = force_reg (SFmode, operands[2]);
1030     }
1031 ")
1032
1033 (define_expand "subdf3"
1034   [(set (match_operand:DF           0 "s_register_operand" "")
1035         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1036                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1037   "TARGET_ARM && TARGET_HARD_FLOAT"
1038   "
1039   if (TARGET_MAVERICK)
1040     {
1041        if (!cirrus_fp_register (operands[1], DFmode))
1042          operands[1] = force_reg (DFmode, operands[1]);
1043        if (!cirrus_fp_register (operands[2], DFmode))
1044          operands[2] = force_reg (DFmode, operands[2]);
1045     }
1046 ")
1047
1048 \f
1049 ;; Multiplication insns
1050
1051 (define_expand "mulsi3"
1052   [(set (match_operand:SI          0 "s_register_operand" "")
1053         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1054                  (match_operand:SI 1 "s_register_operand" "")))]
1055   "TARGET_EITHER"
1056   ""
1057 )
1058
1059 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1060 (define_insn "*arm_mulsi3"
1061   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1062         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1063                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1064   "TARGET_ARM"
1065   "mul%?\\t%0, %2, %1"
1066   [(set_attr "insn" "mul")
1067    (set_attr "predicable" "yes")]
1068 )
1069
1070 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1071 ; 1 and 2; are the same, because reload will make operand 0 match 
1072 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1073 ; this by adding another alternative to match this case, and then `reload' 
1074 ; it ourselves.  This alternative must come first.
1075 (define_insn "*thumb_mulsi3"
1076   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1077         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1078                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1079   "TARGET_THUMB"
1080   "*
1081   if (which_alternative < 2)
1082     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1083   else
1084     return \"mul\\t%0, %0, %2\";
1085   "
1086   [(set_attr "length" "4,4,2")
1087    (set_attr "insn" "mul")]
1088 )
1089
1090 (define_insn "*mulsi3_compare0"
1091   [(set (reg:CC_NOOV CC_REGNUM)
1092         (compare:CC_NOOV (mult:SI
1093                           (match_operand:SI 2 "s_register_operand" "r,r")
1094                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1095                          (const_int 0)))
1096    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1097         (mult:SI (match_dup 2) (match_dup 1)))]
1098   "TARGET_ARM && !arm_arch_xscale"
1099   "mul%?s\\t%0, %2, %1"
1100   [(set_attr "conds" "set")
1101    (set_attr "insn" "muls")]
1102 )
1103
1104 (define_insn "*mulsi_compare0_scratch"
1105   [(set (reg:CC_NOOV CC_REGNUM)
1106         (compare:CC_NOOV (mult:SI
1107                           (match_operand:SI 2 "s_register_operand" "r,r")
1108                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1109                          (const_int 0)))
1110    (clobber (match_scratch:SI 0 "=&r,&r"))]
1111   "TARGET_ARM && !arm_arch_xscale"
1112   "mul%?s\\t%0, %2, %1"
1113   [(set_attr "conds" "set")
1114    (set_attr "insn" "muls")]
1115 )
1116
1117 ;; Unnamed templates to match MLA instruction.
1118
1119 (define_insn "*mulsi3addsi"
1120   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1121         (plus:SI
1122           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1123                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1124           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1125   "TARGET_ARM"
1126   "mla%?\\t%0, %2, %1, %3"
1127   [(set_attr "insn" "mla")
1128    (set_attr "predicable" "yes")]
1129 )
1130
1131 (define_insn "*mulsi3addsi_compare0"
1132   [(set (reg:CC_NOOV CC_REGNUM)
1133         (compare:CC_NOOV
1134          (plus:SI (mult:SI
1135                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1136                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1137                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1138          (const_int 0)))
1139    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1140         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1141                  (match_dup 3)))]
1142   "TARGET_ARM && !arm_arch_xscale"
1143   "mla%?s\\t%0, %2, %1, %3"
1144   [(set_attr "conds" "set")
1145    (set_attr "insn" "mlas")]
1146 )
1147
1148 (define_insn "*mulsi3addsi_compare0_scratch"
1149   [(set (reg:CC_NOOV CC_REGNUM)
1150         (compare:CC_NOOV
1151          (plus:SI (mult:SI
1152                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1153                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1154                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1155          (const_int 0)))
1156    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1157   "TARGET_ARM && !arm_arch_xscale"
1158   "mla%?s\\t%0, %2, %1, %3"
1159   [(set_attr "conds" "set")
1160    (set_attr "insn" "mlas")]
1161 )
1162
1163 ;; Unnamed template to match long long multiply-accumulate (smlal)
1164
1165 (define_insn "*mulsidi3adddi"
1166   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1167         (plus:DI
1168          (mult:DI
1169           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1170           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1171          (match_operand:DI 1 "s_register_operand" "0")))]
1172   "TARGET_ARM && arm_arch3m"
1173   "smlal%?\\t%Q0, %R0, %3, %2"
1174   [(set_attr "insn" "smlal")
1175    (set_attr "predicable" "yes")]
1176 )
1177
1178 (define_insn "mulsidi3"
1179   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1180         (mult:DI
1181          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1182          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1183   "TARGET_ARM && arm_arch3m"
1184   "smull%?\\t%Q0, %R0, %1, %2"
1185   [(set_attr "insn" "smull")
1186    (set_attr "predicable" "yes")]
1187 )
1188
1189 (define_insn "umulsidi3"
1190   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1191         (mult:DI
1192          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1193          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1194   "TARGET_ARM && arm_arch3m"
1195   "umull%?\\t%Q0, %R0, %1, %2"
1196   [(set_attr "insn" "umull")
1197    (set_attr "predicable" "yes")]
1198 )
1199
1200 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1201
1202 (define_insn "*umulsidi3adddi"
1203   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1204         (plus:DI
1205          (mult:DI
1206           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1207           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1208          (match_operand:DI 1 "s_register_operand" "0")))]
1209   "TARGET_ARM && arm_arch3m"
1210   "umlal%?\\t%Q0, %R0, %3, %2"
1211   [(set_attr "insn" "umlal")
1212    (set_attr "predicable" "yes")]
1213 )
1214
1215 (define_insn "smulsi3_highpart"
1216   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1217         (truncate:SI
1218          (lshiftrt:DI
1219           (mult:DI
1220            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1221            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1222           (const_int 32))))
1223    (clobber (match_scratch:SI 3 "=&r,&r"))]
1224   "TARGET_ARM && arm_arch3m"
1225   "smull%?\\t%3, %0, %2, %1"
1226   [(set_attr "insn" "smull")
1227    (set_attr "predicable" "yes")]
1228 )
1229
1230 (define_insn "umulsi3_highpart"
1231   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1232         (truncate:SI
1233          (lshiftrt:DI
1234           (mult:DI
1235            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1236            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1237           (const_int 32))))
1238    (clobber (match_scratch:SI 3 "=&r,&r"))]
1239   "TARGET_ARM && arm_arch3m"
1240   "umull%?\\t%3, %0, %2, %1"
1241   [(set_attr "insn" "umull")
1242    (set_attr "predicable" "yes")]
1243 )
1244
1245 (define_insn "mulhisi3"
1246   [(set (match_operand:SI 0 "s_register_operand" "=r")
1247         (mult:SI (sign_extend:SI
1248                   (match_operand:HI 1 "s_register_operand" "%r"))
1249                  (sign_extend:SI
1250                   (match_operand:HI 2 "s_register_operand" "r"))))]
1251   "TARGET_ARM && arm_arch5e"
1252   "smulbb%?\\t%0, %1, %2"
1253   [(set_attr "insn" "smulxy")
1254    (set_attr "predicable" "yes")]
1255 )
1256
1257 (define_insn "*mulhisi3tb"
1258   [(set (match_operand:SI 0 "s_register_operand" "=r")
1259         (mult:SI (ashiftrt:SI
1260                   (match_operand:SI 1 "s_register_operand" "r")
1261                   (const_int 16))
1262                  (sign_extend:SI
1263                   (match_operand:HI 2 "s_register_operand" "r"))))]
1264   "TARGET_ARM && arm_arch5e"
1265   "smultb%?\\t%0, %1, %2"
1266   [(set_attr "insn" "smulxy")
1267    (set_attr "predicable" "yes")]
1268 )
1269
1270 (define_insn "*mulhisi3bt"
1271   [(set (match_operand:SI 0 "s_register_operand" "=r")
1272         (mult:SI (sign_extend:SI
1273                   (match_operand:HI 1 "s_register_operand" "r"))
1274                  (ashiftrt:SI
1275                   (match_operand:SI 2 "s_register_operand" "r")
1276                   (const_int 16))))]
1277   "TARGET_ARM && arm_arch5e"
1278   "smulbt%?\\t%0, %1, %2"
1279   [(set_attr "insn" "smulxy")
1280    (set_attr "predicable" "yes")]
1281 )
1282
1283 (define_insn "*mulhisi3tt"
1284   [(set (match_operand:SI 0 "s_register_operand" "=r")
1285         (mult:SI (ashiftrt:SI
1286                   (match_operand:SI 1 "s_register_operand" "r")
1287                   (const_int 16))
1288                  (ashiftrt:SI
1289                   (match_operand:SI 2 "s_register_operand" "r")
1290                   (const_int 16))))]
1291   "TARGET_ARM && arm_arch5e"
1292   "smultt%?\\t%0, %1, %2"
1293   [(set_attr "insn" "smulxy")
1294    (set_attr "predicable" "yes")]
1295 )
1296
1297 (define_insn "*mulhisi3addsi"
1298   [(set (match_operand:SI 0 "s_register_operand" "=r")
1299         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1300                  (mult:SI (sign_extend:SI
1301                            (match_operand:HI 2 "s_register_operand" "%r"))
1302                           (sign_extend:SI
1303                            (match_operand:HI 3 "s_register_operand" "r")))))]
1304   "TARGET_ARM && arm_arch5e"
1305   "smlabb%?\\t%0, %2, %3, %1"
1306   [(set_attr "insn" "smlaxy")
1307    (set_attr "predicable" "yes")]
1308 )
1309
1310 (define_insn "*mulhidi3adddi"
1311   [(set (match_operand:DI 0 "s_register_operand" "=r")
1312         (plus:DI
1313           (match_operand:DI 1 "s_register_operand" "0")
1314           (mult:DI (sign_extend:DI
1315                     (match_operand:HI 2 "s_register_operand" "%r"))
1316                    (sign_extend:DI
1317                     (match_operand:HI 3 "s_register_operand" "r")))))]
1318   "TARGET_ARM && arm_arch5e"
1319   "smlalbb%?\\t%Q0, %R0, %2, %3"
1320   [(set_attr "insn" "smlalxy")
1321    (set_attr "predicable" "yes")])
1322
1323 (define_expand "mulsf3"
1324   [(set (match_operand:SF          0 "s_register_operand" "")
1325         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1326                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1327   "TARGET_ARM && TARGET_HARD_FLOAT"
1328   "
1329   if (TARGET_MAVERICK
1330       && !cirrus_fp_register (operands[2], SFmode))
1331     operands[2] = force_reg (SFmode, operands[2]);
1332 ")
1333
1334 (define_expand "muldf3"
1335   [(set (match_operand:DF          0 "s_register_operand" "")
1336         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1337                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1338   "TARGET_ARM && TARGET_HARD_FLOAT"
1339   "
1340   if (TARGET_MAVERICK
1341       && !cirrus_fp_register (operands[2], DFmode))
1342     operands[2] = force_reg (DFmode, operands[2]);
1343 ")
1344 \f
1345 ;; Division insns
1346
1347 (define_expand "divsf3"
1348   [(set (match_operand:SF 0 "s_register_operand" "")
1349         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1350                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1351   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1352   "")
1353
1354 (define_expand "divdf3"
1355   [(set (match_operand:DF 0 "s_register_operand" "")
1356         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1357                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1358   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1359   "")
1360 \f
1361 ;; Modulo insns
1362
1363 (define_expand "modsf3"
1364   [(set (match_operand:SF 0 "s_register_operand" "")
1365         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1366                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1367   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1368   "")
1369
1370 (define_expand "moddf3"
1371   [(set (match_operand:DF 0 "s_register_operand" "")
1372         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1373                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1374   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1375   "")
1376 \f
1377 ;; Boolean and,ior,xor insns
1378
1379 ;; Split up double word logical operations
1380
1381 ;; Split up simple DImode logical operations.  Simply perform the logical
1382 ;; operation on the upper and lower halves of the registers.
1383 (define_split
1384   [(set (match_operand:DI 0 "s_register_operand" "")
1385         (match_operator:DI 6 "logical_binary_operator"
1386           [(match_operand:DI 1 "s_register_operand" "")
1387            (match_operand:DI 2 "s_register_operand" "")]))]
1388   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1389   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1390    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1391   "
1392   {
1393     operands[3] = gen_highpart (SImode, operands[0]);
1394     operands[0] = gen_lowpart (SImode, operands[0]);
1395     operands[4] = gen_highpart (SImode, operands[1]);
1396     operands[1] = gen_lowpart (SImode, operands[1]);
1397     operands[5] = gen_highpart (SImode, operands[2]);
1398     operands[2] = gen_lowpart (SImode, operands[2]);
1399   }"
1400 )
1401
1402 (define_split
1403   [(set (match_operand:DI 0 "s_register_operand" "")
1404         (match_operator:DI 6 "logical_binary_operator"
1405           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1406            (match_operand:DI 1 "s_register_operand" "")]))]
1407   "TARGET_ARM && reload_completed"
1408   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1409    (set (match_dup 3) (match_op_dup:SI 6
1410                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1411                          (match_dup 4)]))]
1412   "
1413   {
1414     operands[3] = gen_highpart (SImode, operands[0]);
1415     operands[0] = gen_lowpart (SImode, operands[0]);
1416     operands[4] = gen_highpart (SImode, operands[1]);
1417     operands[1] = gen_lowpart (SImode, operands[1]);
1418     operands[5] = gen_highpart (SImode, operands[2]);
1419     operands[2] = gen_lowpart (SImode, operands[2]);
1420   }"
1421 )
1422
1423 ;; The zero extend of operand 2 means we can just copy the high part of
1424 ;; operand1 into operand0.
1425 (define_split
1426   [(set (match_operand:DI 0 "s_register_operand" "")
1427         (ior:DI
1428           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1429           (match_operand:DI 1 "s_register_operand" "")))]
1430   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1431   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1432    (set (match_dup 3) (match_dup 4))]
1433   "
1434   {
1435     operands[4] = gen_highpart (SImode, operands[1]);
1436     operands[3] = gen_highpart (SImode, operands[0]);
1437     operands[0] = gen_lowpart (SImode, operands[0]);
1438     operands[1] = gen_lowpart (SImode, operands[1]);
1439   }"
1440 )
1441
1442 ;; The zero extend of operand 2 means we can just copy the high part of
1443 ;; operand1 into operand0.
1444 (define_split
1445   [(set (match_operand:DI 0 "s_register_operand" "")
1446         (xor:DI
1447           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1448           (match_operand:DI 1 "s_register_operand" "")))]
1449   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1450   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1451    (set (match_dup 3) (match_dup 4))]
1452   "
1453   {
1454     operands[4] = gen_highpart (SImode, operands[1]);
1455     operands[3] = gen_highpart (SImode, operands[0]);
1456     operands[0] = gen_lowpart (SImode, operands[0]);
1457     operands[1] = gen_lowpart (SImode, operands[1]);
1458   }"
1459 )
1460
1461 (define_insn "anddi3"
1462   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1463         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1464                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1465   "TARGET_ARM && ! TARGET_IWMMXT"
1466   "#"
1467   [(set_attr "length" "8")]
1468 )
1469
1470 (define_insn_and_split "*anddi_zesidi_di"
1471   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1472         (and:DI (zero_extend:DI
1473                  (match_operand:SI 2 "s_register_operand" "r,r"))
1474                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1475   "TARGET_ARM"
1476   "#"
1477   "TARGET_ARM && reload_completed"
1478   ; The zero extend of operand 2 clears the high word of the output
1479   ; operand.
1480   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1481    (set (match_dup 3) (const_int 0))]
1482   "
1483   {
1484     operands[3] = gen_highpart (SImode, operands[0]);
1485     operands[0] = gen_lowpart (SImode, operands[0]);
1486     operands[1] = gen_lowpart (SImode, operands[1]);
1487   }"
1488   [(set_attr "length" "8")]
1489 )
1490
1491 (define_insn "*anddi_sesdi_di"
1492   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1493         (and:DI (sign_extend:DI
1494                  (match_operand:SI 2 "s_register_operand" "r,r"))
1495                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1496   "TARGET_ARM"
1497   "#"
1498   [(set_attr "length" "8")]
1499 )
1500
1501 (define_expand "andsi3"
1502   [(set (match_operand:SI         0 "s_register_operand" "")
1503         (and:SI (match_operand:SI 1 "s_register_operand" "")
1504                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1505   "TARGET_EITHER"
1506   "
1507   if (TARGET_ARM)
1508     {
1509       if (GET_CODE (operands[2]) == CONST_INT)
1510         {
1511           arm_split_constant (AND, SImode, NULL_RTX,
1512                               INTVAL (operands[2]), operands[0],
1513                               operands[1], optimize && !no_new_pseudos);
1514
1515           DONE;
1516         }
1517     }
1518   else /* TARGET_THUMB */
1519     {
1520       if (GET_CODE (operands[2]) != CONST_INT)
1521         operands[2] = force_reg (SImode, operands[2]);
1522       else
1523         {
1524           int i;
1525           
1526           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1527             {
1528               operands[2] = force_reg (SImode,
1529                                        GEN_INT (~INTVAL (operands[2])));
1530               
1531               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1532               
1533               DONE;
1534             }
1535
1536           for (i = 9; i <= 31; i++)
1537             {
1538               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1539                 {
1540                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1541                                         const0_rtx));
1542                   DONE;
1543                 }
1544               else if ((((HOST_WIDE_INT) 1) << i) - 1
1545                        == ~INTVAL (operands[2]))
1546                 {
1547                   rtx shift = GEN_INT (i);
1548                   rtx reg = gen_reg_rtx (SImode);
1549                 
1550                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1551                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1552                   
1553                   DONE;
1554                 }
1555             }
1556
1557           operands[2] = force_reg (SImode, operands[2]);
1558         }
1559     }
1560   "
1561 )
1562
1563 (define_insn_and_split "*arm_andsi3_insn"
1564   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1565         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1566                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1567   "TARGET_ARM"
1568   "@
1569    and%?\\t%0, %1, %2
1570    bic%?\\t%0, %1, #%B2
1571    #"
1572   "TARGET_ARM
1573    && GET_CODE (operands[2]) == CONST_INT
1574    && !(const_ok_for_arm (INTVAL (operands[2]))
1575         || const_ok_for_arm (~INTVAL (operands[2])))"
1576   [(clobber (const_int 0))]
1577   "
1578   arm_split_constant  (AND, SImode, curr_insn, 
1579                        INTVAL (operands[2]), operands[0], operands[1], 0);
1580   DONE;
1581   "
1582   [(set_attr "length" "4,4,16")
1583    (set_attr "predicable" "yes")]
1584 )
1585
1586 (define_insn "*thumb_andsi3_insn"
1587   [(set (match_operand:SI         0 "register_operand" "=l")
1588         (and:SI (match_operand:SI 1 "register_operand" "%0")
1589                 (match_operand:SI 2 "register_operand" "l")))]
1590   "TARGET_THUMB"
1591   "and\\t%0, %0, %2"
1592   [(set_attr "length" "2")]
1593 )
1594
1595 (define_insn "*andsi3_compare0"
1596   [(set (reg:CC_NOOV CC_REGNUM)
1597         (compare:CC_NOOV
1598          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1599                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1600          (const_int 0)))
1601    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1602         (and:SI (match_dup 1) (match_dup 2)))]
1603   "TARGET_ARM"
1604   "@
1605    and%?s\\t%0, %1, %2
1606    bic%?s\\t%0, %1, #%B2"
1607   [(set_attr "conds" "set")]
1608 )
1609
1610 (define_insn "*andsi3_compare0_scratch"
1611   [(set (reg:CC_NOOV CC_REGNUM)
1612         (compare:CC_NOOV
1613          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1614                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1615          (const_int 0)))
1616    (clobber (match_scratch:SI 2 "=X,r"))]
1617   "TARGET_ARM"
1618   "@
1619    tst%?\\t%0, %1
1620    bic%?s\\t%2, %0, #%B1"
1621   [(set_attr "conds" "set")]
1622 )
1623
1624 (define_insn "*zeroextractsi_compare0_scratch"
1625   [(set (reg:CC_NOOV CC_REGNUM)
1626         (compare:CC_NOOV (zero_extract:SI
1627                           (match_operand:SI 0 "s_register_operand" "r")
1628                           (match_operand 1 "const_int_operand" "n")
1629                           (match_operand 2 "const_int_operand" "n"))
1630                          (const_int 0)))]
1631   "TARGET_ARM
1632   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1633       && INTVAL (operands[1]) > 0 
1634       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1635       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1636   "*
1637   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1638                          << INTVAL (operands[2]));
1639   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1640   return \"\";
1641   "
1642   [(set_attr "conds" "set")]
1643 )
1644
1645 (define_insn_and_split "*ne_zeroextractsi"
1646   [(set (match_operand:SI 0 "s_register_operand" "=r")
1647         (ne:SI (zero_extract:SI
1648                 (match_operand:SI 1 "s_register_operand" "r")
1649                 (match_operand:SI 2 "const_int_operand" "n")
1650                 (match_operand:SI 3 "const_int_operand" "n"))
1651                (const_int 0)))
1652    (clobber (reg:CC CC_REGNUM))]
1653   "TARGET_ARM
1654    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1655        && INTVAL (operands[2]) > 0 
1656        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1657        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1658   "#"
1659   "TARGET_ARM
1660    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1661        && INTVAL (operands[2]) > 0 
1662        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1663        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1664   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1665                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1666                                     (const_int 0)))
1667               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1668    (set (match_dup 0)
1669         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1670                          (match_dup 0) (const_int 1)))]
1671   "
1672   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1673                          << INTVAL (operands[3])); 
1674   "
1675   [(set_attr "conds" "clob")
1676    (set_attr "length" "8")]
1677 )
1678
1679 (define_insn_and_split "*ne_zeroextractsi_shifted"
1680   [(set (match_operand:SI 0 "s_register_operand" "=r")
1681         (ne:SI (zero_extract:SI
1682                 (match_operand:SI 1 "s_register_operand" "r")
1683                 (match_operand:SI 2 "const_int_operand" "n")
1684                 (const_int 0))
1685                (const_int 0)))
1686    (clobber (reg:CC CC_REGNUM))]
1687   "TARGET_ARM"
1688   "#"
1689   "TARGET_ARM"
1690   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1691                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1692                                     (const_int 0)))
1693               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1694    (set (match_dup 0)
1695         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1696                          (match_dup 0) (const_int 1)))]
1697   "
1698   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1699   "
1700   [(set_attr "conds" "clob")
1701    (set_attr "length" "8")]
1702 )
1703
1704 (define_insn_and_split "*ite_ne_zeroextractsi"
1705   [(set (match_operand:SI 0 "s_register_operand" "=r")
1706         (if_then_else:SI (ne (zero_extract:SI
1707                               (match_operand:SI 1 "s_register_operand" "r")
1708                               (match_operand:SI 2 "const_int_operand" "n")
1709                               (match_operand:SI 3 "const_int_operand" "n"))
1710                              (const_int 0))
1711                          (match_operand:SI 4 "arm_not_operand" "rIK")
1712                          (const_int 0)))
1713    (clobber (reg:CC CC_REGNUM))]
1714   "TARGET_ARM
1715    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1716        && INTVAL (operands[2]) > 0 
1717        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1718        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1719    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1720   "#"
1721   "TARGET_ARM
1722    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1723        && INTVAL (operands[2]) > 0 
1724        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1725        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1726    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1727   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1728                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1729                                     (const_int 0)))
1730               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1731    (set (match_dup 0)
1732         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1733                          (match_dup 0) (match_dup 4)))]
1734   "
1735   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1736                          << INTVAL (operands[3])); 
1737   "
1738   [(set_attr "conds" "clob")
1739    (set_attr "length" "8")]
1740 )
1741
1742 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1743   [(set (match_operand:SI 0 "s_register_operand" "=r")
1744         (if_then_else:SI (ne (zero_extract:SI
1745                               (match_operand:SI 1 "s_register_operand" "r")
1746                               (match_operand:SI 2 "const_int_operand" "n")
1747                               (const_int 0))
1748                              (const_int 0))
1749                          (match_operand:SI 3 "arm_not_operand" "rIK")
1750                          (const_int 0)))
1751    (clobber (reg:CC CC_REGNUM))]
1752   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1753   "#"
1754   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1755   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1756                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1757                                     (const_int 0)))
1758               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1759    (set (match_dup 0)
1760         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1761                          (match_dup 0) (match_dup 3)))]
1762   "
1763   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1764   "
1765   [(set_attr "conds" "clob")
1766    (set_attr "length" "8")]
1767 )
1768
1769 (define_split
1770   [(set (match_operand:SI 0 "s_register_operand" "")
1771         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1772                          (match_operand:SI 2 "const_int_operand" "")
1773                          (match_operand:SI 3 "const_int_operand" "")))
1774    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1775   "TARGET_THUMB"
1776   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1777    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1778   "{
1779      HOST_WIDE_INT temp = INTVAL (operands[2]);
1780
1781      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1782      operands[3] = GEN_INT (32 - temp);
1783    }"
1784 )
1785
1786 (define_split
1787   [(set (match_operand:SI 0 "s_register_operand" "")
1788         (match_operator:SI 1 "shiftable_operator"
1789          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1790                            (match_operand:SI 3 "const_int_operand" "")
1791                            (match_operand:SI 4 "const_int_operand" ""))
1792           (match_operand:SI 5 "s_register_operand" "")]))
1793    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1794   "TARGET_ARM"
1795   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1796    (set (match_dup 0)
1797         (match_op_dup 1
1798          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1799           (match_dup 5)]))]
1800   "{
1801      HOST_WIDE_INT temp = INTVAL (operands[3]);
1802
1803      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1804      operands[4] = GEN_INT (32 - temp);
1805    }"
1806 )
1807   
1808 (define_split
1809   [(set (match_operand:SI 0 "s_register_operand" "")
1810         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1811                          (match_operand:SI 2 "const_int_operand" "")
1812                          (match_operand:SI 3 "const_int_operand" "")))]
1813   "TARGET_THUMB"
1814   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1815    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1816   "{
1817      HOST_WIDE_INT temp = INTVAL (operands[2]);
1818
1819      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1820      operands[3] = GEN_INT (32 - temp);
1821    }"
1822 )
1823
1824 (define_split
1825   [(set (match_operand:SI 0 "s_register_operand" "")
1826         (match_operator:SI 1 "shiftable_operator"
1827          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1828                            (match_operand:SI 3 "const_int_operand" "")
1829                            (match_operand:SI 4 "const_int_operand" ""))
1830           (match_operand:SI 5 "s_register_operand" "")]))
1831    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1832   "TARGET_ARM"
1833   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1834    (set (match_dup 0)
1835         (match_op_dup 1
1836          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1837           (match_dup 5)]))]
1838   "{
1839      HOST_WIDE_INT temp = INTVAL (operands[3]);
1840
1841      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1842      operands[4] = GEN_INT (32 - temp);
1843    }"
1844 )
1845   
1846 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1847 ;;; represented by the bitfield, then this will produce incorrect results.
1848 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1849 ;;; which have a real bit-field insert instruction, the truncation happens
1850 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1851 ;;; bit-field insert instruction, we would have to emit code here to truncate
1852 ;;; the value before we insert.  This loses some of the advantage of having
1853 ;;; this insv pattern, so this pattern needs to be reevalutated.
1854
1855 (define_expand "insv"
1856   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1857                          (match_operand:SI 1 "general_operand" "")
1858                          (match_operand:SI 2 "general_operand" ""))
1859         (match_operand:SI 3 "reg_or_int_operand" ""))]
1860   "TARGET_ARM"
1861   "
1862   {
1863     int start_bit = INTVAL (operands[2]);
1864     int width = INTVAL (operands[1]);
1865     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1866     rtx target, subtarget;
1867
1868     target = operands[0];
1869     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1870        subreg as the final target.  */
1871     if (GET_CODE (target) == SUBREG)
1872       {
1873         subtarget = gen_reg_rtx (SImode);
1874         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1875             < GET_MODE_SIZE (SImode))
1876           target = SUBREG_REG (target);
1877       }
1878     else
1879       subtarget = target;    
1880
1881     if (GET_CODE (operands[3]) == CONST_INT)
1882       {
1883         /* Since we are inserting a known constant, we may be able to
1884            reduce the number of bits that we have to clear so that
1885            the mask becomes simple.  */
1886         /* ??? This code does not check to see if the new mask is actually
1887            simpler.  It may not be.  */
1888         rtx op1 = gen_reg_rtx (SImode);
1889         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1890            start of this pattern.  */
1891         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1892         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1893
1894         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1895         emit_insn (gen_iorsi3 (subtarget, op1,
1896                                GEN_INT (op3_value << start_bit)));
1897       }
1898     else if (start_bit == 0
1899              && !(const_ok_for_arm (mask)
1900                   || const_ok_for_arm (~mask)))
1901       {
1902         /* A Trick, since we are setting the bottom bits in the word,
1903            we can shift operand[3] up, operand[0] down, OR them together
1904            and rotate the result back again.  This takes 3 insns, and
1905            the third might be mergeable into another op.  */
1906         /* The shift up copes with the possibility that operand[3] is
1907            wider than the bitfield.  */
1908         rtx op0 = gen_reg_rtx (SImode);
1909         rtx op1 = gen_reg_rtx (SImode);
1910
1911         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1912         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1913         emit_insn (gen_iorsi3  (op1, op1, op0));
1914         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1915       }
1916     else if ((width + start_bit == 32)
1917              && !(const_ok_for_arm (mask)
1918                   || const_ok_for_arm (~mask)))
1919       {
1920         /* Similar trick, but slightly less efficient.  */
1921
1922         rtx op0 = gen_reg_rtx (SImode);
1923         rtx op1 = gen_reg_rtx (SImode);
1924
1925         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1926         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1927         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1928         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1929       }
1930     else
1931       {
1932         rtx op0 = GEN_INT (mask);
1933         rtx op1 = gen_reg_rtx (SImode);
1934         rtx op2 = gen_reg_rtx (SImode);
1935
1936         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1937           {
1938             rtx tmp = gen_reg_rtx (SImode);
1939
1940             emit_insn (gen_movsi (tmp, op0));
1941             op0 = tmp;
1942           }
1943
1944         /* Mask out any bits in operand[3] that are not needed.  */
1945            emit_insn (gen_andsi3 (op1, operands[3], op0));
1946
1947         if (GET_CODE (op0) == CONST_INT
1948             && (const_ok_for_arm (mask << start_bit)
1949                 || const_ok_for_arm (~(mask << start_bit))))
1950           {
1951             op0 = GEN_INT (~(mask << start_bit));
1952             emit_insn (gen_andsi3 (op2, operands[0], op0));
1953           }
1954         else
1955           {
1956             if (GET_CODE (op0) == CONST_INT)
1957               {
1958                 rtx tmp = gen_reg_rtx (SImode);
1959
1960                 emit_insn (gen_movsi (tmp, op0));
1961                 op0 = tmp;
1962               }
1963
1964             if (start_bit != 0)
1965               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1966             
1967             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1968           }
1969
1970         if (start_bit != 0)
1971           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1972
1973         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1974       }
1975
1976     if (subtarget != target)
1977       {
1978         /* If TARGET is still a SUBREG, then it must be wider than a word,
1979            so we must be careful only to set the subword we were asked to.  */
1980         if (GET_CODE (target) == SUBREG)
1981           emit_move_insn (target, subtarget);
1982         else
1983           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1984       }
1985
1986     DONE;
1987   }"
1988 )
1989
1990 ; constants for op 2 will never be given to these patterns.
1991 (define_insn_and_split "*anddi_notdi_di"
1992   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1993         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1994                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1995   "TARGET_ARM"
1996   "#"
1997   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1998   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1999    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2000   "
2001   {
2002     operands[3] = gen_highpart (SImode, operands[0]);
2003     operands[0] = gen_lowpart (SImode, operands[0]);
2004     operands[4] = gen_highpart (SImode, operands[1]);
2005     operands[1] = gen_lowpart (SImode, operands[1]);
2006     operands[5] = gen_highpart (SImode, operands[2]);
2007     operands[2] = gen_lowpart (SImode, operands[2]);
2008   }"
2009   [(set_attr "length" "8")
2010    (set_attr "predicable" "yes")]
2011 )
2012   
2013 (define_insn_and_split "*anddi_notzesidi_di"
2014   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2015         (and:DI (not:DI (zero_extend:DI
2016                          (match_operand:SI 2 "s_register_operand" "r,r")))
2017                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2018   "TARGET_ARM"
2019   "@
2020    bic%?\\t%Q0, %Q1, %2
2021    #"
2022   ; (not (zero_extend ...)) allows us to just copy the high word from
2023   ; operand1 to operand0.
2024   "TARGET_ARM
2025    && reload_completed
2026    && operands[0] != operands[1]"
2027   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2028    (set (match_dup 3) (match_dup 4))]
2029   "
2030   {
2031     operands[3] = gen_highpart (SImode, operands[0]);
2032     operands[0] = gen_lowpart (SImode, operands[0]);
2033     operands[4] = gen_highpart (SImode, operands[1]);
2034     operands[1] = gen_lowpart (SImode, operands[1]);
2035   }"
2036   [(set_attr "length" "4,8")
2037    (set_attr "predicable" "yes")]
2038 )
2039   
2040 (define_insn_and_split "*anddi_notsesidi_di"
2041   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2042         (and:DI (not:DI (sign_extend:DI
2043                          (match_operand:SI 2 "s_register_operand" "r,r")))
2044                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2045   "TARGET_ARM"
2046   "#"
2047   "TARGET_ARM && reload_completed"
2048   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2049    (set (match_dup 3) (and:SI (not:SI
2050                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2051                                (match_dup 4)))]
2052   "
2053   {
2054     operands[3] = gen_highpart (SImode, operands[0]);
2055     operands[0] = gen_lowpart (SImode, operands[0]);
2056     operands[4] = gen_highpart (SImode, operands[1]);
2057     operands[1] = gen_lowpart (SImode, operands[1]);
2058   }"
2059   [(set_attr "length" "8")
2060    (set_attr "predicable" "yes")]
2061 )
2062   
2063 (define_insn "andsi_notsi_si"
2064   [(set (match_operand:SI 0 "s_register_operand" "=r")
2065         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2066                 (match_operand:SI 1 "s_register_operand" "r")))]
2067   "TARGET_ARM"
2068   "bic%?\\t%0, %1, %2"
2069   [(set_attr "predicable" "yes")]
2070 )
2071
2072 (define_insn "bicsi3"
2073   [(set (match_operand:SI                 0 "register_operand" "=l")
2074         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2075                 (match_operand:SI         2 "register_operand" "0")))]
2076   "TARGET_THUMB"
2077   "bic\\t%0, %0, %1"
2078   [(set_attr "length" "2")]
2079 )
2080
2081 (define_insn "andsi_not_shiftsi_si"
2082   [(set (match_operand:SI 0 "s_register_operand" "=r")
2083         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2084                          [(match_operand:SI 2 "s_register_operand" "r")
2085                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2086                 (match_operand:SI 1 "s_register_operand" "r")))]
2087   "TARGET_ARM"
2088   "bic%?\\t%0, %1, %2%S4"
2089   [(set_attr "predicable" "yes")
2090    (set_attr "shift" "2")
2091    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2092                       (const_string "alu_shift")
2093                       (const_string "alu_shift_reg")))]
2094 )
2095
2096 (define_insn "*andsi_notsi_si_compare0"
2097   [(set (reg:CC_NOOV CC_REGNUM)
2098         (compare:CC_NOOV
2099          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2100                  (match_operand:SI 1 "s_register_operand" "r"))
2101          (const_int 0)))
2102    (set (match_operand:SI 0 "s_register_operand" "=r")
2103         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2104   "TARGET_ARM"
2105   "bic%?s\\t%0, %1, %2"
2106   [(set_attr "conds" "set")]
2107 )
2108
2109 (define_insn "*andsi_notsi_si_compare0_scratch"
2110   [(set (reg:CC_NOOV CC_REGNUM)
2111         (compare:CC_NOOV
2112          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2113                  (match_operand:SI 1 "s_register_operand" "r"))
2114          (const_int 0)))
2115    (clobber (match_scratch:SI 0 "=r"))]
2116   "TARGET_ARM"
2117   "bic%?s\\t%0, %1, %2"
2118   [(set_attr "conds" "set")]
2119 )
2120
2121 (define_insn "iordi3"
2122   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2123         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2124                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2125   "TARGET_ARM && ! TARGET_IWMMXT"
2126   "#"
2127   [(set_attr "length" "8")
2128    (set_attr "predicable" "yes")]
2129 )
2130
2131 (define_insn "*iordi_zesidi_di"
2132   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2133         (ior:DI (zero_extend:DI
2134                  (match_operand:SI 2 "s_register_operand" "r,r"))
2135                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2136   "TARGET_ARM"
2137   "@
2138    orr%?\\t%Q0, %Q1, %2
2139    #"
2140   [(set_attr "length" "4,8")
2141    (set_attr "predicable" "yes")]
2142 )
2143
2144 (define_insn "*iordi_sesidi_di"
2145   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2146         (ior:DI (sign_extend:DI
2147                  (match_operand:SI 2 "s_register_operand" "r,r"))
2148                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2149   "TARGET_ARM"
2150   "#"
2151   [(set_attr "length" "8")
2152    (set_attr "predicable" "yes")]
2153 )
2154
2155 (define_expand "iorsi3"
2156   [(set (match_operand:SI         0 "s_register_operand" "")
2157         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2158                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2159   "TARGET_EITHER"
2160   "
2161   if (GET_CODE (operands[2]) == CONST_INT)
2162     {
2163       if (TARGET_ARM)
2164         {
2165           arm_split_constant (IOR, SImode, NULL_RTX,
2166                               INTVAL (operands[2]), operands[0], operands[1],
2167                               optimize && !no_new_pseudos);
2168           DONE;
2169         }
2170       else /* TARGET_THUMB */
2171         operands [2] = force_reg (SImode, operands [2]);
2172     }
2173   "
2174 )
2175
2176 (define_insn_and_split "*arm_iorsi3"
2177   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2178         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2179                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2180   "TARGET_ARM"
2181   "@
2182    orr%?\\t%0, %1, %2
2183    #"
2184   "TARGET_ARM
2185    && GET_CODE (operands[2]) == CONST_INT
2186    && !const_ok_for_arm (INTVAL (operands[2]))"
2187   [(clobber (const_int 0))]
2188   "
2189   arm_split_constant (IOR, SImode, curr_insn, 
2190                       INTVAL (operands[2]), operands[0], operands[1], 0);
2191   DONE;
2192   "
2193   [(set_attr "length" "4,16")
2194    (set_attr "predicable" "yes")]
2195 )
2196
2197 (define_insn "*thumb_iorsi3"
2198   [(set (match_operand:SI         0 "register_operand" "=l")
2199         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2200                 (match_operand:SI 2 "register_operand" "l")))]
2201   "TARGET_THUMB"
2202   "orr\\t%0, %0, %2"
2203   [(set_attr "length" "2")]
2204 )
2205
2206 (define_peephole2
2207   [(match_scratch:SI 3 "r")
2208    (set (match_operand:SI 0 "arm_general_register_operand" "")
2209         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2210                 (match_operand:SI 2 "const_int_operand" "")))]
2211   "TARGET_ARM
2212    && !const_ok_for_arm (INTVAL (operands[2]))
2213    && const_ok_for_arm (~INTVAL (operands[2]))"
2214   [(set (match_dup 3) (match_dup 2))
2215    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2216   ""
2217 )
2218
2219 (define_insn "*iorsi3_compare0"
2220   [(set (reg:CC_NOOV CC_REGNUM)
2221         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2222                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2223                          (const_int 0)))
2224    (set (match_operand:SI 0 "s_register_operand" "=r")
2225         (ior:SI (match_dup 1) (match_dup 2)))]
2226   "TARGET_ARM"
2227   "orr%?s\\t%0, %1, %2"
2228   [(set_attr "conds" "set")]
2229 )
2230
2231 (define_insn "*iorsi3_compare0_scratch"
2232   [(set (reg:CC_NOOV CC_REGNUM)
2233         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2234                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2235                          (const_int 0)))
2236    (clobber (match_scratch:SI 0 "=r"))]
2237   "TARGET_ARM"
2238   "orr%?s\\t%0, %1, %2"
2239   [(set_attr "conds" "set")]
2240 )
2241
2242 (define_insn "xordi3"
2243   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2244         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2245                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2246   "TARGET_ARM && !TARGET_IWMMXT"
2247   "#"
2248   [(set_attr "length" "8")
2249    (set_attr "predicable" "yes")]
2250 )
2251
2252 (define_insn "*xordi_zesidi_di"
2253   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2254         (xor:DI (zero_extend:DI
2255                  (match_operand:SI 2 "s_register_operand" "r,r"))
2256                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2257   "TARGET_ARM"
2258   "@
2259    eor%?\\t%Q0, %Q1, %2
2260    #"
2261   [(set_attr "length" "4,8")
2262    (set_attr "predicable" "yes")]
2263 )
2264
2265 (define_insn "*xordi_sesidi_di"
2266   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2267         (xor:DI (sign_extend:DI
2268                  (match_operand:SI 2 "s_register_operand" "r,r"))
2269                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2270   "TARGET_ARM"
2271   "#"
2272   [(set_attr "length" "8")
2273    (set_attr "predicable" "yes")]
2274 )
2275
2276 (define_expand "xorsi3"
2277   [(set (match_operand:SI         0 "s_register_operand" "")
2278         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2279                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2280   "TARGET_EITHER"
2281   "if (TARGET_THUMB)
2282      if (GET_CODE (operands[2]) == CONST_INT)
2283        operands[2] = force_reg (SImode, operands[2]);
2284   "
2285 )
2286
2287 (define_insn "*arm_xorsi3"
2288   [(set (match_operand:SI         0 "s_register_operand" "=r")
2289         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2290                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2291   "TARGET_ARM"
2292   "eor%?\\t%0, %1, %2"
2293   [(set_attr "predicable" "yes")]
2294 )
2295
2296 (define_insn "*thumb_xorsi3"
2297   [(set (match_operand:SI         0 "register_operand" "=l")
2298         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2299                 (match_operand:SI 2 "register_operand" "l")))]
2300   "TARGET_THUMB"
2301   "eor\\t%0, %0, %2"
2302   [(set_attr "length" "2")]
2303 )
2304
2305 (define_insn "*xorsi3_compare0"
2306   [(set (reg:CC_NOOV CC_REGNUM)
2307         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2308                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2309                          (const_int 0)))
2310    (set (match_operand:SI 0 "s_register_operand" "=r")
2311         (xor:SI (match_dup 1) (match_dup 2)))]
2312   "TARGET_ARM"
2313   "eor%?s\\t%0, %1, %2"
2314   [(set_attr "conds" "set")]
2315 )
2316
2317 (define_insn "*xorsi3_compare0_scratch"
2318   [(set (reg:CC_NOOV CC_REGNUM)
2319         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2320                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2321                          (const_int 0)))]
2322   "TARGET_ARM"
2323   "teq%?\\t%0, %1"
2324   [(set_attr "conds" "set")]
2325 )
2326
2327 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2328 ; (NOT D) we can sometimes merge the final NOT into one of the following
2329 ; insns.
2330
2331 (define_split
2332   [(set (match_operand:SI 0 "s_register_operand" "")
2333         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2334                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2335                 (match_operand:SI 3 "arm_rhs_operand" "")))
2336    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2337   "TARGET_ARM"
2338   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2339                               (not:SI (match_dup 3))))
2340    (set (match_dup 0) (not:SI (match_dup 4)))]
2341   ""
2342 )
2343
2344 (define_insn "*andsi_iorsi3_notsi"
2345   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2346         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2347                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2348                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2349   "TARGET_ARM"
2350   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2351   [(set_attr "length" "8")
2352    (set_attr "predicable" "yes")]
2353 )
2354
2355 (define_split
2356   [(set (match_operand:SI 0 "s_register_operand" "")
2357         (match_operator:SI 1 "logical_binary_operator"
2358          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2359                            (match_operand:SI 3 "const_int_operand" "")
2360                            (match_operand:SI 4 "const_int_operand" ""))
2361           (match_operator:SI 9 "logical_binary_operator"
2362            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2363                          (match_operand:SI 6 "const_int_operand" ""))
2364             (match_operand:SI 7 "s_register_operand" "")])]))
2365    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2366   "TARGET_ARM
2367    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2368    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2369   [(set (match_dup 8)
2370         (match_op_dup 1
2371          [(ashift:SI (match_dup 2) (match_dup 4))
2372           (match_dup 5)]))
2373    (set (match_dup 0)
2374         (match_op_dup 1
2375          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2376           (match_dup 7)]))]
2377   "
2378   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2379 ")
2380
2381 (define_split
2382   [(set (match_operand:SI 0 "s_register_operand" "")
2383         (match_operator:SI 1 "logical_binary_operator"
2384          [(match_operator:SI 9 "logical_binary_operator"
2385            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2386                          (match_operand:SI 6 "const_int_operand" ""))
2387             (match_operand:SI 7 "s_register_operand" "")])
2388           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2389                            (match_operand:SI 3 "const_int_operand" "")
2390                            (match_operand:SI 4 "const_int_operand" ""))]))
2391    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2392   "TARGET_ARM
2393    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2394    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2395   [(set (match_dup 8)
2396         (match_op_dup 1
2397          [(ashift:SI (match_dup 2) (match_dup 4))
2398           (match_dup 5)]))
2399    (set (match_dup 0)
2400         (match_op_dup 1
2401          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2402           (match_dup 7)]))]
2403   "
2404   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2405 ")
2406
2407 (define_split
2408   [(set (match_operand:SI 0 "s_register_operand" "")
2409         (match_operator:SI 1 "logical_binary_operator"
2410          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2411                            (match_operand:SI 3 "const_int_operand" "")
2412                            (match_operand:SI 4 "const_int_operand" ""))
2413           (match_operator:SI 9 "logical_binary_operator"
2414            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2415                          (match_operand:SI 6 "const_int_operand" ""))
2416             (match_operand:SI 7 "s_register_operand" "")])]))
2417    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2418   "TARGET_ARM
2419    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2420    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2421   [(set (match_dup 8)
2422         (match_op_dup 1
2423          [(ashift:SI (match_dup 2) (match_dup 4))
2424           (match_dup 5)]))
2425    (set (match_dup 0)
2426         (match_op_dup 1
2427          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2428           (match_dup 7)]))]
2429   "
2430   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2431 ")
2432
2433 (define_split
2434   [(set (match_operand:SI 0 "s_register_operand" "")
2435         (match_operator:SI 1 "logical_binary_operator"
2436          [(match_operator:SI 9 "logical_binary_operator"
2437            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2438                          (match_operand:SI 6 "const_int_operand" ""))
2439             (match_operand:SI 7 "s_register_operand" "")])
2440           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2441                            (match_operand:SI 3 "const_int_operand" "")
2442                            (match_operand:SI 4 "const_int_operand" ""))]))
2443    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2444   "TARGET_ARM
2445    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2446    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2447   [(set (match_dup 8)
2448         (match_op_dup 1
2449          [(ashift:SI (match_dup 2) (match_dup 4))
2450           (match_dup 5)]))
2451    (set (match_dup 0)
2452         (match_op_dup 1
2453          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2454           (match_dup 7)]))]
2455   "
2456   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2457 ")
2458 \f
2459
2460 ;; Minimum and maximum insns
2461
2462 (define_insn "smaxsi3"
2463   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2464         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2465                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2466    (clobber (reg:CC CC_REGNUM))]
2467   "TARGET_ARM"
2468   "@
2469    cmp\\t%1, %2\;movlt\\t%0, %2
2470    cmp\\t%1, %2\;movge\\t%0, %1
2471    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2472   [(set_attr "conds" "clob")
2473    (set_attr "length" "8,8,12")]
2474 )
2475
2476 (define_insn "sminsi3"
2477   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2478         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2479                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2480    (clobber (reg:CC CC_REGNUM))]
2481   "TARGET_ARM"
2482   "@
2483    cmp\\t%1, %2\;movge\\t%0, %2
2484    cmp\\t%1, %2\;movlt\\t%0, %1
2485    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2486   [(set_attr "conds" "clob")
2487    (set_attr "length" "8,8,12")]
2488 )
2489
2490 (define_insn "umaxsi3"
2491   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2492         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2493                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2494    (clobber (reg:CC CC_REGNUM))]
2495   "TARGET_ARM"
2496   "@
2497    cmp\\t%1, %2\;movcc\\t%0, %2
2498    cmp\\t%1, %2\;movcs\\t%0, %1
2499    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2500   [(set_attr "conds" "clob")
2501    (set_attr "length" "8,8,12")]
2502 )
2503
2504 (define_insn "uminsi3"
2505   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2506         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2507                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2508    (clobber (reg:CC CC_REGNUM))]
2509   "TARGET_ARM"
2510   "@
2511    cmp\\t%1, %2\;movcs\\t%0, %2
2512    cmp\\t%1, %2\;movcc\\t%0, %1
2513    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2514   [(set_attr "conds" "clob")
2515    (set_attr "length" "8,8,12")]
2516 )
2517
2518 (define_insn "*store_minmaxsi"
2519   [(set (match_operand:SI 0 "memory_operand" "=m")
2520         (match_operator:SI 3 "minmax_operator"
2521          [(match_operand:SI 1 "s_register_operand" "r")
2522           (match_operand:SI 2 "s_register_operand" "r")]))
2523    (clobber (reg:CC CC_REGNUM))]
2524   "TARGET_ARM"
2525   "*
2526   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2527                                 operands[1], operands[2]);
2528   output_asm_insn (\"cmp\\t%1, %2\", operands);
2529   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2530   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2531   return \"\";
2532   "
2533   [(set_attr "conds" "clob")
2534    (set_attr "length" "12")
2535    (set_attr "type" "store1")]
2536 )
2537
2538 ; Reject the frame pointer in operand[1], since reloading this after
2539 ; it has been eliminated can cause carnage.
2540 (define_insn "*minmax_arithsi"
2541   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2542         (match_operator:SI 4 "shiftable_operator"
2543          [(match_operator:SI 5 "minmax_operator"
2544            [(match_operand:SI 2 "s_register_operand" "r,r")
2545             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2546           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2547    (clobber (reg:CC CC_REGNUM))]
2548   "TARGET_ARM
2549    && (GET_CODE (operands[1]) != REG
2550        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2551            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2552   "*
2553   {
2554     enum rtx_code code = GET_CODE (operands[4]);
2555
2556     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2557                                   operands[2], operands[3]);
2558     output_asm_insn (\"cmp\\t%2, %3\", operands);
2559     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2560     if (which_alternative != 0 || operands[3] != const0_rtx
2561         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2562       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2563     return \"\";
2564   }"
2565   [(set_attr "conds" "clob")
2566    (set_attr "length" "12")]
2567 )
2568
2569 \f
2570 ;; Shift and rotation insns
2571
2572 (define_expand "ashldi3"
2573   [(set (match_operand:DI            0 "s_register_operand" "")
2574         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2575                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2576   "TARGET_ARM"
2577   "
2578   if (GET_CODE (operands[2]) == CONST_INT)
2579     {
2580       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2581         {
2582           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2583           DONE;
2584         }
2585         /* Ideally we shouldn't fail here if we could know that operands[1] 
2586            ends up already living in an iwmmxt register. Otherwise it's
2587            cheaper to have the alternate code being generated than moving
2588            values to iwmmxt regs and back.  */
2589         FAIL;
2590     }
2591   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2592     FAIL;
2593   "
2594 )
2595
2596 (define_insn "arm_ashldi3_1bit"
2597   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2598         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2599                    (const_int 1)))
2600    (clobber (reg:CC CC_REGNUM))]
2601   "TARGET_ARM"
2602   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2603   [(set_attr "conds" "clob")
2604    (set_attr "length" "8")]
2605 )
2606
2607 (define_expand "ashlsi3"
2608   [(set (match_operand:SI            0 "s_register_operand" "")
2609         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2610                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2611   "TARGET_EITHER"
2612   "
2613   if (GET_CODE (operands[2]) == CONST_INT
2614       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2615     {
2616       emit_insn (gen_movsi (operands[0], const0_rtx));
2617       DONE;
2618     }
2619   "
2620 )
2621
2622 (define_insn "*thumb_ashlsi3"
2623   [(set (match_operand:SI            0 "register_operand" "=l,l")
2624         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2625                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2626   "TARGET_THUMB"
2627   "lsl\\t%0, %1, %2"
2628   [(set_attr "length" "2")]
2629 )
2630
2631 (define_expand "ashrdi3"
2632   [(set (match_operand:DI              0 "s_register_operand" "")
2633         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2634                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2635   "TARGET_ARM"
2636   "
2637   if (GET_CODE (operands[2]) == CONST_INT)
2638     {
2639       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2640         {
2641           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2642           DONE;
2643         }
2644         /* Ideally we shouldn't fail here if we could know that operands[1] 
2645            ends up already living in an iwmmxt register. Otherwise it's
2646            cheaper to have the alternate code being generated than moving
2647            values to iwmmxt regs and back.  */
2648         FAIL;
2649     }
2650   else if (!TARGET_REALLY_IWMMXT)
2651     FAIL;
2652   "
2653 )
2654
2655 (define_insn "arm_ashrdi3_1bit"
2656   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2657         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2658                      (const_int 1)))
2659    (clobber (reg:CC CC_REGNUM))]
2660   "TARGET_ARM"
2661   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2662   [(set_attr "conds" "clob")
2663    (set_attr "length" "8")]
2664 )
2665
2666 (define_expand "ashrsi3"
2667   [(set (match_operand:SI              0 "s_register_operand" "")
2668         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2669                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2670   "TARGET_EITHER"
2671   "
2672   if (GET_CODE (operands[2]) == CONST_INT
2673       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2674     operands[2] = GEN_INT (31);
2675   "
2676 )
2677
2678 (define_insn "*thumb_ashrsi3"
2679   [(set (match_operand:SI              0 "register_operand" "=l,l")
2680         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2681                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2682   "TARGET_THUMB"
2683   "asr\\t%0, %1, %2"
2684   [(set_attr "length" "2")]
2685 )
2686
2687 (define_expand "lshrdi3"
2688   [(set (match_operand:DI              0 "s_register_operand" "")
2689         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2690                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2691   "TARGET_ARM"
2692   "
2693   if (GET_CODE (operands[2]) == CONST_INT)
2694     {
2695       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2696         {
2697           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2698           DONE;
2699         }
2700         /* Ideally we shouldn't fail here if we could know that operands[1] 
2701            ends up already living in an iwmmxt register. Otherwise it's
2702            cheaper to have the alternate code being generated than moving
2703            values to iwmmxt regs and back.  */
2704         FAIL;
2705     }
2706   else if (!TARGET_REALLY_IWMMXT)
2707     FAIL;
2708   "
2709 )
2710
2711 (define_insn "arm_lshrdi3_1bit"
2712   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2713         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2714                      (const_int 1)))
2715    (clobber (reg:CC CC_REGNUM))]
2716   "TARGET_ARM"
2717   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2718   [(set_attr "conds" "clob")
2719    (set_attr "length" "8")]
2720 )
2721
2722 (define_expand "lshrsi3"
2723   [(set (match_operand:SI              0 "s_register_operand" "")
2724         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2725                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2726   "TARGET_EITHER"
2727   "
2728   if (GET_CODE (operands[2]) == CONST_INT
2729       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2730     {
2731       emit_insn (gen_movsi (operands[0], const0_rtx));
2732       DONE;
2733     }
2734   "
2735 )
2736
2737 (define_insn "*thumb_lshrsi3"
2738   [(set (match_operand:SI              0 "register_operand" "=l,l")
2739         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2740                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2741   "TARGET_THUMB"
2742   "lsr\\t%0, %1, %2"
2743   [(set_attr "length" "2")]
2744 )
2745
2746 (define_expand "rotlsi3"
2747   [(set (match_operand:SI              0 "s_register_operand" "")
2748         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2749                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2750   "TARGET_ARM"
2751   "
2752   if (GET_CODE (operands[2]) == CONST_INT)
2753     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2754   else
2755     {
2756       rtx reg = gen_reg_rtx (SImode);
2757       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2758       operands[2] = reg;
2759     }
2760   "
2761 )
2762
2763 (define_expand "rotrsi3"
2764   [(set (match_operand:SI              0 "s_register_operand" "")
2765         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2766                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2767   "TARGET_EITHER"
2768   "
2769   if (TARGET_ARM)
2770     {
2771       if (GET_CODE (operands[2]) == CONST_INT
2772           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2773         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2774     }
2775   else /* TARGET_THUMB */
2776     {
2777       if (GET_CODE (operands [2]) == CONST_INT)
2778         operands [2] = force_reg (SImode, operands[2]);
2779     }
2780   "
2781 )
2782
2783 (define_insn "*thumb_rotrsi3"
2784   [(set (match_operand:SI              0 "register_operand" "=l")
2785         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2786                      (match_operand:SI 2 "register_operand" "l")))]
2787   "TARGET_THUMB"
2788   "ror\\t%0, %0, %2"
2789   [(set_attr "length" "2")]
2790 )
2791
2792 (define_insn "*arm_shiftsi3"
2793   [(set (match_operand:SI   0 "s_register_operand" "=r")
2794         (match_operator:SI  3 "shift_operator"
2795          [(match_operand:SI 1 "s_register_operand"  "r")
2796           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2797   "TARGET_ARM"
2798   "mov%?\\t%0, %1%S3"
2799   [(set_attr "predicable" "yes")
2800    (set_attr "shift" "1")
2801    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2802                       (const_string "alu_shift")
2803                       (const_string "alu_shift_reg")))]
2804 )
2805
2806 (define_insn "*shiftsi3_compare0"
2807   [(set (reg:CC_NOOV CC_REGNUM)
2808         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2809                           [(match_operand:SI 1 "s_register_operand" "r")
2810                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2811                          (const_int 0)))
2812    (set (match_operand:SI 0 "s_register_operand" "=r")
2813         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2814   "TARGET_ARM"
2815   "mov%?s\\t%0, %1%S3"
2816   [(set_attr "conds" "set")
2817    (set_attr "shift" "1")
2818    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2819                       (const_string "alu_shift")
2820                       (const_string "alu_shift_reg")))]
2821 )
2822
2823 (define_insn "*shiftsi3_compare0_scratch"
2824   [(set (reg:CC_NOOV CC_REGNUM)
2825         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2826                           [(match_operand:SI 1 "s_register_operand" "r")
2827                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2828                          (const_int 0)))
2829    (clobber (match_scratch:SI 0 "=r"))]
2830   "TARGET_ARM"
2831   "mov%?s\\t%0, %1%S3"
2832   [(set_attr "conds" "set")
2833    (set_attr "shift" "1")]
2834 )
2835
2836 (define_insn "*notsi_shiftsi"
2837   [(set (match_operand:SI 0 "s_register_operand" "=r")
2838         (not:SI (match_operator:SI 3 "shift_operator"
2839                  [(match_operand:SI 1 "s_register_operand" "r")
2840                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2841   "TARGET_ARM"
2842   "mvn%?\\t%0, %1%S3"
2843   [(set_attr "predicable" "yes")
2844    (set_attr "shift" "1")
2845    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2846                       (const_string "alu_shift")
2847                       (const_string "alu_shift_reg")))]
2848 )
2849
2850 (define_insn "*notsi_shiftsi_compare0"
2851   [(set (reg:CC_NOOV CC_REGNUM)
2852         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2853                           [(match_operand:SI 1 "s_register_operand" "r")
2854                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2855                          (const_int 0)))
2856    (set (match_operand:SI 0 "s_register_operand" "=r")
2857         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2858   "TARGET_ARM"
2859   "mvn%?s\\t%0, %1%S3"
2860   [(set_attr "conds" "set")
2861    (set_attr "shift" "1")
2862    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2863                       (const_string "alu_shift")
2864                       (const_string "alu_shift_reg")))]
2865 )
2866
2867 (define_insn "*not_shiftsi_compare0_scratch"
2868   [(set (reg:CC_NOOV CC_REGNUM)
2869         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2870                           [(match_operand:SI 1 "s_register_operand" "r")
2871                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2872                          (const_int 0)))
2873    (clobber (match_scratch:SI 0 "=r"))]
2874   "TARGET_ARM"
2875   "mvn%?s\\t%0, %1%S3"
2876   [(set_attr "conds" "set")
2877    (set_attr "shift" "1")
2878    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2879                       (const_string "alu_shift")
2880                       (const_string "alu_shift_reg")))]
2881 )
2882
2883 ;; We don't really have extzv, but defining this using shifts helps
2884 ;; to reduce register pressure later on.
2885
2886 (define_expand "extzv"
2887   [(set (match_dup 4)
2888         (ashift:SI (match_operand:SI   1 "register_operand" "")
2889                    (match_operand:SI   2 "const_int_operand" "")))
2890    (set (match_operand:SI              0 "register_operand" "")
2891         (lshiftrt:SI (match_dup 4)
2892                      (match_operand:SI 3 "const_int_operand" "")))]
2893   "TARGET_THUMB"
2894   "
2895   {
2896     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2897     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2898     
2899     operands[3] = GEN_INT (rshift);
2900     
2901     if (lshift == 0)
2902       {
2903         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2904         DONE;
2905       }
2906       
2907     operands[2] = GEN_INT (lshift);
2908     operands[4] = gen_reg_rtx (SImode);
2909   }"
2910 )
2911
2912 \f
2913 ;; Unary arithmetic insns
2914
2915 (define_expand "negdi2"
2916  [(parallel
2917    [(set (match_operand:DI          0 "s_register_operand" "")
2918           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2919     (clobber (reg:CC CC_REGNUM))])]
2920   "TARGET_EITHER"
2921   "
2922   if (TARGET_THUMB)
2923     {
2924       if (GET_CODE (operands[1]) != REG)
2925         operands[1] = force_reg (SImode, operands[1]);
2926      }
2927   "
2928 )
2929
2930 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2931 ;; The second alternative is to allow the common case of a *full* overlap.
2932 (define_insn "*arm_negdi2"
2933   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2934         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2935    (clobber (reg:CC CC_REGNUM))]
2936   "TARGET_ARM"
2937   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2938   [(set_attr "conds" "clob")
2939    (set_attr "length" "8")]
2940 )
2941
2942 (define_insn "*thumb_negdi2"
2943   [(set (match_operand:DI         0 "register_operand" "=&l")
2944         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2945    (clobber (reg:CC CC_REGNUM))]
2946   "TARGET_THUMB"
2947   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2948   [(set_attr "length" "6")]
2949 )
2950
2951 (define_expand "negsi2"
2952   [(set (match_operand:SI         0 "s_register_operand" "")
2953         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2954   "TARGET_EITHER"
2955   ""
2956 )
2957
2958 (define_insn "*arm_negsi2"
2959   [(set (match_operand:SI         0 "s_register_operand" "=r")
2960         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2961   "TARGET_ARM"
2962   "rsb%?\\t%0, %1, #0"
2963   [(set_attr "predicable" "yes")]
2964 )
2965
2966 (define_insn "*thumb_negsi2"
2967   [(set (match_operand:SI         0 "register_operand" "=l")
2968         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2969   "TARGET_THUMB"
2970   "neg\\t%0, %1"
2971   [(set_attr "length" "2")]
2972 )
2973
2974 (define_expand "negsf2"
2975   [(set (match_operand:SF         0 "s_register_operand" "")
2976         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2977   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2978   ""
2979 )
2980
2981 (define_expand "negdf2"
2982   [(set (match_operand:DF         0 "s_register_operand" "")
2983         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2984   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2985   "")
2986
2987 ;; abssi2 doesn't really clobber the condition codes if a different register
2988 ;; is being set.  To keep things simple, assume during rtl manipulations that
2989 ;; it does, but tell the final scan operator the truth.  Similarly for
2990 ;; (neg (abs...))
2991
2992 (define_expand "abssi2"
2993   [(parallel
2994     [(set (match_operand:SI         0 "s_register_operand" "")
2995           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2996      (clobber (reg:CC CC_REGNUM))])]
2997   "TARGET_ARM"
2998   "")
2999
3000 (define_insn "*arm_abssi2"
3001   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3002         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3003    (clobber (reg:CC CC_REGNUM))]
3004   "TARGET_ARM"
3005   "@
3006    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3007    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3008   [(set_attr "conds" "clob,*")
3009    (set_attr "shift" "1")
3010    ;; predicable can't be set based on the variant, so left as no
3011    (set_attr "length" "8")]
3012 )
3013
3014 (define_insn "*neg_abssi2"
3015   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3016         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3017    (clobber (reg:CC CC_REGNUM))]
3018   "TARGET_ARM"
3019   "@
3020    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3021    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3022   [(set_attr "conds" "clob,*")
3023    (set_attr "shift" "1")
3024    ;; predicable can't be set based on the variant, so left as no
3025    (set_attr "length" "8")]
3026 )
3027
3028 (define_expand "abssf2"
3029   [(set (match_operand:SF         0 "s_register_operand" "")
3030         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3031   "TARGET_ARM && TARGET_HARD_FLOAT"
3032   "")
3033
3034 (define_expand "absdf2"
3035   [(set (match_operand:DF         0 "s_register_operand" "")
3036         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3037   "TARGET_ARM && TARGET_HARD_FLOAT"
3038   "")
3039
3040 (define_expand "sqrtsf2"
3041   [(set (match_operand:SF 0 "s_register_operand" "")
3042         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3043   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3044   "")
3045
3046 (define_expand "sqrtdf2"
3047   [(set (match_operand:DF 0 "s_register_operand" "")
3048         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3049   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3050   "")
3051
3052 (define_insn_and_split "one_cmpldi2"
3053   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3054         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3055   "TARGET_ARM"
3056   "#"
3057   "TARGET_ARM && reload_completed"
3058   [(set (match_dup 0) (not:SI (match_dup 1)))
3059    (set (match_dup 2) (not:SI (match_dup 3)))]
3060   "
3061   {
3062     operands[2] = gen_highpart (SImode, operands[0]);
3063     operands[0] = gen_lowpart (SImode, operands[0]);
3064     operands[3] = gen_highpart (SImode, operands[1]);
3065     operands[1] = gen_lowpart (SImode, operands[1]);
3066   }"
3067   [(set_attr "length" "8")
3068    (set_attr "predicable" "yes")]
3069 )
3070
3071 (define_expand "one_cmplsi2"
3072   [(set (match_operand:SI         0 "s_register_operand" "")
3073         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3074   "TARGET_EITHER"
3075   ""
3076 )
3077
3078 (define_insn "*arm_one_cmplsi2"
3079   [(set (match_operand:SI         0 "s_register_operand" "=r")
3080         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3081   "TARGET_ARM"
3082   "mvn%?\\t%0, %1"
3083   [(set_attr "predicable" "yes")]
3084 )
3085
3086 (define_insn "*thumb_one_cmplsi2"
3087   [(set (match_operand:SI         0 "register_operand" "=l")
3088         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3089   "TARGET_THUMB"
3090   "mvn\\t%0, %1"
3091   [(set_attr "length" "2")]
3092 )
3093
3094 (define_insn "*notsi_compare0"
3095   [(set (reg:CC_NOOV CC_REGNUM)
3096         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3097                          (const_int 0)))
3098    (set (match_operand:SI 0 "s_register_operand" "=r")
3099         (not:SI (match_dup 1)))]
3100   "TARGET_ARM"
3101   "mvn%?s\\t%0, %1"
3102   [(set_attr "conds" "set")]
3103 )
3104
3105 (define_insn "*notsi_compare0_scratch"
3106   [(set (reg:CC_NOOV CC_REGNUM)
3107         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3108                          (const_int 0)))
3109    (clobber (match_scratch:SI 0 "=r"))]
3110   "TARGET_ARM"
3111   "mvn%?s\\t%0, %1"
3112   [(set_attr "conds" "set")]
3113 )
3114 \f
3115 ;; Fixed <--> Floating conversion insns
3116
3117 (define_expand "floatsisf2"
3118   [(set (match_operand:SF           0 "s_register_operand" "")
3119         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3120   "TARGET_ARM && TARGET_HARD_FLOAT"
3121   "
3122   if (TARGET_MAVERICK)
3123     {
3124       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3125       DONE;
3126     }
3127 ")
3128
3129 (define_expand "floatsidf2"
3130   [(set (match_operand:DF           0 "s_register_operand" "")
3131         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3132   "TARGET_ARM && TARGET_HARD_FLOAT"
3133   "
3134   if (TARGET_MAVERICK)
3135     {
3136       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3137       DONE;
3138     }
3139 ")
3140
3141 (define_expand "fix_truncsfsi2"
3142   [(set (match_operand:SI         0 "s_register_operand" "")
3143         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3144   "TARGET_ARM && TARGET_HARD_FLOAT"
3145   "
3146   if (TARGET_MAVERICK)
3147     {
3148       if (!cirrus_fp_register (operands[0], SImode))
3149         operands[0] = force_reg (SImode, operands[0]);
3150       if (!cirrus_fp_register (operands[1], SFmode))
3151         operands[1] = force_reg (SFmode, operands[0]);
3152       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3153       DONE;
3154     }
3155 ")
3156
3157 (define_expand "fix_truncdfsi2"
3158   [(set (match_operand:SI         0 "s_register_operand" "")
3159         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3160   "TARGET_ARM && TARGET_HARD_FLOAT"
3161   "
3162   if (TARGET_MAVERICK)
3163     {
3164       if (!cirrus_fp_register (operands[1], DFmode))
3165         operands[1] = force_reg (DFmode, operands[0]);
3166       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3167       DONE;
3168     }
3169 ")
3170
3171 ;; Truncation insns
3172
3173 (define_expand "truncdfsf2"
3174   [(set (match_operand:SF  0 "s_register_operand" "")
3175         (float_truncate:SF
3176          (match_operand:DF 1 "s_register_operand" "")))]
3177   "TARGET_ARM && TARGET_HARD_FLOAT"
3178   ""
3179 )
3180 \f
3181 ;; Zero and sign extension instructions.
3182
3183 (define_insn "zero_extendsidi2"
3184   [(set (match_operand:DI 0 "s_register_operand" "=r")
3185         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3186   "TARGET_ARM"
3187   "*
3188     if (REGNO (operands[1])
3189         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3190       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3191     return \"mov%?\\t%R0, #0\";
3192   "
3193   [(set_attr "length" "8")
3194    (set_attr "predicable" "yes")]
3195 )
3196
3197 (define_insn "zero_extendqidi2"
3198   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3199         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3200   "TARGET_ARM"
3201   "@
3202    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3203    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3204   [(set_attr "length" "8")
3205    (set_attr "predicable" "yes")
3206    (set_attr "type" "*,load_byte")
3207    (set_attr "pool_range" "*,4092")
3208    (set_attr "neg_pool_range" "*,4084")]
3209 )
3210
3211 (define_insn "extendsidi2"
3212   [(set (match_operand:DI 0 "s_register_operand" "=r")
3213         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3214   "TARGET_ARM"
3215   "*
3216     if (REGNO (operands[1])
3217         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3218       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3219     return \"mov%?\\t%R0, %Q0, asr #31\";
3220   "
3221   [(set_attr "length" "8")
3222    (set_attr "shift" "1")
3223    (set_attr "predicable" "yes")]
3224 )
3225
3226 (define_expand "zero_extendhisi2"
3227   [(set (match_dup 2)
3228         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3229                    (const_int 16)))
3230    (set (match_operand:SI 0 "s_register_operand" "")
3231         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3232   "TARGET_EITHER"
3233   "
3234   {
3235     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3236       {
3237         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3238                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3239         DONE;
3240       }
3241
3242     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3243       {
3244         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3245         DONE;
3246       }
3247
3248     if (!s_register_operand (operands[1], HImode))
3249       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3250
3251     if (arm_arch6)
3252       {
3253         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3254                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3255         DONE;
3256       }
3257
3258     operands[1] = gen_lowpart (SImode, operands[1]);
3259     operands[2] = gen_reg_rtx (SImode);
3260   }"
3261 )
3262
3263 (define_insn "*thumb_zero_extendhisi2"
3264   [(set (match_operand:SI 0 "register_operand" "=l")
3265         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3266   "TARGET_THUMB && !arm_arch6"
3267   "*
3268   rtx mem = XEXP (operands[1], 0);
3269
3270   if (GET_CODE (mem) == CONST)
3271     mem = XEXP (mem, 0);
3272     
3273   if (GET_CODE (mem) == LABEL_REF)
3274     return \"ldr\\t%0, %1\";
3275     
3276   if (GET_CODE (mem) == PLUS)
3277     {
3278       rtx a = XEXP (mem, 0);
3279       rtx b = XEXP (mem, 1);
3280
3281       /* This can happen due to bugs in reload.  */
3282       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3283         {
3284           rtx ops[2];
3285           ops[0] = operands[0];
3286           ops[1] = a;
3287       
3288           output_asm_insn (\"mov        %0, %1\", ops);
3289
3290           XEXP (mem, 0) = operands[0];
3291        }
3292
3293       else if (   GET_CODE (a) == LABEL_REF
3294                && GET_CODE (b) == CONST_INT)
3295         return \"ldr\\t%0, %1\";
3296     }
3297     
3298   return \"ldrh\\t%0, %1\";
3299   "
3300   [(set_attr "length" "4")
3301    (set_attr "type" "load_byte")
3302    (set_attr "pool_range" "60")]
3303 )
3304
3305 (define_insn "*thumb_zero_extendhisi2_v6"
3306   [(set (match_operand:SI 0 "register_operand" "=l,l")
3307         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3308   "TARGET_THUMB && arm_arch6"
3309   "*
3310   rtx mem;
3311
3312   if (which_alternative == 0)
3313     return \"uxth\\t%0, %1\";
3314
3315   mem = XEXP (operands[1], 0);
3316
3317   if (GET_CODE (mem) == CONST)
3318     mem = XEXP (mem, 0);
3319     
3320   if (GET_CODE (mem) == LABEL_REF)
3321     return \"ldr\\t%0, %1\";
3322     
3323   if (GET_CODE (mem) == PLUS)
3324     {
3325       rtx a = XEXP (mem, 0);
3326       rtx b = XEXP (mem, 1);
3327
3328       /* This can happen due to bugs in reload.  */
3329       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3330         {
3331           rtx ops[2];
3332           ops[0] = operands[0];
3333           ops[1] = a;
3334       
3335           output_asm_insn (\"mov        %0, %1\", ops);
3336
3337           XEXP (mem, 0) = operands[0];
3338        }
3339
3340       else if (   GET_CODE (a) == LABEL_REF
3341                && GET_CODE (b) == CONST_INT)
3342         return \"ldr\\t%0, %1\";
3343     }
3344     
3345   return \"ldrh\\t%0, %1\";
3346   "
3347   [(set_attr "length" "2,4")
3348    (set_attr "type" "alu_shift,load_byte")
3349    (set_attr "pool_range" "*,60")]
3350 )
3351
3352 (define_insn "*arm_zero_extendhisi2"
3353   [(set (match_operand:SI 0 "s_register_operand" "=r")
3354         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3355   "TARGET_ARM && arm_arch4 && !arm_arch6"
3356   "ldr%?h\\t%0, %1"
3357   [(set_attr "type" "load_byte")
3358    (set_attr "predicable" "yes")
3359    (set_attr "pool_range" "256")
3360    (set_attr "neg_pool_range" "244")]
3361 )
3362
3363 (define_insn "*arm_zero_extendhisi2_v6"
3364   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3365         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3366   "TARGET_ARM && arm_arch6"
3367   "@
3368    uxth%?\\t%0, %1
3369    ldr%?h\\t%0, %1"
3370   [(set_attr "type" "alu_shift,load_byte")
3371    (set_attr "predicable" "yes")
3372    (set_attr "pool_range" "*,256")
3373    (set_attr "neg_pool_range" "*,244")]
3374 )
3375
3376 (define_insn "*arm_zero_extendhisi2addsi"
3377   [(set (match_operand:SI 0 "s_register_operand" "=r")
3378         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3379                  (match_operand:SI 2 "s_register_operand" "r")))]
3380   "TARGET_ARM && arm_arch6"
3381   "uxtah%?\\t%0, %2, %1"
3382   [(set_attr "type" "alu_shift")
3383    (set_attr "predicable" "yes")]
3384 )
3385
3386 (define_split
3387   [(set (match_operand:SI 0 "s_register_operand" "")
3388         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3389    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3390   "TARGET_ARM && (!arm_arch4)"
3391   [(set (match_dup 2) (match_dup 1))
3392    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3393   "
3394   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3395     FAIL;
3396   "
3397 )
3398
3399 (define_split
3400   [(set (match_operand:SI 0 "s_register_operand" "")
3401         (match_operator:SI 3 "shiftable_operator"
3402          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3403           (match_operand:SI 4 "s_register_operand" "")]))
3404    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3405   "TARGET_ARM && (!arm_arch4)"
3406   [(set (match_dup 2) (match_dup 1))
3407    (set (match_dup 0)
3408         (match_op_dup 3
3409          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3410   "
3411   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3412     FAIL;
3413   "
3414 )
3415
3416 (define_expand "zero_extendqisi2"
3417   [(set (match_operand:SI 0 "s_register_operand" "")
3418         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3419   "TARGET_EITHER"
3420   "
3421   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3422     {
3423       if (TARGET_ARM)
3424         {
3425           emit_insn (gen_andsi3 (operands[0],
3426                                  gen_lowpart (SImode, operands[1]),
3427                                  GEN_INT (255)));
3428         }
3429       else /* TARGET_THUMB */
3430         {
3431           rtx temp = gen_reg_rtx (SImode);
3432           rtx ops[3];
3433           
3434           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3435           operands[1] = gen_lowpart (SImode, operands[1]);
3436
3437           ops[0] = temp;
3438           ops[1] = operands[1];
3439           ops[2] = GEN_INT (24);
3440
3441           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3442                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3443           
3444           ops[0] = operands[0];
3445           ops[1] = temp;
3446           ops[2] = GEN_INT (24);
3447
3448           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3449                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3450         }
3451       DONE;
3452     }
3453   "
3454 )
3455
3456 (define_insn "*thumb_zero_extendqisi2"
3457   [(set (match_operand:SI 0 "register_operand" "=l")
3458         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3459   "TARGET_THUMB && !arm_arch6"
3460   "ldrb\\t%0, %1"
3461   [(set_attr "length" "2")
3462    (set_attr "type" "load_byte")
3463    (set_attr "pool_range" "32")]
3464 )
3465
3466 (define_insn "*thumb_zero_extendqisi2_v6"
3467   [(set (match_operand:SI 0 "register_operand" "=l,l")
3468         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3469   "TARGET_THUMB && arm_arch6"
3470   "@
3471    uxtb\\t%0, %1
3472    ldrb\\t%0, %1"
3473   [(set_attr "length" "2,2")
3474    (set_attr "type" "alu_shift,load_byte")
3475    (set_attr "pool_range" "*,32")]
3476 )
3477
3478 (define_insn "*arm_zero_extendqisi2"
3479   [(set (match_operand:SI 0 "s_register_operand" "=r")
3480         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3481   "TARGET_ARM && !arm_arch6"
3482   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3483   [(set_attr "type" "load_byte")
3484    (set_attr "predicable" "yes")
3485    (set_attr "pool_range" "4096")
3486    (set_attr "neg_pool_range" "4084")]
3487 )
3488
3489 (define_insn "*arm_zero_extendqisi2_v6"
3490   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3491         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3492   "TARGET_ARM && arm_arch6"
3493   "@
3494    uxtb%?\\t%0, %1
3495    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3496   [(set_attr "type" "alu_shift,load_byte")
3497    (set_attr "predicable" "yes")
3498    (set_attr "pool_range" "*,4096")
3499    (set_attr "neg_pool_range" "*,4084")]
3500 )
3501
3502 (define_insn "*arm_zero_extendqisi2addsi"
3503   [(set (match_operand:SI 0 "s_register_operand" "=r")
3504         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3505                  (match_operand:SI 2 "s_register_operand" "r")))]
3506   "TARGET_ARM && arm_arch6"
3507   "uxtab%?\\t%0, %2, %1"
3508   [(set_attr "predicable" "yes")
3509    (set_attr "type" "alu_shift")]
3510 )
3511
3512 (define_split
3513   [(set (match_operand:SI 0 "s_register_operand" "")
3514         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3515    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3516   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3517   [(set (match_dup 2) (match_dup 1))
3518    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3519   ""
3520 )
3521
3522 (define_insn "*compareqi_eq0"
3523   [(set (reg:CC_Z CC_REGNUM)
3524         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3525                          (const_int 0)))]
3526   "TARGET_ARM"
3527   "tst\\t%0, #255"
3528   [(set_attr "conds" "set")]
3529 )
3530
3531 (define_expand "extendhisi2"
3532   [(set (match_dup 2)
3533         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3534                    (const_int 16)))
3535    (set (match_operand:SI 0 "s_register_operand" "")
3536         (ashiftrt:SI (match_dup 2)
3537                      (const_int 16)))]
3538   "TARGET_EITHER"
3539   "
3540   {
3541     if (GET_CODE (operands[1]) == MEM)
3542       {
3543         if (TARGET_THUMB)
3544           {
3545             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3546             DONE;
3547           }
3548         else if (arm_arch4)
3549           {
3550             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3551                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3552             DONE;
3553           }
3554       }
3555
3556     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3557       {
3558         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3559         DONE;
3560       }
3561
3562     if (!s_register_operand (operands[1], HImode))
3563       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3564
3565     if (arm_arch6)
3566       {
3567         if (TARGET_THUMB)
3568           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3569         else
3570           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3571                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3572
3573         DONE;
3574       }
3575
3576     operands[1] = gen_lowpart (SImode, operands[1]);
3577     operands[2] = gen_reg_rtx (SImode);
3578   }"
3579 )
3580
3581 (define_insn "thumb_extendhisi2"
3582   [(set (match_operand:SI 0 "register_operand" "=l")
3583         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3584    (clobber (match_scratch:SI 2 "=&l"))]
3585   "TARGET_THUMB && !arm_arch6"
3586   "*
3587   {
3588     rtx ops[4];
3589     rtx mem = XEXP (operands[1], 0);
3590
3591     /* This code used to try to use 'V', and fix the address only if it was
3592        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3593        range of QImode offsets, and offsettable_address_p does a QImode
3594        address check.  */
3595        
3596     if (GET_CODE (mem) == CONST)
3597       mem = XEXP (mem, 0);
3598     
3599     if (GET_CODE (mem) == LABEL_REF)
3600       return \"ldr\\t%0, %1\";
3601     
3602     if (GET_CODE (mem) == PLUS)
3603       {
3604         rtx a = XEXP (mem, 0);
3605         rtx b = XEXP (mem, 1);
3606
3607         if (GET_CODE (a) == LABEL_REF
3608             && GET_CODE (b) == CONST_INT)
3609           return \"ldr\\t%0, %1\";
3610
3611         if (GET_CODE (b) == REG)
3612           return \"ldrsh\\t%0, %1\";
3613           
3614         ops[1] = a;
3615         ops[2] = b;
3616       }
3617     else
3618       {
3619         ops[1] = mem;
3620         ops[2] = const0_rtx;
3621       }
3622       
3623     if (GET_CODE (ops[1]) != REG)
3624       {
3625         debug_rtx (ops[1]);
3626         abort ();
3627       }
3628
3629     ops[0] = operands[0];
3630     ops[3] = operands[2];
3631     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3632     return \"\";
3633   }"
3634   [(set_attr "length" "4")
3635    (set_attr "type" "load_byte")
3636    (set_attr "pool_range" "1020")]
3637 )
3638
3639 ;; We used to have an early-clobber on the scratch register here.
3640 ;; However, there's a bug somewhere in reload which means that this
3641 ;; can be partially ignored during spill allocation if the memory
3642 ;; address also needs reloading; this causes an abort later on when
3643 ;; we try to verify the operands.  Fortunately, we don't really need
3644 ;; the early-clobber: we can always use operand 0 if operand 2
3645 ;; overlaps the address.
3646 (define_insn "*thumb_extendhisi2_insn_v6"
3647   [(set (match_operand:SI 0 "register_operand" "=l,l")
3648         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3649    (clobber (match_scratch:SI 2 "=X,l"))]
3650   "TARGET_THUMB && arm_arch6"
3651   "*
3652   {
3653     rtx ops[4];
3654     rtx mem;
3655
3656     if (which_alternative == 0)
3657       return \"sxth\\t%0, %1\";
3658
3659     mem = XEXP (operands[1], 0);
3660
3661     /* This code used to try to use 'V', and fix the address only if it was
3662        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3663        range of QImode offsets, and offsettable_address_p does a QImode
3664        address check.  */
3665        
3666     if (GET_CODE (mem) == CONST)
3667       mem = XEXP (mem, 0);
3668     
3669     if (GET_CODE (mem) == LABEL_REF)
3670       return \"ldr\\t%0, %1\";
3671     
3672     if (GET_CODE (mem) == PLUS)
3673       {
3674         rtx a = XEXP (mem, 0);
3675         rtx b = XEXP (mem, 1);
3676
3677         if (GET_CODE (a) == LABEL_REF
3678             && GET_CODE (b) == CONST_INT)
3679           return \"ldr\\t%0, %1\";
3680
3681         if (GET_CODE (b) == REG)
3682           return \"ldrsh\\t%0, %1\";
3683           
3684         ops[1] = a;
3685         ops[2] = b;
3686       }
3687     else
3688       {
3689         ops[1] = mem;
3690         ops[2] = const0_rtx;
3691       }
3692       
3693     if (GET_CODE (ops[1]) != REG)
3694       {
3695         debug_rtx (ops[1]);
3696         abort ();
3697       }
3698
3699     ops[0] = operands[0];
3700     if (reg_mentioned_p (operands[2], ops[1]))
3701       ops[3] = ops[0];
3702     else
3703       ops[3] = operands[2];
3704     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3705     return \"\";
3706   }"
3707   [(set_attr "length" "2,4")
3708    (set_attr "type" "alu_shift,load_byte")
3709    (set_attr "pool_range" "*,1020")]
3710 )
3711
3712 (define_expand "extendhisi2_mem"
3713   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3714    (set (match_dup 3)
3715         (zero_extend:SI (match_dup 7)))
3716    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3717    (set (match_operand:SI 0 "" "")
3718         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3719   "TARGET_ARM"
3720   "
3721   {
3722     rtx mem1, mem2;
3723     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3724
3725     mem1 = gen_rtx_MEM (QImode, addr);
3726     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3727     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3728     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3729     operands[0] = gen_lowpart (SImode, operands[0]);
3730     operands[1] = mem1;
3731     operands[2] = gen_reg_rtx (SImode);
3732     operands[3] = gen_reg_rtx (SImode);
3733     operands[6] = gen_reg_rtx (SImode);
3734     operands[7] = mem2;
3735
3736     if (BYTES_BIG_ENDIAN)
3737       {
3738         operands[4] = operands[2];
3739         operands[5] = operands[3];
3740       }
3741     else
3742       {
3743         operands[4] = operands[3];
3744         operands[5] = operands[2];
3745       }
3746   }"
3747 )
3748
3749 (define_insn "*arm_extendhisi2"
3750   [(set (match_operand:SI 0 "s_register_operand" "=r")
3751         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3752   "TARGET_ARM && arm_arch4 && !arm_arch6"
3753   "ldr%?sh\\t%0, %1"
3754   [(set_attr "type" "load_byte")
3755    (set_attr "predicable" "yes")
3756    (set_attr "pool_range" "256")
3757    (set_attr "neg_pool_range" "244")]
3758 )
3759
3760 (define_insn "*arm_extendhisi2_v6"
3761   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3762         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3763   "TARGET_ARM && arm_arch6"
3764   "@
3765    sxth%?\\t%0, %1
3766    ldr%?sh\\t%0, %1"
3767   [(set_attr "type" "alu_shift,load_byte")
3768    (set_attr "predicable" "yes")
3769    (set_attr "pool_range" "*,256")
3770    (set_attr "neg_pool_range" "*,244")]
3771 )
3772
3773 (define_insn "*arm_extendhisi2addsi"
3774   [(set (match_operand:SI 0 "s_register_operand" "=r")
3775         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3776                  (match_operand:SI 2 "s_register_operand" "r")))]
3777   "TARGET_ARM && arm_arch6"
3778   "sxtah%?\\t%0, %2, %1"
3779 )
3780
3781 (define_split
3782   [(set (match_operand:SI                 0 "s_register_operand" "")
3783         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3784    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3785   "TARGET_ARM && (!arm_arch4)"
3786   [(set (match_dup 2) (match_dup 1))
3787    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3788   "
3789   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3790     FAIL;
3791   "
3792 )
3793
3794 (define_split
3795   [(set (match_operand:SI                   0 "s_register_operand" "")
3796         (match_operator:SI                  3 "shiftable_operator"
3797          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3798           (match_operand:SI                 4 "s_register_operand" "")]))
3799    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3800   "TARGET_ARM && (!arm_arch4)"
3801   [(set (match_dup 2) (match_dup 1))
3802    (set (match_dup 0)
3803         (match_op_dup 3
3804          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3805   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3806      FAIL;
3807   "
3808 )
3809
3810 (define_expand "extendqihi2"
3811   [(set (match_dup 2)
3812         (ashift:SI (match_operand:QI 1 "general_operand" "")
3813                    (const_int 24)))
3814    (set (match_operand:HI 0 "s_register_operand" "")
3815         (ashiftrt:SI (match_dup 2)
3816                      (const_int 24)))]
3817   "TARGET_ARM"
3818   "
3819   {
3820     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3821       {
3822         emit_insn (gen_rtx_SET (VOIDmode,
3823                                 operands[0],
3824                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3825         DONE;
3826       }
3827     if (!s_register_operand (operands[1], QImode))
3828       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3829     operands[0] = gen_lowpart (SImode, operands[0]);
3830     operands[1] = gen_lowpart (SImode, operands[1]);
3831     operands[2] = gen_reg_rtx (SImode);
3832   }"
3833 )
3834
3835 (define_insn "*extendqihi_insn"
3836   [(set (match_operand:HI 0 "s_register_operand" "=r")
3837         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3838   "TARGET_ARM && arm_arch4"
3839   "ldr%?sb\\t%0, %1"
3840   [(set_attr "type" "load_byte")
3841    (set_attr "predicable" "yes")
3842    (set_attr "pool_range" "256")
3843    (set_attr "neg_pool_range" "244")]
3844 )
3845
3846 (define_expand "extendqisi2"
3847   [(set (match_dup 2)
3848         (ashift:SI (match_operand:QI 1 "general_operand" "")
3849                    (const_int 24)))
3850    (set (match_operand:SI 0 "s_register_operand" "")
3851         (ashiftrt:SI (match_dup 2)
3852                      (const_int 24)))]
3853   "TARGET_EITHER"
3854   "
3855   {
3856     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3857       {
3858         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3859                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3860         DONE;
3861       }
3862
3863     if (!s_register_operand (operands[1], QImode))
3864       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3865
3866     if (arm_arch6)
3867       {
3868         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3869                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3870         DONE;
3871       }
3872
3873     operands[1] = gen_lowpart (SImode, operands[1]);
3874     operands[2] = gen_reg_rtx (SImode);
3875   }"
3876 )
3877
3878 (define_insn "*arm_extendqisi"
3879   [(set (match_operand:SI 0 "s_register_operand" "=r")
3880         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3881   "TARGET_ARM && arm_arch4 && !arm_arch6"
3882   "ldr%?sb\\t%0, %1"
3883   [(set_attr "type" "load_byte")
3884    (set_attr "predicable" "yes")
3885    (set_attr "pool_range" "256")
3886    (set_attr "neg_pool_range" "244")]
3887 )
3888
3889 (define_insn "*arm_extendqisi_v6"
3890   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3891         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3892   "TARGET_ARM && arm_arch6"
3893   "@
3894    sxtb%?\\t%0, %1
3895    ldr%?sb\\t%0, %1"
3896   [(set_attr "type" "alu_shift,load_byte")
3897    (set_attr "predicable" "yes")
3898    (set_attr "pool_range" "*,256")
3899    (set_attr "neg_pool_range" "*,244")]
3900 )
3901
3902 (define_insn "*arm_extendqisi2addsi"
3903   [(set (match_operand:SI 0 "s_register_operand" "=r")
3904         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3905                  (match_operand:SI 2 "s_register_operand" "r")))]
3906   "TARGET_ARM && arm_arch6"
3907   "sxtab%?\\t%0, %2, %1"
3908   [(set_attr "type" "alu_shift")
3909    (set_attr "predicable" "yes")]
3910 )
3911
3912 (define_insn "*thumb_extendqisi2"
3913   [(set (match_operand:SI 0 "register_operand" "=l,l")
3914         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3915   "TARGET_THUMB && !arm_arch6"
3916   "*
3917   {
3918     rtx ops[3];
3919     rtx mem = XEXP (operands[1], 0);
3920     
3921     if (GET_CODE (mem) == CONST)
3922       mem = XEXP (mem, 0);
3923     
3924     if (GET_CODE (mem) == LABEL_REF)
3925       return \"ldr\\t%0, %1\";
3926
3927     if (GET_CODE (mem) == PLUS
3928         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3929       return \"ldr\\t%0, %1\";
3930       
3931     if (which_alternative == 0)
3932       return \"ldrsb\\t%0, %1\";
3933       
3934     ops[0] = operands[0];
3935     
3936     if (GET_CODE (mem) == PLUS)
3937       {
3938         rtx a = XEXP (mem, 0);
3939         rtx b = XEXP (mem, 1);
3940         
3941         ops[1] = a;
3942         ops[2] = b;
3943
3944         if (GET_CODE (a) == REG)
3945           {
3946             if (GET_CODE (b) == REG)
3947               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3948             else if (REGNO (a) == REGNO (ops[0]))
3949               {
3950                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3951                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3952                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3953               }
3954             else
3955               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3956           }
3957         else if (GET_CODE (b) != REG)
3958           abort ();
3959         else
3960           {
3961             if (REGNO (b) == REGNO (ops[0]))
3962               {
3963                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3964                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3965                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3966               }
3967             else
3968               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3969           }
3970       }
3971     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3972       {
3973         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3974         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3975         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3976       }
3977     else
3978       {
3979         ops[1] = mem;
3980         ops[2] = const0_rtx;
3981         
3982         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3983       }
3984     return \"\";
3985   }"
3986   [(set_attr "length" "2,6")
3987    (set_attr "type" "load_byte,load_byte")
3988    (set_attr "pool_range" "32,32")]
3989 )
3990
3991 (define_insn "*thumb_extendqisi2_v6"
3992   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3993         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3994   "TARGET_THUMB && arm_arch6"
3995   "*
3996   {
3997     rtx ops[3];
3998     rtx mem;
3999
4000     if (which_alternative == 0)
4001       return \"sxtb\\t%0, %1\";
4002
4003     mem = XEXP (operands[1], 0);
4004     
4005     if (GET_CODE (mem) == CONST)
4006       mem = XEXP (mem, 0);
4007     
4008     if (GET_CODE (mem) == LABEL_REF)
4009       return \"ldr\\t%0, %1\";
4010
4011     if (GET_CODE (mem) == PLUS
4012         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4013       return \"ldr\\t%0, %1\";
4014       
4015     if (which_alternative == 0)
4016       return \"ldrsb\\t%0, %1\";
4017       
4018     ops[0] = operands[0];
4019     
4020     if (GET_CODE (mem) == PLUS)
4021       {
4022         rtx a = XEXP (mem, 0);
4023         rtx b = XEXP (mem, 1);
4024         
4025         ops[1] = a;
4026         ops[2] = b;
4027
4028         if (GET_CODE (a) == REG)
4029           {
4030             if (GET_CODE (b) == REG)
4031               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4032             else if (REGNO (a) == REGNO (ops[0]))
4033               {
4034                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4035                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4036               }
4037             else
4038               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4039           }
4040         else if (GET_CODE (b) != REG)
4041           abort ();
4042         else
4043           {
4044             if (REGNO (b) == REGNO (ops[0]))
4045               {
4046                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4047                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4048               }
4049             else
4050               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4051           }
4052       }
4053     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4054       {
4055         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4056         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4057       }
4058     else
4059       {
4060         ops[1] = mem;
4061         ops[2] = const0_rtx;
4062         
4063         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4064       }
4065     return \"\";
4066   }"
4067   [(set_attr "length" "2,2,4")
4068    (set_attr "type" "alu_shift,load_byte,load_byte")
4069    (set_attr "pool_range" "*,32,32")]
4070 )
4071
4072 (define_expand "extendsfdf2"
4073   [(set (match_operand:DF                  0 "s_register_operand" "")
4074         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4075   "TARGET_ARM && TARGET_HARD_FLOAT"
4076   ""
4077 )
4078 \f
4079 ;; Move insns (including loads and stores)
4080
4081 ;; XXX Just some ideas about movti.
4082 ;; I don't think these are a good idea on the arm, there just aren't enough
4083 ;; registers
4084 ;;(define_expand "loadti"
4085 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4086 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4087 ;;  "" "")
4088
4089 ;;(define_expand "storeti"
4090 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4091 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4092 ;;  "" "")
4093
4094 ;;(define_expand "movti"
4095 ;;  [(set (match_operand:TI 0 "general_operand" "")
4096 ;;      (match_operand:TI 1 "general_operand" ""))]
4097 ;;  ""
4098 ;;  "
4099 ;;{
4100 ;;  rtx insn;
4101 ;;
4102 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4103 ;;    operands[1] = copy_to_reg (operands[1]);
4104 ;;  if (GET_CODE (operands[0]) == MEM)
4105 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4106 ;;  else if (GET_CODE (operands[1]) == MEM)
4107 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4108 ;;  else
4109 ;;    FAIL;
4110 ;;
4111 ;;  emit_insn (insn);
4112 ;;  DONE;
4113 ;;}")
4114
4115 ;; Recognize garbage generated above.
4116
4117 ;;(define_insn ""
4118 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4119 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4120 ;;  ""
4121 ;;  "*
4122 ;;  {
4123 ;;    register mem = (which_alternative < 3);
4124 ;;    register const char *template;
4125 ;;
4126 ;;    operands[mem] = XEXP (operands[mem], 0);
4127 ;;    switch (which_alternative)
4128 ;;      {
4129 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4130 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4131 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4132 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4133 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4134 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4135 ;;      }
4136 ;;    output_asm_insn (template, operands);
4137 ;;    return \"\";
4138 ;;  }")
4139
4140 (define_expand "movdi"
4141   [(set (match_operand:DI 0 "general_operand" "")
4142         (match_operand:DI 1 "general_operand" ""))]
4143   "TARGET_EITHER"
4144   "
4145   if (TARGET_THUMB)
4146     {
4147       if (!no_new_pseudos)
4148         {
4149           if (GET_CODE (operands[0]) != REG)
4150             operands[1] = force_reg (DImode, operands[1]);
4151         }
4152     }
4153   "
4154 )
4155
4156 (define_insn "*arm_movdi"
4157   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
4158         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
4159   "TARGET_ARM
4160   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4161   && !TARGET_IWMMXT"
4162   "*
4163   return (output_move_double (operands));
4164   "
4165   [(set_attr "length" "8")
4166    (set_attr "type" "*,load2,store2")
4167    (set_attr "pool_range" "*,1020,*")
4168    (set_attr "neg_pool_range" "*,1008,*")]
4169 )
4170
4171 ;; We can't actually do base+index doubleword loads if the index and
4172 ;; destination overlap.  Split here so that we at least have chance to
4173 ;; schedule.
4174 (define_split
4175   [(set (match_operand:DI 0 "s_register_operand" "")
4176         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4177                          (match_operand:SI 2 "s_register_operand" ""))))]
4178   "TARGET_LDRD
4179   && reg_overlap_mentioned_p (operands[0], operands[1])
4180   && reg_overlap_mentioned_p (operands[0], operands[2])"
4181   [(set (match_dup 4)
4182         (plus:SI (match_dup 1)
4183                  (match_dup 2)))
4184    (set (match_dup 0)
4185         (mem:DI (match_dup 4)))]
4186   "
4187   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4188   "
4189 )
4190
4191 ;;; ??? This should have alternatives for constants.
4192 ;;; ??? This was originally identical to the movdf_insn pattern.
4193 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4194 ;;; thumb_reorg with a memory reference.
4195 (define_insn "*thumb_movdi_insn"
4196   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4197         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4198   "TARGET_THUMB
4199    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4200    && (   register_operand (operands[0], DImode)
4201        || register_operand (operands[1], DImode))"
4202   "*
4203   {
4204   switch (which_alternative)
4205     {
4206     default:
4207     case 0:
4208       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4209         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4210       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4211     case 1:
4212       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4213     case 2:
4214       operands[1] = GEN_INT (- INTVAL (operands[1]));
4215       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4216     case 3:
4217       return \"ldmia\\t%1, {%0, %H0}\";
4218     case 4:
4219       return \"stmia\\t%0, {%1, %H1}\";
4220     case 5:
4221       return thumb_load_double_from_address (operands);
4222     case 6:
4223       operands[2] = gen_rtx_MEM (SImode,
4224                              plus_constant (XEXP (operands[0], 0), 4));
4225       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4226       return \"\";
4227     case 7:
4228       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4229         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4230       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4231     }
4232   }"
4233   [(set_attr "length" "4,4,6,2,2,6,4,4")
4234    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4235    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4236 )
4237
4238 (define_expand "movsi"
4239   [(set (match_operand:SI 0 "general_operand" "")
4240         (match_operand:SI 1 "general_operand" ""))]
4241   "TARGET_EITHER"
4242   "
4243   if (TARGET_ARM)
4244     {
4245       /* Everything except mem = const or mem = mem can be done easily.  */
4246       if (GET_CODE (operands[0]) == MEM)
4247         operands[1] = force_reg (SImode, operands[1]);
4248       if (arm_general_register_operand (operands[0], SImode)
4249           && GET_CODE (operands[1]) == CONST_INT
4250           && !(const_ok_for_arm (INTVAL (operands[1]))
4251                || const_ok_for_arm (~INTVAL (operands[1]))))
4252         {
4253            arm_split_constant (SET, SImode, NULL_RTX,
4254                                INTVAL (operands[1]), operands[0], NULL_RTX,
4255                                optimize && !no_new_pseudos);
4256           DONE;
4257         }
4258     }
4259   else /* TARGET_THUMB....  */
4260     {
4261       if (!no_new_pseudos)
4262         {
4263           if (GET_CODE (operands[0]) != REG)
4264             operands[1] = force_reg (SImode, operands[1]);
4265         }
4266     }
4267     
4268   if (flag_pic
4269       && (CONSTANT_P (operands[1])
4270          || symbol_mentioned_p (operands[1])
4271          || label_mentioned_p (operands[1])))
4272     operands[1] = legitimize_pic_address (operands[1], SImode,
4273                                           (no_new_pseudos ? operands[0] : 0));
4274   "
4275 )
4276
4277 (define_insn "*arm_movsi_insn"
4278   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4279         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4280   "TARGET_ARM && ! TARGET_IWMMXT
4281    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4282    && (   register_operand (operands[0], SImode)
4283        || register_operand (operands[1], SImode))"
4284   "@
4285    mov%?\\t%0, %1
4286    mvn%?\\t%0, #%B1
4287    ldr%?\\t%0, %1
4288    str%?\\t%1, %0"
4289   [(set_attr "type" "*,*,load1,store1")
4290    (set_attr "predicable" "yes")
4291    (set_attr "pool_range" "*,*,4096,*")
4292    (set_attr "neg_pool_range" "*,*,4084,*")]
4293 )
4294
4295 (define_split
4296   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4297         (match_operand:SI 1 "const_int_operand" ""))]
4298   "TARGET_ARM
4299   && (!(const_ok_for_arm (INTVAL (operands[1]))
4300         || const_ok_for_arm (~INTVAL (operands[1]))))"
4301   [(clobber (const_int 0))]
4302   "
4303   arm_split_constant (SET, SImode, NULL_RTX, 
4304                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4305   DONE;
4306   "
4307 )
4308
4309 (define_insn "*thumb_movsi_insn"
4310   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4311         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4312   "TARGET_THUMB
4313    && (   register_operand (operands[0], SImode) 
4314        || register_operand (operands[1], SImode))"
4315   "@
4316    mov  %0, %1
4317    mov  %0, %1
4318    #
4319    #
4320    ldmia\\t%1, {%0}
4321    stmia\\t%0, {%1}
4322    ldr\\t%0, %1
4323    str\\t%1, %0
4324    mov\\t%0, %1"
4325   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4326    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4327    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4328 )
4329
4330 (define_split 
4331   [(set (match_operand:SI 0 "register_operand" "")
4332         (match_operand:SI 1 "const_int_operand" ""))]
4333   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4334   [(set (match_dup 0) (match_dup 1))
4335    (set (match_dup 0) (neg:SI (match_dup 0)))]
4336   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4337 )
4338
4339 (define_split 
4340   [(set (match_operand:SI 0 "register_operand" "")
4341         (match_operand:SI 1 "const_int_operand" ""))]
4342   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4343   [(set (match_dup 0) (match_dup 1))
4344    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4345   "
4346   {
4347     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4348     unsigned HOST_WIDE_INT mask = 0xff;
4349     int i;
4350     
4351     for (i = 0; i < 25; i++)
4352       if ((val & (mask << i)) == val)
4353         break;
4354
4355     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4356     if (i == 0)
4357       FAIL;
4358
4359     operands[1] = GEN_INT (val >> i);
4360     operands[2] = GEN_INT (i);
4361   }"
4362 )
4363
4364 ;; When generating pic, we need to load the symbol offset into a register.
4365 ;; So that the optimizer does not confuse this with a normal symbol load
4366 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4367 ;; since that is the only type of relocation we can use.
4368
4369 ;; The rather odd constraints on the following are to force reload to leave
4370 ;; the insn alone, and to force the minipool generation pass to then move
4371 ;; the GOT symbol to memory.
4372
4373 (define_insn "pic_load_addr_arm"
4374   [(set (match_operand:SI 0 "s_register_operand" "=r")
4375         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4376   "TARGET_ARM && flag_pic"
4377   "ldr%?\\t%0, %1"
4378   [(set_attr "type" "load1")
4379    (set (attr "pool_range")     (const_int 4096))
4380    (set (attr "neg_pool_range") (const_int 4084))]
4381 )
4382
4383 (define_insn "pic_load_addr_thumb"
4384   [(set (match_operand:SI 0 "s_register_operand" "=l")
4385         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4386   "TARGET_THUMB && flag_pic"
4387   "ldr\\t%0, %1"
4388   [(set_attr "type" "load1")
4389    (set (attr "pool_range") (const_int 1024))]
4390 )
4391
4392 ;; This variant is used for AOF assembly, since it needs to mention the
4393 ;; pic register in the rtl.
4394 (define_expand "pic_load_addr_based"
4395   [(set (match_operand:SI 0 "s_register_operand" "")
4396         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4397   "TARGET_ARM && flag_pic"
4398   "operands[2] = pic_offset_table_rtx;"
4399 )
4400
4401 (define_insn "*pic_load_addr_based_insn"
4402   [(set (match_operand:SI 0 "s_register_operand" "=r")
4403         (unspec:SI [(match_operand 1 "" "")
4404                     (match_operand 2 "s_register_operand" "r")]
4405                    UNSPEC_PIC_SYM))]
4406   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4407   "*
4408 #ifdef AOF_ASSEMBLER
4409   operands[1] = aof_pic_entry (operands[1]);
4410 #endif
4411   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4412   return \"\";
4413   "
4414   [(set_attr "type" "load1")
4415    (set (attr "pool_range")
4416         (if_then_else (eq_attr "is_thumb" "yes")
4417                       (const_int 1024)
4418                       (const_int 4096)))
4419    (set (attr "neg_pool_range")
4420         (if_then_else (eq_attr "is_thumb" "yes")
4421                       (const_int 0)
4422                       (const_int 4084)))]
4423 )
4424
4425 (define_insn "pic_add_dot_plus_four"
4426   [(set (match_operand:SI 0 "register_operand" "+r")
4427         (unspec:SI [(plus:SI (match_dup 0)
4428                              (const (plus:SI (pc) (const_int 4))))]
4429                    UNSPEC_PIC_BASE))
4430    (use (label_ref (match_operand 1 "" "")))]
4431   "TARGET_THUMB && flag_pic"
4432   "*
4433   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4434                              CODE_LABEL_NUMBER (operands[1]));
4435   return \"add\\t%0, %|pc\";
4436   "
4437   [(set_attr "length" "2")]
4438 )
4439
4440 (define_insn "pic_add_dot_plus_eight"
4441   [(set (match_operand:SI 0 "register_operand" "+r")
4442         (unspec:SI [(plus:SI (match_dup 0)
4443                              (const (plus:SI (pc) (const_int 8))))]
4444                    UNSPEC_PIC_BASE))
4445    (use (label_ref (match_operand 1 "" "")))]
4446   "TARGET_ARM && flag_pic"
4447   "*
4448     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4449                                CODE_LABEL_NUMBER (operands[1]));
4450     return \"add%?\\t%0, %|pc, %0\";
4451   "
4452   [(set_attr "predicable" "yes")]
4453 )
4454
4455 (define_expand "builtin_setjmp_receiver"
4456   [(label_ref (match_operand 0 "" ""))]
4457   "flag_pic"
4458   "
4459 {
4460   arm_load_pic_register ();
4461   DONE;
4462 }")
4463
4464 ;; If copying one reg to another we can set the condition codes according to
4465 ;; its value.  Such a move is common after a return from subroutine and the
4466 ;; result is being tested against zero.
4467
4468 (define_insn "*movsi_compare0"
4469   [(set (reg:CC CC_REGNUM)
4470         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4471                     (const_int 0)))
4472    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4473         (match_dup 1))]
4474   "TARGET_ARM"
4475   "@
4476    cmp%?\\t%0, #0
4477    sub%?s\\t%0, %1, #0"
4478   [(set_attr "conds" "set")]
4479 )
4480
4481 ;; Subroutine to store a half word from a register into memory.
4482 ;; Operand 0 is the source register (HImode)
4483 ;; Operand 1 is the destination address in a register (SImode)
4484
4485 ;; In both this routine and the next, we must be careful not to spill
4486 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4487 ;; can generate unrecognizable rtl.
4488
4489 (define_expand "storehi"
4490   [;; store the low byte
4491    (set (match_operand 1 "" "") (match_dup 3))
4492    ;; extract the high byte
4493    (set (match_dup 2)
4494         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4495    ;; store the high byte
4496    (set (match_dup 4) (match_dup 5))]
4497   "TARGET_ARM"
4498   "
4499   {
4500     rtx op1 = operands[1];
4501     rtx addr = XEXP (op1, 0);
4502     enum rtx_code code = GET_CODE (addr);
4503
4504     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4505         || code == MINUS)
4506       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4507
4508     operands[4] = adjust_address (op1, QImode, 1);
4509     operands[1] = adjust_address (operands[1], QImode, 0);
4510     operands[3] = gen_lowpart (QImode, operands[0]);
4511     operands[0] = gen_lowpart (SImode, operands[0]);
4512     operands[2] = gen_reg_rtx (SImode);
4513     operands[5] = gen_lowpart (QImode, operands[2]);
4514   }"
4515 )
4516
4517 (define_expand "storehi_bigend"
4518   [(set (match_dup 4) (match_dup 3))
4519    (set (match_dup 2)
4520         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4521    (set (match_operand 1 "" "") (match_dup 5))]
4522   "TARGET_ARM"
4523   "
4524   {
4525     rtx op1 = operands[1];
4526     rtx addr = XEXP (op1, 0);
4527     enum rtx_code code = GET_CODE (addr);
4528
4529     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4530         || code == MINUS)
4531       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4532
4533     operands[4] = adjust_address (op1, QImode, 1);
4534     operands[1] = adjust_address (operands[1], QImode, 0);
4535     operands[3] = gen_lowpart (QImode, operands[0]);
4536     operands[0] = gen_lowpart (SImode, operands[0]);
4537     operands[2] = gen_reg_rtx (SImode);
4538     operands[5] = gen_lowpart (QImode, operands[2]);
4539   }"
4540 )
4541
4542 ;; Subroutine to store a half word integer constant into memory.
4543 (define_expand "storeinthi"
4544   [(set (match_operand 0 "" "")
4545         (match_operand 1 "" ""))
4546    (set (match_dup 3) (match_dup 2))]
4547   "TARGET_ARM"
4548   "
4549   {
4550     HOST_WIDE_INT value = INTVAL (operands[1]);
4551     rtx addr = XEXP (operands[0], 0);
4552     rtx op0 = operands[0];
4553     enum rtx_code code = GET_CODE (addr);
4554
4555     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4556         || code == MINUS)
4557       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4558
4559     operands[1] = gen_reg_rtx (SImode);
4560     if (BYTES_BIG_ENDIAN)
4561       {
4562         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4563         if ((value & 255) == ((value >> 8) & 255))
4564           operands[2] = operands[1];
4565         else
4566           {
4567             operands[2] = gen_reg_rtx (SImode);
4568             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4569           }
4570       }
4571     else
4572       {
4573         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4574         if ((value & 255) == ((value >> 8) & 255))
4575           operands[2] = operands[1];
4576         else
4577           {
4578             operands[2] = gen_reg_rtx (SImode);
4579             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4580           }
4581       }
4582
4583     operands[3] = adjust_address (op0, QImode, 1);
4584     operands[0] = adjust_address (operands[0], QImode, 0);
4585     operands[2] = gen_lowpart (QImode, operands[2]);
4586     operands[1] = gen_lowpart (QImode, operands[1]);
4587   }"
4588 )
4589
4590 (define_expand "storehi_single_op"
4591   [(set (match_operand:HI 0 "memory_operand" "")
4592         (match_operand:HI 1 "general_operand" ""))]
4593   "TARGET_ARM && arm_arch4"
4594   "
4595   if (!s_register_operand (operands[1], HImode))
4596     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4597   "
4598 )
4599
4600 (define_expand "movhi"
4601   [(set (match_operand:HI 0 "general_operand" "")
4602         (match_operand:HI 1 "general_operand" ""))]
4603   "TARGET_EITHER"
4604   "
4605   if (TARGET_ARM)
4606     {
4607       if (!no_new_pseudos)
4608         {
4609           if (GET_CODE (operands[0]) == MEM)
4610             {
4611               if (arm_arch4)
4612                 {
4613                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4614                   DONE;
4615                 }
4616               if (GET_CODE (operands[1]) == CONST_INT)
4617                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4618               else
4619                 {
4620                   if (GET_CODE (operands[1]) == MEM)
4621                     operands[1] = force_reg (HImode, operands[1]);
4622                   if (BYTES_BIG_ENDIAN)
4623                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4624                   else
4625                    emit_insn (gen_storehi (operands[1], operands[0]));
4626                 }
4627               DONE;
4628             }
4629           /* Sign extend a constant, and keep it in an SImode reg.  */
4630           else if (GET_CODE (operands[1]) == CONST_INT)
4631             {
4632               rtx reg = gen_reg_rtx (SImode);
4633               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4634
4635               /* If the constant is already valid, leave it alone.  */
4636               if (!const_ok_for_arm (val))
4637                 {
4638                   /* If setting all the top bits will make the constant 
4639                      loadable in a single instruction, then set them.  
4640                      Otherwise, sign extend the number.  */
4641
4642                   if (const_ok_for_arm (~(val | ~0xffff)))
4643                     val |= ~0xffff;
4644                   else if (val & 0x8000)
4645                     val |= ~0xffff;
4646                 }
4647
4648               emit_insn (gen_movsi (reg, GEN_INT (val)));
4649               operands[1] = gen_lowpart (HImode, reg);
4650             }
4651           else if (arm_arch4 && optimize && !no_new_pseudos
4652                    && GET_CODE (operands[1]) == MEM)
4653             {
4654               rtx reg = gen_reg_rtx (SImode);
4655
4656               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4657               operands[1] = gen_lowpart (HImode, reg);
4658             }
4659           else if (!arm_arch4)
4660             {
4661               if (GET_CODE (operands[1]) == MEM)
4662                 {
4663                   rtx base;
4664                   rtx offset = const0_rtx;
4665                   rtx reg = gen_reg_rtx (SImode);
4666
4667                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4668                        || (GET_CODE (base) == PLUS
4669                            && (GET_CODE (offset = XEXP (base, 1))
4670                                == CONST_INT)
4671                            && ((INTVAL(offset) & 1) != 1)
4672                            && GET_CODE (base = XEXP (base, 0)) == REG))
4673                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4674                     {
4675                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4676                       rtx new;
4677
4678                       new = gen_rtx_MEM (SImode,
4679                                          plus_constant (base, new_offset));
4680                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4681                       emit_insn (gen_movsi (reg, new));
4682                       if (((INTVAL (offset) & 2) != 0)
4683                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4684                         {
4685                           rtx reg2 = gen_reg_rtx (SImode);
4686
4687                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4688                           reg = reg2;
4689                         }
4690                     }
4691                   else
4692                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4693
4694                   operands[1] = gen_lowpart (HImode, reg);
4695                }
4696            }
4697         }
4698       /* Handle loading a large integer during reload.  */
4699       else if (GET_CODE (operands[1]) == CONST_INT
4700                && !const_ok_for_arm (INTVAL (operands[1]))
4701                && !const_ok_for_arm (~INTVAL (operands[1])))
4702         {
4703           /* Writing a constant to memory needs a scratch, which should
4704              be handled with SECONDARY_RELOADs.  */
4705           if (GET_CODE (operands[0]) != REG)
4706             abort ();
4707
4708           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4709           emit_insn (gen_movsi (operands[0], operands[1]));
4710           DONE;
4711        }
4712     }
4713   else /* TARGET_THUMB */
4714     {
4715       if (!no_new_pseudos)
4716         {
4717           if (GET_CODE (operands[0]) != REG)
4718             operands[1] = force_reg (HImode, operands[1]);
4719
4720           /* ??? We shouldn't really get invalid addresses here, but this can
4721              happen if we are passed a SP (never OK for HImode/QImode) or 
4722              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4723              HImode/QImode) relative address.  */
4724           /* ??? This should perhaps be fixed elsewhere, for instance, in
4725              fixup_stack_1, by checking for other kinds of invalid addresses,
4726              e.g. a bare reference to a virtual register.  This may confuse the
4727              alpha though, which must handle this case differently.  */
4728           if (GET_CODE (operands[0]) == MEM
4729               && !memory_address_p (GET_MODE (operands[0]),
4730                                     XEXP (operands[0], 0)))
4731             operands[0]
4732               = replace_equiv_address (operands[0],
4733                                        copy_to_reg (XEXP (operands[0], 0)));
4734    
4735           if (GET_CODE (operands[1]) == MEM
4736               && !memory_address_p (GET_MODE (operands[1]),
4737                                     XEXP (operands[1], 0)))
4738             operands[1]
4739               = replace_equiv_address (operands[1],
4740                                        copy_to_reg (XEXP (operands[1], 0)));
4741         }
4742       /* Handle loading a large integer during reload.  */
4743       else if (GET_CODE (operands[1]) == CONST_INT
4744                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4745         {
4746           /* Writing a constant to memory needs a scratch, which should
4747              be handled with SECONDARY_RELOADs.  */
4748           if (GET_CODE (operands[0]) != REG)
4749             abort ();
4750
4751           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4752           emit_insn (gen_movsi (operands[0], operands[1]));
4753           DONE;
4754         }
4755     }
4756   "
4757 )
4758
4759 (define_insn "*thumb_movhi_insn"
4760   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4761         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4762   "TARGET_THUMB
4763    && (   register_operand (operands[0], HImode)
4764        || register_operand (operands[1], HImode))"
4765   "*
4766   switch (which_alternative)
4767     {
4768     case 0: return \"add        %0, %1, #0\";
4769     case 2: return \"strh       %1, %0\";
4770     case 3: return \"mov        %0, %1\";
4771     case 4: return \"mov        %0, %1\";
4772     case 5: return \"mov        %0, %1\";
4773     default: abort ();
4774     case 1:
4775       /* The stack pointer can end up being taken as an index register.
4776           Catch this case here and deal with it.  */
4777       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4778           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4779           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4780         {
4781           rtx ops[2];
4782           ops[0] = operands[0];
4783           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4784       
4785           output_asm_insn (\"mov        %0, %1\", ops);
4786
4787           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4788     
4789         }
4790       return \"ldrh     %0, %1\";
4791     }"
4792   [(set_attr "length" "2,4,2,2,2,2")
4793    (set_attr "type" "*,load1,store1,*,*,*")]
4794 )
4795
4796
4797 (define_expand "movhi_bytes"
4798   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4799    (set (match_dup 3)
4800         (zero_extend:SI (match_dup 6)))
4801    (set (match_operand:SI 0 "" "")
4802          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4803   "TARGET_ARM"
4804   "
4805   {
4806     rtx mem1, mem2;
4807     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4808
4809     mem1 = gen_rtx_MEM (QImode, addr);
4810     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4811     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4812     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4813     operands[0] = gen_lowpart (SImode, operands[0]);
4814     operands[1] = mem1;
4815     operands[2] = gen_reg_rtx (SImode);
4816     operands[3] = gen_reg_rtx (SImode);
4817     operands[6] = mem2;
4818
4819     if (BYTES_BIG_ENDIAN)
4820       {
4821         operands[4] = operands[2];
4822         operands[5] = operands[3];
4823       }
4824     else
4825       {
4826         operands[4] = operands[3];
4827         operands[5] = operands[2];
4828       }
4829   }"
4830 )
4831
4832 (define_expand "movhi_bigend"
4833   [(set (match_dup 2)
4834         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4835                    (const_int 16)))
4836    (set (match_dup 3)
4837         (ashiftrt:SI (match_dup 2) (const_int 16)))
4838    (set (match_operand:HI 0 "s_register_operand" "")
4839         (match_dup 4))]
4840   "TARGET_ARM"
4841   "
4842   operands[2] = gen_reg_rtx (SImode);
4843   operands[3] = gen_reg_rtx (SImode);
4844   operands[4] = gen_lowpart (HImode, operands[3]);
4845   "
4846 )
4847
4848 ;; Pattern to recognize insn generated default case above
4849 (define_insn "*movhi_insn_arch4"
4850   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4851         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4852   "TARGET_ARM
4853    && arm_arch4
4854    && (GET_CODE (operands[1]) != CONST_INT
4855        || const_ok_for_arm (INTVAL (operands[1]))
4856        || const_ok_for_arm (~INTVAL (operands[1])))"
4857   "@
4858    mov%?\\t%0, %1\\t%@ movhi
4859    mvn%?\\t%0, #%B1\\t%@ movhi
4860    str%?h\\t%1, %0\\t%@ movhi 
4861    ldr%?h\\t%0, %1\\t%@ movhi"
4862   [(set_attr "type" "*,*,store1,load1")
4863    (set_attr "predicable" "yes")
4864    (set_attr "pool_range" "*,*,*,256")
4865    (set_attr "neg_pool_range" "*,*,*,244")]
4866 )
4867
4868 (define_insn "*movhi_bytes"
4869   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4870         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4871   "TARGET_ARM"
4872   "@
4873    mov%?\\t%0, %1\\t%@ movhi
4874    mvn%?\\t%0, #%B1\\t%@ movhi"
4875   [(set_attr "predicable" "yes")]
4876 )
4877
4878 (define_insn "thumb_movhi_clobber"
4879   [(set (match_operand:HI     0 "memory_operand"   "=m")
4880         (match_operand:HI     1 "register_operand" "l"))
4881    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4882   "TARGET_THUMB"
4883   "*
4884   abort ();"
4885 )
4886         
4887 ;; We use a DImode scratch because we may occasionally need an additional
4888 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4889 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4890 (define_expand "reload_outhi"
4891   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4892               (match_operand:HI 1 "s_register_operand"        "r")
4893               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4894   "TARGET_EITHER"
4895   "if (TARGET_ARM)
4896      arm_reload_out_hi (operands);
4897    else
4898      thumb_reload_out_hi (operands);
4899   DONE;
4900   "
4901 )
4902
4903 (define_expand "reload_inhi"
4904   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4905               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4906               (match_operand:DI 2 "s_register_operand" "=&r")])]
4907   "TARGET_EITHER"
4908   "
4909   if (TARGET_ARM)
4910     arm_reload_in_hi (operands);
4911   else
4912     thumb_reload_out_hi (operands);
4913   DONE;
4914 ")
4915
4916 (define_expand "movqi"
4917   [(set (match_operand:QI 0 "general_operand" "")
4918         (match_operand:QI 1 "general_operand" ""))]
4919   "TARGET_EITHER"
4920   "
4921   if (TARGET_ARM)
4922     {
4923       /* Everything except mem = const or mem = mem can be done easily */
4924
4925       if (!no_new_pseudos)
4926         {
4927           if (GET_CODE (operands[1]) == CONST_INT)
4928             {
4929               rtx reg = gen_reg_rtx (SImode);
4930
4931               emit_insn (gen_movsi (reg, operands[1]));
4932               operands[1] = gen_lowpart (QImode, reg);
4933             }
4934           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4935             {
4936               rtx reg = gen_reg_rtx (SImode);
4937
4938               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4939               operands[1] = gen_lowpart (QImode, reg);
4940             }
4941           if (GET_CODE (operands[0]) == MEM)
4942             operands[1] = force_reg (QImode, operands[1]);
4943         }
4944     }
4945   else /* TARGET_THUMB */
4946     {
4947       if (!no_new_pseudos)
4948         {
4949           if (GET_CODE (operands[0]) != REG)
4950             operands[1] = force_reg (QImode, operands[1]);
4951
4952           /* ??? We shouldn't really get invalid addresses here, but this can
4953              happen if we are passed a SP (never OK for HImode/QImode) or
4954              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4955              HImode/QImode) relative address.  */
4956           /* ??? This should perhaps be fixed elsewhere, for instance, in
4957              fixup_stack_1, by checking for other kinds of invalid addresses,
4958              e.g. a bare reference to a virtual register.  This may confuse the
4959              alpha though, which must handle this case differently.  */
4960           if (GET_CODE (operands[0]) == MEM
4961               && !memory_address_p (GET_MODE (operands[0]),
4962                                      XEXP (operands[0], 0)))
4963             operands[0]
4964               = replace_equiv_address (operands[0],
4965                                        copy_to_reg (XEXP (operands[0], 0)));
4966           if (GET_CODE (operands[1]) == MEM
4967               && !memory_address_p (GET_MODE (operands[1]),
4968                                     XEXP (operands[1], 0)))
4969              operands[1]
4970                = replace_equiv_address (operands[1],
4971                                         copy_to_reg (XEXP (operands[1], 0)));
4972         }
4973       /* Handle loading a large integer during reload.  */
4974       else if (GET_CODE (operands[1]) == CONST_INT
4975                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4976         {
4977           /* Writing a constant to memory needs a scratch, which should
4978              be handled with SECONDARY_RELOADs.  */
4979           if (GET_CODE (operands[0]) != REG)
4980             abort ();
4981
4982           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4983           emit_insn (gen_movsi (operands[0], operands[1]));
4984           DONE;
4985        }
4986     }
4987   "
4988 )
4989
4990
4991 (define_insn "*arm_movqi_insn"
4992   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4993         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4994   "TARGET_ARM
4995    && (   register_operand (operands[0], QImode)
4996        || register_operand (operands[1], QImode))"
4997   "@
4998    mov%?\\t%0, %1
4999    mvn%?\\t%0, #%B1
5000    ldr%?b\\t%0, %1
5001    str%?b\\t%1, %0"
5002   [(set_attr "type" "*,*,load1,store1")
5003    (set_attr "predicable" "yes")]
5004 )
5005
5006 (define_insn "*thumb_movqi_insn"
5007   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5008         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5009   "TARGET_THUMB
5010    && (   register_operand (operands[0], QImode)
5011        || register_operand (operands[1], QImode))"
5012   "@
5013    add\\t%0, %1, #0
5014    ldrb\\t%0, %1
5015    strb\\t%1, %0
5016    mov\\t%0, %1
5017    mov\\t%0, %1
5018    mov\\t%0, %1"
5019   [(set_attr "length" "2")
5020    (set_attr "type" "*,load1,store1,*,*,*")
5021    (set_attr "pool_range" "*,32,*,*,*,*")]
5022 )
5023
5024 (define_expand "movsf"
5025   [(set (match_operand:SF 0 "general_operand" "")
5026         (match_operand:SF 1 "general_operand" ""))]
5027   "TARGET_EITHER"
5028   "
5029   if (TARGET_ARM)
5030     {
5031       if (GET_CODE (operands[0]) == MEM)
5032         operands[1] = force_reg (SFmode, operands[1]);
5033     }
5034   else /* TARGET_THUMB */
5035     {
5036       if (!no_new_pseudos)
5037         {
5038            if (GET_CODE (operands[0]) != REG)
5039              operands[1] = force_reg (SFmode, operands[1]);
5040         }
5041     }
5042   "
5043 )
5044
5045 (define_split
5046   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5047         (match_operand:SF 1 "immediate_operand" ""))]
5048   "TARGET_ARM
5049    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5050    && reload_completed
5051    && GET_CODE (operands[1]) == CONST_DOUBLE"
5052   [(set (match_dup 2) (match_dup 3))]
5053   "
5054   operands[2] = gen_lowpart (SImode, operands[0]);
5055   operands[3] = gen_lowpart (SImode, operands[1]);
5056   if (operands[2] == 0 || operands[3] == 0)
5057     FAIL;
5058   "
5059 )
5060
5061 (define_insn "*arm_movsf_soft_insn"
5062   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5063         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5064   "TARGET_ARM
5065    && TARGET_SOFT_FLOAT
5066    && (GET_CODE (operands[0]) != MEM
5067        || register_operand (operands[1], SFmode))"
5068   "@
5069    mov%?\\t%0, %1
5070    ldr%?\\t%0, %1\\t%@ float
5071    str%?\\t%1, %0\\t%@ float"
5072   [(set_attr "length" "4,4,4")
5073    (set_attr "predicable" "yes")
5074    (set_attr "type" "*,load1,store1")
5075    (set_attr "pool_range" "*,4096,*")
5076    (set_attr "neg_pool_range" "*,4084,*")]
5077 )
5078
5079 ;;; ??? This should have alternatives for constants.
5080 (define_insn "*thumb_movsf_insn"
5081   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5082         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5083   "TARGET_THUMB
5084    && (   register_operand (operands[0], SFmode) 
5085        || register_operand (operands[1], SFmode))"
5086   "@
5087    add\\t%0, %1, #0
5088    ldmia\\t%1, {%0}
5089    stmia\\t%0, {%1}
5090    ldr\\t%0, %1
5091    str\\t%1, %0
5092    mov\\t%0, %1
5093    mov\\t%0, %1"
5094   [(set_attr "length" "2")
5095    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5096    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5097 )
5098
5099 (define_expand "movdf"
5100   [(set (match_operand:DF 0 "general_operand" "")
5101         (match_operand:DF 1 "general_operand" ""))]
5102   "TARGET_EITHER"
5103   "
5104   if (TARGET_ARM)
5105     {
5106       if (GET_CODE (operands[0]) == MEM)
5107         operands[1] = force_reg (DFmode, operands[1]);
5108     }
5109   else /* TARGET_THUMB */
5110     {
5111       if (!no_new_pseudos)
5112         {
5113           if (GET_CODE (operands[0]) != REG)
5114             operands[1] = force_reg (DFmode, operands[1]);
5115         }
5116     }
5117   "
5118 )
5119
5120 ;; Reloading a df mode value stored in integer regs to memory can require a
5121 ;; scratch reg.
5122 (define_expand "reload_outdf"
5123   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5124    (match_operand:DF 1 "s_register_operand" "r")
5125    (match_operand:SI 2 "s_register_operand" "=&r")]
5126   "TARGET_ARM"
5127   "
5128   {
5129     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5130
5131     if (code == REG)
5132       operands[2] = XEXP (operands[0], 0);
5133     else if (code == POST_INC || code == PRE_DEC)
5134       {
5135         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5136         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5137         emit_insn (gen_movdi (operands[0], operands[1]));
5138         DONE;
5139       }
5140     else if (code == PRE_INC)
5141       {
5142         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5143
5144         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5145         operands[2] = reg;
5146       }
5147     else if (code == POST_DEC)
5148       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5149     else
5150       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5151                              XEXP (XEXP (operands[0], 0), 1)));
5152
5153     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5154                             operands[1]));
5155
5156     if (code == POST_DEC)
5157       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5158
5159     DONE;
5160   }"
5161 )
5162
5163 (define_insn "*movdf_soft_insn"
5164   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5165         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5166   "TARGET_ARM && TARGET_SOFT_FLOAT
5167   "
5168   "* return output_move_double (operands);"
5169   [(set_attr "length" "8,8,8")
5170    (set_attr "type" "*,load2,store2")
5171    (set_attr "pool_range" "1020")
5172    (set_attr "neg_pool_range" "1008")]
5173 )
5174
5175 ;;; ??? This should have alternatives for constants.
5176 ;;; ??? This was originally identical to the movdi_insn pattern.
5177 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5178 ;;; thumb_reorg with a memory reference.
5179 (define_insn "*thumb_movdf_insn"
5180   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5181         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5182   "TARGET_THUMB
5183    && (   register_operand (operands[0], DFmode)
5184        || register_operand (operands[1], DFmode))"
5185   "*
5186   switch (which_alternative)
5187     {
5188     default:
5189     case 0:
5190       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5191         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5192       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5193     case 1:
5194       return \"ldmia\\t%1, {%0, %H0}\";
5195     case 2:
5196       return \"stmia\\t%0, {%1, %H1}\";
5197     case 3:
5198       return thumb_load_double_from_address (operands);
5199     case 4:
5200       operands[2] = gen_rtx_MEM (SImode,
5201                                  plus_constant (XEXP (operands[0], 0), 4));
5202       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5203       return \"\";
5204     case 5:
5205       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5206         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5207       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5208     }
5209   "
5210   [(set_attr "length" "4,2,2,6,4,4")
5211    (set_attr "type" "*,load2,store2,load2,store2,*")
5212    (set_attr "pool_range" "*,*,*,1020,*,*")]
5213 )
5214
5215 ;; Vector Moves
5216 (define_expand "movv2si"
5217   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5218         (match_operand:V2SI 1 "general_operand" ""))]
5219   "TARGET_REALLY_IWMMXT"
5220 {
5221 })
5222
5223 (define_expand "movv4hi"
5224   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5225         (match_operand:V4HI 1 "general_operand" ""))]
5226   "TARGET_REALLY_IWMMXT"
5227 {
5228 })
5229
5230 (define_expand "movv8qi"
5231   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5232         (match_operand:V8QI 1 "general_operand" ""))]
5233   "TARGET_REALLY_IWMMXT"
5234 {
5235 })
5236 \f
5237
5238 ;; load- and store-multiple insns
5239 ;; The arm can load/store any set of registers, provided that they are in
5240 ;; ascending order; but that is beyond GCC so stick with what it knows.
5241
5242 (define_expand "load_multiple"
5243   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5244                           (match_operand:SI 1 "" ""))
5245                      (use (match_operand:SI 2 "" ""))])]
5246   "TARGET_ARM"
5247 {
5248   HOST_WIDE_INT offset = 0;
5249
5250   /* Support only fixed point registers.  */
5251   if (GET_CODE (operands[2]) != CONST_INT
5252       || INTVAL (operands[2]) > 14
5253       || INTVAL (operands[2]) < 2
5254       || GET_CODE (operands[1]) != MEM
5255       || GET_CODE (operands[0]) != REG
5256       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5257       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5258     FAIL;
5259
5260   operands[3]
5261     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5262                              force_reg (SImode, XEXP (operands[1], 0)),
5263                              TRUE, FALSE, operands[1], &offset);
5264 })
5265
5266 ;; Load multiple with write-back
5267
5268 (define_insn "*ldmsi_postinc4"
5269   [(match_parallel 0 "load_multiple_operation"
5270     [(set (match_operand:SI 1 "s_register_operand" "=r")
5271           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5272                    (const_int 16)))
5273      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5274           (mem:SI (match_dup 2)))
5275      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5276           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5277      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5278           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5279      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5280           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5281   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5282   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5283   [(set_attr "type" "load4")
5284    (set_attr "predicable" "yes")]
5285 )
5286
5287 (define_insn "*ldmsi_postinc3"
5288   [(match_parallel 0 "load_multiple_operation"
5289     [(set (match_operand:SI 1 "s_register_operand" "=r")
5290           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5291                    (const_int 12)))
5292      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5293           (mem:SI (match_dup 2)))
5294      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5295           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5296      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5297           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5298   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5299   "ldm%?ia\\t%1!, {%3, %4, %5}"
5300   [(set_attr "type" "load3")
5301    (set_attr "predicable" "yes")]
5302 )
5303
5304 (define_insn "*ldmsi_postinc2"
5305   [(match_parallel 0 "load_multiple_operation"
5306     [(set (match_operand:SI 1 "s_register_operand" "=r")
5307           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5308                    (const_int 8)))
5309      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5310           (mem:SI (match_dup 2)))
5311      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5312           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5313   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5314   "ldm%?ia\\t%1!, {%3, %4}"
5315   [(set_attr "type" "load2")
5316    (set_attr "predicable" "yes")]
5317 )
5318
5319 ;; Ordinary load multiple
5320
5321 (define_insn "*ldmsi4"
5322   [(match_parallel 0 "load_multiple_operation"
5323     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5324           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5325      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5326           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5327      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5328           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5329      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5330           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5331   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5332   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5333   [(set_attr "type" "load4")
5334    (set_attr "predicable" "yes")]
5335 )
5336
5337 (define_insn "*ldmsi3"
5338   [(match_parallel 0 "load_multiple_operation"
5339     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5340           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5341      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5342           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5343      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5344           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5345   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5346   "ldm%?ia\\t%1, {%2, %3, %4}"
5347   [(set_attr "type" "load3")
5348    (set_attr "predicable" "yes")]
5349 )
5350
5351 (define_insn "*ldmsi2"
5352   [(match_parallel 0 "load_multiple_operation"
5353     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5354           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5355      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5356           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5357   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5358   "ldm%?ia\\t%1, {%2, %3}"
5359   [(set_attr "type" "load2")
5360    (set_attr "predicable" "yes")]
5361 )
5362
5363 (define_expand "store_multiple"
5364   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5365                           (match_operand:SI 1 "" ""))
5366                      (use (match_operand:SI 2 "" ""))])]
5367   "TARGET_ARM"
5368 {
5369   HOST_WIDE_INT offset = 0;
5370
5371   /* Support only fixed point registers.  */
5372   if (GET_CODE (operands[2]) != CONST_INT
5373       || INTVAL (operands[2]) > 14
5374       || INTVAL (operands[2]) < 2
5375       || GET_CODE (operands[1]) != REG
5376       || GET_CODE (operands[0]) != MEM
5377       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5378       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5379     FAIL;
5380
5381   operands[3]
5382     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5383                               force_reg (SImode, XEXP (operands[0], 0)),
5384                               TRUE, FALSE, operands[0], &offset);
5385 })
5386
5387 ;; Store multiple with write-back
5388
5389 (define_insn "*stmsi_postinc4"
5390   [(match_parallel 0 "store_multiple_operation"
5391     [(set (match_operand:SI 1 "s_register_operand" "=r")
5392           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5393                    (const_int 16)))
5394      (set (mem:SI (match_dup 2))
5395           (match_operand:SI 3 "arm_hard_register_operand" ""))
5396      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5397           (match_operand:SI 4 "arm_hard_register_operand" ""))
5398      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5399           (match_operand:SI 5 "arm_hard_register_operand" ""))
5400      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5401           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5402   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5403   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5404   [(set_attr "predicable" "yes")
5405    (set_attr "type" "store4")]
5406 )
5407
5408 (define_insn "*stmsi_postinc3"
5409   [(match_parallel 0 "store_multiple_operation"
5410     [(set (match_operand:SI 1 "s_register_operand" "=r")
5411           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5412                    (const_int 12)))
5413      (set (mem:SI (match_dup 2))
5414           (match_operand:SI 3 "arm_hard_register_operand" ""))
5415      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5416           (match_operand:SI 4 "arm_hard_register_operand" ""))
5417      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5418           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5419   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5420   "stm%?ia\\t%1!, {%3, %4, %5}"
5421   [(set_attr "predicable" "yes")
5422    (set_attr "type" "store3")]
5423 )
5424
5425 (define_insn "*stmsi_postinc2"
5426   [(match_parallel 0 "store_multiple_operation"
5427     [(set (match_operand:SI 1 "s_register_operand" "=r")
5428           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5429                    (const_int 8)))
5430      (set (mem:SI (match_dup 2))
5431           (match_operand:SI 3 "arm_hard_register_operand" ""))
5432      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5433           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5434   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5435   "stm%?ia\\t%1!, {%3, %4}"
5436   [(set_attr "predicable" "yes")
5437    (set_attr "type" "store2")]
5438 )
5439
5440 ;; Ordinary store multiple
5441
5442 (define_insn "*stmsi4"
5443   [(match_parallel 0 "store_multiple_operation"
5444     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5445           (match_operand:SI 2 "arm_hard_register_operand" ""))
5446      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5447           (match_operand:SI 3 "arm_hard_register_operand" ""))
5448      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5449           (match_operand:SI 4 "arm_hard_register_operand" ""))
5450      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5451           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5452   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5453   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5454   [(set_attr "predicable" "yes")
5455    (set_attr "type" "store4")]
5456 )
5457
5458 (define_insn "*stmsi3"
5459   [(match_parallel 0 "store_multiple_operation"
5460     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5461           (match_operand:SI 2 "arm_hard_register_operand" ""))
5462      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5463           (match_operand:SI 3 "arm_hard_register_operand" ""))
5464      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5465           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5466   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5467   "stm%?ia\\t%1, {%2, %3, %4}"
5468   [(set_attr "predicable" "yes")
5469    (set_attr "type" "store3")]
5470 )
5471
5472 (define_insn "*stmsi2"
5473   [(match_parallel 0 "store_multiple_operation"
5474     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5475           (match_operand:SI 2 "arm_hard_register_operand" ""))
5476      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5477           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5478   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5479   "stm%?ia\\t%1, {%2, %3}"
5480   [(set_attr "predicable" "yes")
5481    (set_attr "type" "store2")]
5482 )
5483
5484 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5485 ;; We could let this apply for blocks of less than this, but it clobbers so
5486 ;; many registers that there is then probably a better way.
5487
5488 (define_expand "movmemqi"
5489   [(match_operand:BLK 0 "general_operand" "")
5490    (match_operand:BLK 1 "general_operand" "")
5491    (match_operand:SI 2 "const_int_operand" "")
5492    (match_operand:SI 3 "const_int_operand" "")]
5493   "TARGET_EITHER"
5494   "
5495   if (TARGET_ARM)
5496     {
5497       if (arm_gen_movmemqi (operands))
5498         DONE;
5499       FAIL;
5500     }
5501   else /* TARGET_THUMB */
5502     {
5503       if (   INTVAL (operands[3]) != 4
5504           || INTVAL (operands[2]) > 48)
5505         FAIL;
5506
5507       thumb_expand_movmemqi (operands);
5508       DONE;
5509     }
5510   "
5511 )
5512
5513 ;; Thumb block-move insns
5514
5515 (define_insn "movmem12b"
5516   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5517         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5518    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5519         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5520    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5521         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5522    (set (match_operand:SI 0 "register_operand" "=l")
5523         (plus:SI (match_dup 2) (const_int 12)))
5524    (set (match_operand:SI 1 "register_operand" "=l")
5525         (plus:SI (match_dup 3) (const_int 12)))
5526    (clobber (match_scratch:SI 4 "=&l"))
5527    (clobber (match_scratch:SI 5 "=&l"))
5528    (clobber (match_scratch:SI 6 "=&l"))]
5529   "TARGET_THUMB"
5530   "* return thumb_output_move_mem_multiple (3, operands);"
5531   [(set_attr "length" "4")
5532    ; This isn't entirely accurate...  It loads as well, but in terms of
5533    ; scheduling the following insn it is better to consider it as a store
5534    (set_attr "type" "store3")]
5535 )
5536
5537 (define_insn "movmem8b"
5538   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5539         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5540    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5541         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5542    (set (match_operand:SI 0 "register_operand" "=l")
5543         (plus:SI (match_dup 2) (const_int 8)))
5544    (set (match_operand:SI 1 "register_operand" "=l")
5545         (plus:SI (match_dup 3) (const_int 8)))
5546    (clobber (match_scratch:SI 4 "=&l"))
5547    (clobber (match_scratch:SI 5 "=&l"))]
5548   "TARGET_THUMB"
5549   "* return thumb_output_move_mem_multiple (2, operands);"
5550   [(set_attr "length" "4")
5551    ; This isn't entirely accurate...  It loads as well, but in terms of
5552    ; scheduling the following insn it is better to consider it as a store
5553    (set_attr "type" "store2")]
5554 )
5555
5556 \f
5557
5558 ;; Compare & branch insns
5559 ;; The range calculations are based as follows:
5560 ;; For forward branches, the address calculation returns the address of
5561 ;; the next instruction.  This is 2 beyond the branch instruction.
5562 ;; For backward branches, the address calculation returns the address of
5563 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5564 ;; instruction for the shortest sequence, and 4 before the branch instruction
5565 ;; if we have to jump around an unconditional branch.
5566 ;; To the basic branch range the PC offset must be added (this is +4).
5567 ;; So for forward branches we have 
5568 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5569 ;; And for backward branches we have 
5570 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5571 ;;
5572 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5573 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5574
5575 (define_expand "cbranchsi4"
5576   [(set (pc) (if_then_else
5577               (match_operator 0 "arm_comparison_operator"
5578                [(match_operand:SI 1 "s_register_operand" "")
5579                 (match_operand:SI 2 "nonmemory_operand" "")])
5580               (label_ref (match_operand 3 "" ""))
5581               (pc)))]
5582   "TARGET_THUMB"
5583   "
5584   if (thumb_cmpneg_operand (operands[2], SImode))
5585     {
5586       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5587                                               operands[3], operands[0]));
5588       DONE;
5589     }
5590   if (!thumb_cmp_operand (operands[2], SImode))
5591     operands[2] = force_reg (SImode, operands[2]);
5592   ")
5593
5594 (define_insn "*cbranchsi4_insn"
5595   [(set (pc) (if_then_else
5596               (match_operator 0 "arm_comparison_operator"
5597                [(match_operand:SI 1 "s_register_operand" "l,*h")
5598                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5599               (label_ref (match_operand 3 "" ""))
5600               (pc)))]
5601   "TARGET_THUMB"
5602   "*
5603   output_asm_insn (\"cmp\\t%1, %2\", operands);
5604
5605   switch (get_attr_length (insn))
5606     {
5607     case 4:  return \"b%d0\\t%l3\";
5608     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5609     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5610     }
5611   "
5612   [(set (attr "far_jump")
5613         (if_then_else
5614             (eq_attr "length" "8")
5615             (const_string "yes")
5616             (const_string "no")))
5617    (set (attr "length") 
5618         (if_then_else
5619             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5620                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5621             (const_int 4)
5622             (if_then_else
5623                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5624                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5625                 (const_int 6)
5626                 (const_int 8))))]
5627 )
5628
5629 (define_insn "cbranchsi4_scratch"
5630   [(set (pc) (if_then_else
5631               (match_operator 4 "arm_comparison_operator"
5632                [(match_operand:SI 1 "s_register_operand" "l,0")
5633                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5634               (label_ref (match_operand 3 "" ""))
5635               (pc)))
5636    (clobber (match_scratch:SI 0 "=l,l"))]
5637   "TARGET_THUMB"
5638   "*
5639   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5640
5641   switch (get_attr_length (insn))
5642     {
5643     case 4:  return \"b%d4\\t%l3\";
5644     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5645     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5646     }
5647   "
5648   [(set (attr "far_jump")
5649         (if_then_else
5650             (eq_attr "length" "8")
5651             (const_string "yes")
5652             (const_string "no")))
5653    (set (attr "length") 
5654         (if_then_else
5655             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5656                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5657             (const_int 4)
5658             (if_then_else
5659                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5660                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5661                 (const_int 6)
5662                 (const_int 8))))]
5663 )
5664 (define_insn "*movsi_cbranchsi4"
5665   [(set (pc)
5666         (if_then_else
5667          (match_operator 3 "arm_comparison_operator"
5668           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5669            (const_int 0)])
5670          (label_ref (match_operand 2 "" ""))
5671          (pc)))
5672    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5673         (match_dup 1))]
5674   "TARGET_THUMB"
5675   "*{
5676   if (which_alternative == 0)
5677     output_asm_insn (\"cmp\t%0, #0\", operands);
5678   else if (which_alternative == 1)
5679     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5680   else
5681     {
5682       output_asm_insn (\"cmp\t%1, #0\", operands);
5683       if (which_alternative == 2)
5684         output_asm_insn (\"mov\t%0, %1\", operands);
5685       else
5686         output_asm_insn (\"str\t%1, %0\", operands);
5687     }
5688   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5689     {
5690     case 4:  return \"b%d3\\t%l2\";
5691     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5692     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5693     }
5694   }"
5695   [(set (attr "far_jump")
5696         (if_then_else
5697             (ior (and (gt (symbol_ref ("which_alternative"))
5698                           (const_int 1))
5699                       (eq_attr "length" "8"))
5700                  (eq_attr "length" "10"))
5701             (const_string "yes")
5702             (const_string "no")))
5703    (set (attr "length")
5704      (if_then_else
5705        (le (symbol_ref ("which_alternative"))
5706                        (const_int 1))
5707        (if_then_else
5708          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5709               (le (minus (match_dup 2) (pc)) (const_int 256)))
5710          (const_int 4)
5711          (if_then_else
5712            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5713                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5714            (const_int 6)
5715            (const_int 8)))
5716        (if_then_else
5717          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5718               (le (minus (match_dup 2) (pc)) (const_int 256)))
5719          (const_int 6)
5720          (if_then_else
5721            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5722                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5723            (const_int 8)
5724            (const_int 10)))))]
5725 )
5726
5727 (define_insn "*negated_cbranchsi4"
5728   [(set (pc)
5729         (if_then_else
5730          (match_operator 0 "arm_comparison_operator"
5731           [(match_operand:SI 1 "s_register_operand" "l")
5732            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5733          (label_ref (match_operand 3 "" ""))
5734          (pc)))]
5735   "TARGET_THUMB"
5736   "*
5737   output_asm_insn (\"cmn\\t%1, %2\", operands);
5738   switch (get_attr_length (insn))
5739     {
5740     case 4:  return \"b%d0\\t%l3\";
5741     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5742     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5743     }
5744   "
5745   [(set (attr "far_jump")
5746         (if_then_else
5747             (eq_attr "length" "8")
5748             (const_string "yes")
5749             (const_string "no")))
5750    (set (attr "length") 
5751         (if_then_else
5752             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5753                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5754             (const_int 4)
5755             (if_then_else
5756                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5757                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5758                 (const_int 6)
5759                 (const_int 8))))]
5760 )
5761
5762 (define_insn "*tbit_cbranch"
5763   [(set (pc)
5764         (if_then_else
5765          (match_operator 0 "equality_operator"
5766           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5767                             (const_int 1)
5768                             (match_operand:SI 2 "const_int_operand" "i"))
5769            (const_int 0)])
5770          (label_ref (match_operand 3 "" ""))
5771          (pc)))
5772    (clobber (match_scratch:SI 4 "=l"))]
5773   "TARGET_THUMB"
5774   "*
5775   {
5776   rtx op[3];
5777   op[0] = operands[4];
5778   op[1] = operands[1];
5779   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5780
5781   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5782   switch (get_attr_length (insn))
5783     {
5784     case 4:  return \"b%d0\\t%l3\";
5785     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5786     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5787     }
5788   }"
5789   [(set (attr "far_jump")
5790         (if_then_else
5791             (eq_attr "length" "8")
5792             (const_string "yes")
5793             (const_string "no")))
5794    (set (attr "length") 
5795         (if_then_else
5796             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5797                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5798             (const_int 4)
5799             (if_then_else
5800                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5801                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5802                 (const_int 6)
5803                 (const_int 8))))]
5804 )
5805   
5806 (define_insn "*tstsi3_cbranch"
5807   [(set (pc)
5808         (if_then_else
5809          (match_operator 3 "equality_operator"
5810           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5811                    (match_operand:SI 1 "s_register_operand" "l"))
5812            (const_int 0)])
5813          (label_ref (match_operand 2 "" ""))
5814          (pc)))]
5815   "TARGET_THUMB"
5816   "*
5817   {
5818   output_asm_insn (\"tst\\t%0, %1\", operands);
5819   switch (get_attr_length (insn))
5820     {
5821     case 4:  return \"b%d3\\t%l2\";
5822     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5823     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5824     }
5825   }"
5826   [(set (attr "far_jump")
5827         (if_then_else
5828             (eq_attr "length" "8")
5829             (const_string "yes")
5830             (const_string "no")))
5831    (set (attr "length") 
5832         (if_then_else
5833             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5834                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5835             (const_int 4)
5836             (if_then_else
5837                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5838                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5839                 (const_int 6)
5840                 (const_int 8))))]
5841 )
5842   
5843 (define_insn "*andsi3_cbranch"
5844   [(set (pc)
5845         (if_then_else
5846          (match_operator 5 "equality_operator"
5847           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5848                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5849            (const_int 0)])
5850          (label_ref (match_operand 4 "" ""))
5851          (pc)))
5852    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5853         (and:SI (match_dup 2) (match_dup 3)))
5854    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5855   "TARGET_THUMB"
5856   "*
5857   {
5858   if (which_alternative == 0)
5859     output_asm_insn (\"and\\t%0, %3\", operands);
5860   else if (which_alternative == 1)
5861     {
5862       output_asm_insn (\"and\\t%1, %3\", operands);
5863       output_asm_insn (\"mov\\t%0, %1\", operands);
5864     }
5865   else
5866     {
5867       output_asm_insn (\"and\\t%1, %3\", operands);
5868       output_asm_insn (\"str\\t%1, %0\", operands);
5869     }
5870
5871   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5872     {
5873     case 4:  return \"b%d5\\t%l4\";
5874     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5875     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5876     }
5877   }"
5878   [(set (attr "far_jump")
5879         (if_then_else
5880             (ior (and (eq (symbol_ref ("which_alternative"))
5881                           (const_int 0))
5882                       (eq_attr "length" "8"))
5883                  (eq_attr "length" "10"))
5884             (const_string "yes")
5885             (const_string "no")))
5886    (set (attr "length")
5887      (if_then_else
5888        (eq (symbol_ref ("which_alternative"))
5889                        (const_int 0))
5890        (if_then_else
5891          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5892               (le (minus (match_dup 4) (pc)) (const_int 256)))
5893          (const_int 4)
5894          (if_then_else
5895            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5896                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5897            (const_int 6)
5898            (const_int 8)))
5899        (if_then_else
5900          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5901               (le (minus (match_dup 4) (pc)) (const_int 256)))
5902          (const_int 6)
5903          (if_then_else
5904            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5905                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5906            (const_int 8)
5907            (const_int 10)))))]
5908 )
5909
5910 (define_insn "*orrsi3_cbranch_scratch"
5911   [(set (pc)
5912         (if_then_else
5913          (match_operator 4 "equality_operator"
5914           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5915                    (match_operand:SI 2 "s_register_operand" "l"))
5916            (const_int 0)])
5917          (label_ref (match_operand 3 "" ""))
5918          (pc)))
5919    (clobber (match_scratch:SI 0 "=l"))]
5920   "TARGET_THUMB"
5921   "*
5922   {
5923   output_asm_insn (\"orr\\t%0, %2\", operands);
5924   switch (get_attr_length (insn))
5925     {
5926     case 4:  return \"b%d4\\t%l3\";
5927     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5928     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5929     }
5930   }"
5931   [(set (attr "far_jump")
5932         (if_then_else
5933             (eq_attr "length" "8")
5934             (const_string "yes")
5935             (const_string "no")))
5936    (set (attr "length") 
5937         (if_then_else
5938             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5939                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5940             (const_int 4)
5941             (if_then_else
5942                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5943                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5944                 (const_int 6)
5945                 (const_int 8))))]
5946 )
5947   
5948 (define_insn "*orrsi3_cbranch"
5949   [(set (pc)
5950         (if_then_else
5951          (match_operator 5 "equality_operator"
5952           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5953                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5954            (const_int 0)])
5955          (label_ref (match_operand 4 "" ""))
5956          (pc)))
5957    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5958         (ior:SI (match_dup 2) (match_dup 3)))
5959    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5960   "TARGET_THUMB"
5961   "*
5962   {
5963   if (which_alternative == 0)
5964     output_asm_insn (\"orr\\t%0, %3\", operands);
5965   else if (which_alternative == 1)
5966     {
5967       output_asm_insn (\"orr\\t%1, %3\", operands);
5968       output_asm_insn (\"mov\\t%0, %1\", operands);
5969     }
5970   else
5971     {
5972       output_asm_insn (\"orr\\t%1, %3\", operands);
5973       output_asm_insn (\"str\\t%1, %0\", operands);
5974     }
5975
5976   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5977     {
5978     case 4:  return \"b%d5\\t%l4\";
5979     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5980     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5981     }
5982   }"
5983   [(set (attr "far_jump")
5984         (if_then_else
5985             (ior (and (eq (symbol_ref ("which_alternative"))
5986                           (const_int 0))
5987                       (eq_attr "length" "8"))
5988                  (eq_attr "length" "10"))
5989             (const_string "yes")
5990             (const_string "no")))
5991    (set (attr "length")
5992      (if_then_else
5993        (eq (symbol_ref ("which_alternative"))
5994                        (const_int 0))
5995        (if_then_else
5996          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5997               (le (minus (match_dup 4) (pc)) (const_int 256)))
5998          (const_int 4)
5999          (if_then_else
6000            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6001                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6002            (const_int 6)
6003            (const_int 8)))
6004        (if_then_else
6005          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6006               (le (minus (match_dup 4) (pc)) (const_int 256)))
6007          (const_int 6)
6008          (if_then_else
6009            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6010                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6011            (const_int 8)
6012            (const_int 10)))))]
6013 )
6014
6015 (define_insn "*xorsi3_cbranch_scratch"
6016   [(set (pc)
6017         (if_then_else
6018          (match_operator 4 "equality_operator"
6019           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6020                    (match_operand:SI 2 "s_register_operand" "l"))
6021            (const_int 0)])
6022          (label_ref (match_operand 3 "" ""))
6023          (pc)))
6024    (clobber (match_scratch:SI 0 "=l"))]
6025   "TARGET_THUMB"
6026   "*
6027   {
6028   output_asm_insn (\"eor\\t%0, %2\", operands);
6029   switch (get_attr_length (insn))
6030     {
6031     case 4:  return \"b%d4\\t%l3\";
6032     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6033     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6034     }
6035   }"
6036   [(set (attr "far_jump")
6037         (if_then_else
6038             (eq_attr "length" "8")
6039             (const_string "yes")
6040             (const_string "no")))
6041    (set (attr "length") 
6042         (if_then_else
6043             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6044                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6045             (const_int 4)
6046             (if_then_else
6047                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6048                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6049                 (const_int 6)
6050                 (const_int 8))))]
6051 )
6052   
6053 (define_insn "*xorsi3_cbranch"
6054   [(set (pc)
6055         (if_then_else
6056          (match_operator 5 "equality_operator"
6057           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6058                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6059            (const_int 0)])
6060          (label_ref (match_operand 4 "" ""))
6061          (pc)))
6062    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6063         (xor:SI (match_dup 2) (match_dup 3)))
6064    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6065   "TARGET_THUMB"
6066   "*
6067   {
6068   if (which_alternative == 0)
6069     output_asm_insn (\"eor\\t%0, %3\", operands);
6070   else if (which_alternative == 1)
6071     {
6072       output_asm_insn (\"eor\\t%1, %3\", operands);
6073       output_asm_insn (\"mov\\t%0, %1\", operands);
6074     }
6075   else
6076     {
6077       output_asm_insn (\"eor\\t%1, %3\", operands);
6078       output_asm_insn (\"str\\t%1, %0\", operands);
6079     }
6080
6081   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6082     {
6083     case 4:  return \"b%d5\\t%l4\";
6084     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6085     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6086     }
6087   }"
6088   [(set (attr "far_jump")
6089         (if_then_else
6090             (ior (and (eq (symbol_ref ("which_alternative"))
6091                           (const_int 0))
6092                       (eq_attr "length" "8"))
6093                  (eq_attr "length" "10"))
6094             (const_string "yes")
6095             (const_string "no")))
6096    (set (attr "length")
6097      (if_then_else
6098        (eq (symbol_ref ("which_alternative"))
6099                        (const_int 0))
6100        (if_then_else
6101          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6102               (le (minus (match_dup 4) (pc)) (const_int 256)))
6103          (const_int 4)
6104          (if_then_else
6105            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6106                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6107            (const_int 6)
6108            (const_int 8)))
6109        (if_then_else
6110          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6111               (le (minus (match_dup 4) (pc)) (const_int 256)))
6112          (const_int 6)
6113          (if_then_else
6114            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6115                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6116            (const_int 8)
6117            (const_int 10)))))]
6118 )
6119
6120 (define_insn "*bicsi3_cbranch_scratch"
6121   [(set (pc)
6122         (if_then_else
6123          (match_operator 4 "equality_operator"
6124           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6125                    (match_operand:SI 1 "s_register_operand" "0"))
6126            (const_int 0)])
6127          (label_ref (match_operand 3 "" ""))
6128          (pc)))
6129    (clobber (match_scratch:SI 0 "=l"))]
6130   "TARGET_THUMB"
6131   "*
6132   {
6133   output_asm_insn (\"bic\\t%0, %2\", operands);
6134   switch (get_attr_length (insn))
6135     {
6136     case 4:  return \"b%d4\\t%l3\";
6137     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6138     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6139     }
6140   }"
6141   [(set (attr "far_jump")
6142         (if_then_else
6143             (eq_attr "length" "8")
6144             (const_string "yes")
6145             (const_string "no")))
6146    (set (attr "length") 
6147         (if_then_else
6148             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6149                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6150             (const_int 4)
6151             (if_then_else
6152                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6153                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6154                 (const_int 6)
6155                 (const_int 8))))]
6156 )
6157   
6158 (define_insn "*bicsi3_cbranch"
6159   [(set (pc)
6160         (if_then_else
6161          (match_operator 5 "equality_operator"
6162           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6163                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6164            (const_int 0)])
6165          (label_ref (match_operand 4 "" ""))
6166          (pc)))
6167    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6168         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6169    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6170   "TARGET_THUMB"
6171   "*
6172   {
6173   if (which_alternative == 0)
6174     output_asm_insn (\"bic\\t%0, %3\", operands);
6175   else if (which_alternative <= 2)
6176     {
6177       output_asm_insn (\"bic\\t%1, %3\", operands);
6178       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6179          conditions again, since we're only testing for equality.  */
6180       output_asm_insn (\"mov\\t%0, %1\", operands);
6181     }
6182   else
6183     {
6184       output_asm_insn (\"bic\\t%1, %3\", operands);
6185       output_asm_insn (\"str\\t%1, %0\", operands);
6186     }
6187
6188   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6189     {
6190     case 4:  return \"b%d5\\t%l4\";
6191     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6192     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6193     }
6194   }"
6195   [(set (attr "far_jump")
6196         (if_then_else
6197             (ior (and (eq (symbol_ref ("which_alternative"))
6198                           (const_int 0))
6199                       (eq_attr "length" "8"))
6200                  (eq_attr "length" "10"))
6201             (const_string "yes")
6202             (const_string "no")))
6203    (set (attr "length")
6204      (if_then_else
6205        (eq (symbol_ref ("which_alternative"))
6206                        (const_int 0))
6207        (if_then_else
6208          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6209               (le (minus (match_dup 4) (pc)) (const_int 256)))
6210          (const_int 4)
6211          (if_then_else
6212            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6213                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6214            (const_int 6)
6215            (const_int 8)))
6216        (if_then_else
6217          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6218               (le (minus (match_dup 4) (pc)) (const_int 256)))
6219          (const_int 6)
6220          (if_then_else
6221            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6222                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6223            (const_int 8)
6224            (const_int 10)))))]
6225 )
6226
6227 (define_insn "*cbranchne_decr1"
6228   [(set (pc)
6229         (if_then_else (match_operator 3 "equality_operator"
6230                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6231                         (const_int 0)])
6232                       (label_ref (match_operand 4 "" ""))
6233                       (pc)))
6234    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6235         (plus:SI (match_dup 2) (const_int -1)))
6236    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6237   "TARGET_THUMB"
6238   "*
6239    {
6240      rtx cond[2];
6241      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6242                                 ? GEU : LTU),
6243                                VOIDmode, operands[2], const1_rtx);
6244      cond[1] = operands[4];
6245
6246      if (which_alternative == 0)
6247        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6248      else if (which_alternative == 1)
6249        {
6250          /* We must provide an alternative for a hi reg because reload 
6251             cannot handle output reloads on a jump instruction, but we
6252             can't subtract into that.  Fortunately a mov from lo to hi
6253             does not clobber the condition codes.  */
6254          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6255          output_asm_insn (\"mov\\t%0, %1\", operands);
6256        }
6257      else
6258        {
6259          /* Similarly, but the target is memory.  */
6260          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6261          output_asm_insn (\"str\\t%1, %0\", operands);
6262        }
6263
6264      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6265        {
6266          case 4:
6267            output_asm_insn (\"b%d0\\t%l1\", cond);
6268            return \"\";
6269          case 6:
6270            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6271            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6272          default:
6273            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6274            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6275        }
6276    }
6277   "
6278   [(set (attr "far_jump")
6279         (if_then_else
6280             (ior (and (eq (symbol_ref ("which_alternative"))
6281                           (const_int 0))
6282                       (eq_attr "length" "8"))
6283                  (eq_attr "length" "10"))
6284             (const_string "yes")
6285             (const_string "no")))
6286    (set_attr_alternative "length"
6287       [
6288        ;; Alternative 0
6289        (if_then_else
6290          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6291               (le (minus (match_dup 4) (pc)) (const_int 256)))
6292          (const_int 4)
6293          (if_then_else
6294            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6295                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6296            (const_int 6)
6297            (const_int 8)))
6298        ;; Alternative 1
6299        (if_then_else
6300          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6301               (le (minus (match_dup 4) (pc)) (const_int 256)))
6302          (const_int 6)
6303          (if_then_else
6304            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6305                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6306            (const_int 8)
6307            (const_int 10)))
6308        ;; Alternative 2
6309        (if_then_else
6310          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6311               (le (minus (match_dup 4) (pc)) (const_int 256)))
6312          (const_int 6)
6313          (if_then_else
6314            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6315                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6316            (const_int 8)
6317            (const_int 10)))
6318        ;; Alternative 3
6319        (if_then_else
6320          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6321               (le (minus (match_dup 4) (pc)) (const_int 256)))
6322          (const_int 6)
6323          (if_then_else
6324            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6325                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6326            (const_int 8)
6327            (const_int 10)))])]
6328 )
6329
6330 (define_insn "*addsi3_cbranch"
6331   [(set (pc)
6332         (if_then_else
6333          (match_operator 4 "comparison_operator"
6334           [(plus:SI
6335             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6336             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6337            (const_int 0)])
6338          (label_ref (match_operand 5 "" ""))
6339          (pc)))
6340    (set
6341     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6342     (plus:SI (match_dup 2) (match_dup 3)))
6343    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6344   "TARGET_THUMB
6345    && (GET_CODE (operands[4]) == EQ
6346        || GET_CODE (operands[4]) == NE
6347        || GET_CODE (operands[4]) == GE
6348        || GET_CODE (operands[4]) == LT)"
6349   "*
6350    {
6351      rtx cond[3];
6352
6353      
6354      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6355      cond[1] = operands[2];
6356      cond[2] = operands[3];
6357
6358      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6359        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6360      else
6361        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6362
6363      if (which_alternative >= 3
6364          && which_alternative < 4)
6365        output_asm_insn (\"mov\\t%0, %1\", operands);
6366      else if (which_alternative >= 4)
6367        output_asm_insn (\"str\\t%1, %0\", operands);
6368
6369      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6370        {
6371          case 4:
6372            return \"b%d4\\t%l5\";
6373          case 6:
6374            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6375          default:
6376            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6377        }
6378    }
6379   "
6380   [(set (attr "far_jump")
6381         (if_then_else
6382             (ior (and (lt (symbol_ref ("which_alternative"))
6383                           (const_int 3))
6384                       (eq_attr "length" "8"))
6385                  (eq_attr "length" "10"))
6386             (const_string "yes")
6387             (const_string "no")))
6388    (set (attr "length")
6389      (if_then_else
6390        (lt (symbol_ref ("which_alternative"))
6391                        (const_int 3))
6392        (if_then_else
6393          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6394               (le (minus (match_dup 5) (pc)) (const_int 256)))
6395          (const_int 4)
6396          (if_then_else
6397            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6398                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6399            (const_int 6)
6400            (const_int 8)))
6401        (if_then_else
6402          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6403               (le (minus (match_dup 5) (pc)) (const_int 256)))
6404          (const_int 6)
6405          (if_then_else
6406            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6407                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6408            (const_int 8)
6409            (const_int 10)))))]
6410 )
6411
6412 (define_insn "*addsi3_cbranch_scratch"
6413   [(set (pc)
6414         (if_then_else
6415          (match_operator 3 "comparison_operator"
6416           [(plus:SI
6417             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6418             (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6419            (const_int 0)])
6420          (label_ref (match_operand 4 "" ""))
6421          (pc)))
6422    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6423   "TARGET_THUMB
6424    && (GET_CODE (operands[3]) == EQ
6425        || GET_CODE (operands[3]) == NE
6426        || GET_CODE (operands[3]) == GE
6427        || GET_CODE (operands[3]) == LT)"
6428   "*
6429    {
6430      switch (which_alternative)
6431        {
6432        case 0:
6433          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6434          break;
6435        case 1:
6436          output_asm_insn (\"cmn\t%1, %2\", operands);
6437          break;
6438        case 2:
6439          output_asm_insn (\"add\t%0, %1, %2\", operands);
6440          break;
6441        case 3:
6442          output_asm_insn (\"add\t%0, %0, %2\", operands);
6443          break;
6444        }
6445
6446      switch (get_attr_length (insn))
6447        {
6448          case 4:
6449            return \"b%d3\\t%l4\";
6450          case 6:
6451            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6452          default:
6453            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6454        }
6455    }
6456   "
6457   [(set (attr "far_jump")
6458         (if_then_else
6459             (eq_attr "length" "8")
6460             (const_string "yes")
6461             (const_string "no")))
6462    (set (attr "length")
6463        (if_then_else
6464          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6465               (le (minus (match_dup 4) (pc)) (const_int 256)))
6466          (const_int 4)
6467          (if_then_else
6468            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6469                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6470            (const_int 6)
6471            (const_int 8))))]
6472 )
6473
6474 (define_insn "*subsi3_cbranch"
6475   [(set (pc)
6476         (if_then_else
6477          (match_operator 4 "comparison_operator"
6478           [(minus:SI
6479             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6480             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6481            (const_int 0)])
6482          (label_ref (match_operand 5 "" ""))
6483          (pc)))
6484    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6485         (minus:SI (match_dup 2) (match_dup 3)))
6486    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6487   "TARGET_THUMB
6488    && (GET_CODE (operands[4]) == EQ
6489        || GET_CODE (operands[4]) == NE
6490        || GET_CODE (operands[4]) == GE
6491        || GET_CODE (operands[4]) == LT)"
6492   "*
6493    {
6494      if (which_alternative == 0)
6495        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6496      else if (which_alternative == 1)
6497        {
6498          /* We must provide an alternative for a hi reg because reload 
6499             cannot handle output reloads on a jump instruction, but we
6500             can't subtract into that.  Fortunately a mov from lo to hi
6501             does not clobber the condition codes.  */
6502          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6503          output_asm_insn (\"mov\\t%0, %1\", operands);
6504        }
6505      else
6506        {
6507          /* Similarly, but the target is memory.  */
6508          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6509          output_asm_insn (\"str\\t%1, %0\", operands);
6510        }
6511
6512      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6513        {
6514          case 4:
6515            return \"b%d4\\t%l5\";
6516          case 6:
6517            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6518          default:
6519            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6520        }
6521    }
6522   "
6523   [(set (attr "far_jump")
6524         (if_then_else
6525             (ior (and (eq (symbol_ref ("which_alternative"))
6526                           (const_int 0))
6527                       (eq_attr "length" "8"))
6528                  (eq_attr "length" "10"))
6529             (const_string "yes")
6530             (const_string "no")))
6531    (set (attr "length")
6532      (if_then_else
6533        (eq (symbol_ref ("which_alternative"))
6534                        (const_int 0))
6535        (if_then_else
6536          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6537               (le (minus (match_dup 5) (pc)) (const_int 256)))
6538          (const_int 4)
6539          (if_then_else
6540            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6541                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6542            (const_int 6)
6543            (const_int 8)))
6544        (if_then_else
6545          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6546               (le (minus (match_dup 5) (pc)) (const_int 256)))
6547          (const_int 6)
6548          (if_then_else
6549            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6550                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6551            (const_int 8)
6552            (const_int 10)))))]
6553 )
6554
6555 (define_insn "*subsi3_cbranch_scratch"
6556   [(set (pc)
6557         (if_then_else
6558          (match_operator 0 "arm_comparison_operator"
6559           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6560                      (match_operand:SI 2 "nonmemory_operand" "l"))
6561            (const_int 0)])
6562          (label_ref (match_operand 3 "" ""))
6563          (pc)))]
6564   "TARGET_THUMB
6565    && (GET_CODE (operands[0]) == EQ
6566        || GET_CODE (operands[0]) == NE
6567        || GET_CODE (operands[0]) == GE
6568        || GET_CODE (operands[0]) == LT)"
6569   "*
6570   output_asm_insn (\"cmp\\t%1, %2\", operands);
6571   switch (get_attr_length (insn))
6572     {
6573     case 4:  return \"b%d0\\t%l3\";
6574     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6575     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6576     }
6577   "
6578   [(set (attr "far_jump")
6579         (if_then_else
6580             (eq_attr "length" "8")
6581             (const_string "yes")
6582             (const_string "no")))
6583    (set (attr "length") 
6584         (if_then_else
6585             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6586                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6587             (const_int 4)
6588             (if_then_else
6589                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6590                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6591                 (const_int 6)
6592                 (const_int 8))))]
6593 )
6594
6595 ;; Comparison and test insns
6596
6597 (define_expand "cmpsi"
6598   [(match_operand:SI 0 "s_register_operand" "")
6599    (match_operand:SI 1 "arm_add_operand" "")]
6600   "TARGET_ARM"
6601   "{
6602     arm_compare_op0 = operands[0];
6603     arm_compare_op1 = operands[1];
6604     DONE;
6605   }"
6606 )
6607
6608 (define_expand "cmpsf"
6609   [(match_operand:SF 0 "s_register_operand" "")
6610    (match_operand:SF 1 "arm_float_compare_operand" "")]
6611   "TARGET_ARM && TARGET_HARD_FLOAT"
6612   "
6613   arm_compare_op0 = operands[0];
6614   arm_compare_op1 = operands[1];
6615   DONE;
6616   "
6617 )
6618
6619 (define_expand "cmpdf"
6620   [(match_operand:DF 0 "s_register_operand" "")
6621    (match_operand:DF 1 "arm_float_compare_operand" "")]
6622   "TARGET_ARM && TARGET_HARD_FLOAT"
6623   "
6624   arm_compare_op0 = operands[0];
6625   arm_compare_op1 = operands[1];
6626   DONE;
6627   "
6628 )
6629
6630 (define_insn "*arm_cmpsi_insn"
6631   [(set (reg:CC CC_REGNUM)
6632         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6633                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6634   "TARGET_ARM"
6635   "@
6636    cmp%?\\t%0, %1
6637    cmn%?\\t%0, #%n1"
6638   [(set_attr "conds" "set")]
6639 )
6640
6641 (define_insn "*cmpsi_shiftsi"
6642   [(set (reg:CC CC_REGNUM)
6643         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6644                     (match_operator:SI  3 "shift_operator"
6645                      [(match_operand:SI 1 "s_register_operand" "r")
6646                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6647   "TARGET_ARM"
6648   "cmp%?\\t%0, %1%S3"
6649   [(set_attr "conds" "set")
6650    (set_attr "shift" "1")
6651    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6652                       (const_string "alu_shift")
6653                       (const_string "alu_shift_reg")))]
6654 )
6655
6656 (define_insn "*cmpsi_shiftsi_swp"
6657   [(set (reg:CC_SWP CC_REGNUM)
6658         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6659                          [(match_operand:SI 1 "s_register_operand" "r")
6660                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6661                         (match_operand:SI 0 "s_register_operand" "r")))]
6662   "TARGET_ARM"
6663   "cmp%?\\t%0, %1%S3"
6664   [(set_attr "conds" "set")
6665    (set_attr "shift" "1")
6666    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6667                       (const_string "alu_shift")
6668                       (const_string "alu_shift_reg")))]
6669 )
6670
6671 (define_insn "*cmpsi_neg_shiftsi"
6672   [(set (reg:CC CC_REGNUM)
6673         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6674                     (neg:SI (match_operator:SI 3 "shift_operator"
6675                              [(match_operand:SI 1 "s_register_operand" "r")
6676                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6677   "TARGET_ARM"
6678   "cmn%?\\t%0, %1%S3"
6679   [(set_attr "conds" "set")
6680    (set_attr "shift" "1")
6681    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6682                       (const_string "alu_shift")
6683                       (const_string "alu_shift_reg")))]
6684 )
6685
6686 ;; Cirrus SF compare instruction
6687 (define_insn "*cirrus_cmpsf"
6688   [(set (reg:CCFP CC_REGNUM)
6689         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6690                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6691   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6692   "cfcmps%?\\tr15, %V0, %V1"
6693   [(set_attr "type"   "mav_farith")
6694    (set_attr "cirrus" "compare")]
6695 )
6696
6697 ;; Cirrus DF compare instruction
6698 (define_insn "*cirrus_cmpdf"
6699   [(set (reg:CCFP CC_REGNUM)
6700         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6701                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6702   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6703   "cfcmpd%?\\tr15, %V0, %V1"
6704   [(set_attr "type"   "mav_farith")
6705    (set_attr "cirrus" "compare")]
6706 )
6707
6708 ;; Cirrus DI compare instruction
6709 (define_expand "cmpdi"
6710   [(match_operand:DI 0 "cirrus_fp_register" "")
6711    (match_operand:DI 1 "cirrus_fp_register" "")]
6712   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6713   "{
6714      arm_compare_op0 = operands[0];
6715      arm_compare_op1 = operands[1];
6716      DONE;
6717    }")
6718
6719 (define_insn "*cirrus_cmpdi"
6720   [(set (reg:CC CC_REGNUM)
6721         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6722                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6723   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6724   "cfcmp64%?\\tr15, %V0, %V1"
6725   [(set_attr "type"   "mav_farith")
6726    (set_attr "cirrus" "compare")]
6727 )
6728
6729 ; This insn allows redundant compares to be removed by cse, nothing should
6730 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6731 ; is deleted later on. The match_dup will match the mode here, so that
6732 ; mode changes of the condition codes aren't lost by this even though we don't
6733 ; specify what they are.
6734
6735 (define_insn "*deleted_compare"
6736   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6737   "TARGET_ARM"
6738   "\\t%@ deleted compare"
6739   [(set_attr "conds" "set")
6740    (set_attr "length" "0")]
6741 )
6742
6743 \f
6744 ;; Conditional branch insns
6745
6746 (define_expand "beq"
6747   [(set (pc)
6748         (if_then_else (eq (match_dup 1) (const_int 0))
6749                       (label_ref (match_operand 0 "" ""))
6750                       (pc)))]
6751   "TARGET_ARM"
6752   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6753 )
6754
6755 (define_expand "bne"
6756   [(set (pc)
6757         (if_then_else (ne (match_dup 1) (const_int 0))
6758                       (label_ref (match_operand 0 "" ""))
6759                       (pc)))]
6760   "TARGET_ARM"
6761   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6762 )
6763
6764 (define_expand "bgt"
6765   [(set (pc)
6766         (if_then_else (gt (match_dup 1) (const_int 0))
6767                       (label_ref (match_operand 0 "" ""))
6768                       (pc)))]
6769   "TARGET_ARM"
6770   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6771 )
6772
6773 (define_expand "ble"
6774   [(set (pc)
6775         (if_then_else (le (match_dup 1) (const_int 0))
6776                       (label_ref (match_operand 0 "" ""))
6777                       (pc)))]
6778   "TARGET_ARM"
6779   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6780 )
6781
6782 (define_expand "bge"
6783   [(set (pc)
6784         (if_then_else (ge (match_dup 1) (const_int 0))
6785                       (label_ref (match_operand 0 "" ""))
6786                       (pc)))]
6787   "TARGET_ARM"
6788   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6789 )
6790
6791 (define_expand "blt"
6792   [(set (pc)
6793         (if_then_else (lt (match_dup 1) (const_int 0))
6794                       (label_ref (match_operand 0 "" ""))
6795                       (pc)))]
6796   "TARGET_ARM"
6797   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6798 )
6799
6800 (define_expand "bgtu"
6801   [(set (pc)
6802         (if_then_else (gtu (match_dup 1) (const_int 0))
6803                       (label_ref (match_operand 0 "" ""))
6804                       (pc)))]
6805   "TARGET_ARM"
6806   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6807 )
6808
6809 (define_expand "bleu"
6810   [(set (pc)
6811         (if_then_else (leu (match_dup 1) (const_int 0))
6812                       (label_ref (match_operand 0 "" ""))
6813                       (pc)))]
6814   "TARGET_ARM"
6815   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6816 )
6817
6818 (define_expand "bgeu"
6819   [(set (pc)
6820         (if_then_else (geu (match_dup 1) (const_int 0))
6821                       (label_ref (match_operand 0 "" ""))
6822                       (pc)))]
6823   "TARGET_ARM"
6824   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6825 )
6826
6827 (define_expand "bltu"
6828   [(set (pc)
6829         (if_then_else (ltu (match_dup 1) (const_int 0))
6830                       (label_ref (match_operand 0 "" ""))
6831                       (pc)))]
6832   "TARGET_ARM"
6833   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6834 )
6835
6836 (define_expand "bunordered"
6837   [(set (pc)
6838         (if_then_else (unordered (match_dup 1) (const_int 0))
6839                       (label_ref (match_operand 0 "" ""))
6840                       (pc)))]
6841   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6842   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6843                                       arm_compare_op1);"
6844 )
6845
6846 (define_expand "bordered"
6847   [(set (pc)
6848         (if_then_else (ordered (match_dup 1) (const_int 0))
6849                       (label_ref (match_operand 0 "" ""))
6850                       (pc)))]
6851   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6852   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6853                                       arm_compare_op1);"
6854 )
6855
6856 (define_expand "bungt"
6857   [(set (pc)
6858         (if_then_else (ungt (match_dup 1) (const_int 0))
6859                       (label_ref (match_operand 0 "" ""))
6860                       (pc)))]
6861   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6862   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6863 )
6864
6865 (define_expand "bunlt"
6866   [(set (pc)
6867         (if_then_else (unlt (match_dup 1) (const_int 0))
6868                       (label_ref (match_operand 0 "" ""))
6869                       (pc)))]
6870   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6871   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6872 )
6873
6874 (define_expand "bunge"
6875   [(set (pc)
6876         (if_then_else (unge (match_dup 1) (const_int 0))
6877                       (label_ref (match_operand 0 "" ""))
6878                       (pc)))]
6879   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6880   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6881 )
6882
6883 (define_expand "bunle"
6884   [(set (pc)
6885         (if_then_else (unle (match_dup 1) (const_int 0))
6886                       (label_ref (match_operand 0 "" ""))
6887                       (pc)))]
6888   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6889   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6890 )
6891
6892 ;; The following two patterns need two branch instructions, since there is
6893 ;; no single instruction that will handle all cases.
6894 (define_expand "buneq"
6895   [(set (pc)
6896         (if_then_else (uneq (match_dup 1) (const_int 0))
6897                       (label_ref (match_operand 0 "" ""))
6898                       (pc)))]
6899   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6900   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6901 )
6902
6903 (define_expand "bltgt"
6904   [(set (pc)
6905         (if_then_else (ltgt (match_dup 1) (const_int 0))
6906                       (label_ref (match_operand 0 "" ""))
6907                       (pc)))]
6908   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6909   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6910 )
6911
6912 ;;
6913 ;; Patterns to match conditional branch insns.
6914 ;;
6915
6916 ; Special pattern to match UNEQ.
6917 (define_insn "*arm_buneq"
6918   [(set (pc)
6919         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6920                       (label_ref (match_operand 0 "" ""))
6921                       (pc)))]
6922   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6923   "*
6924   if (arm_ccfsm_state != 0)
6925     abort ();
6926
6927   return \"bvs\\t%l0\;beq\\t%l0\";
6928   "
6929   [(set_attr "conds" "jump_clob")
6930    (set_attr "length" "8")]
6931 )
6932
6933 ; Special pattern to match LTGT.
6934 (define_insn "*arm_bltgt"
6935   [(set (pc)
6936         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6937                       (label_ref (match_operand 0 "" ""))
6938                       (pc)))]
6939   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6940   "*
6941   if (arm_ccfsm_state != 0)
6942     abort ();
6943
6944   return \"bmi\\t%l0\;bgt\\t%l0\";
6945   "
6946   [(set_attr "conds" "jump_clob")
6947    (set_attr "length" "8")]
6948 )
6949
6950 (define_insn "*arm_cond_branch"
6951   [(set (pc)
6952         (if_then_else (match_operator 1 "arm_comparison_operator"
6953                        [(match_operand 2 "cc_register" "") (const_int 0)])
6954                       (label_ref (match_operand 0 "" ""))
6955                       (pc)))]
6956   "TARGET_ARM"
6957   "*
6958   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6959     {
6960       arm_ccfsm_state += 2;
6961       return \"\";
6962     }
6963   return \"b%d1\\t%l0\";
6964   "
6965   [(set_attr "conds" "use")
6966    (set_attr "type" "branch")]
6967 )
6968
6969 ; Special pattern to match reversed UNEQ.
6970 (define_insn "*arm_buneq_reversed"
6971   [(set (pc)
6972         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6973                       (pc)
6974                       (label_ref (match_operand 0 "" ""))))]
6975   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6976   "*
6977   if (arm_ccfsm_state != 0)
6978     abort ();
6979
6980   return \"bmi\\t%l0\;bgt\\t%l0\";
6981   "
6982   [(set_attr "conds" "jump_clob")
6983    (set_attr "length" "8")]
6984 )
6985
6986 ; Special pattern to match reversed LTGT.
6987 (define_insn "*arm_bltgt_reversed"
6988   [(set (pc)
6989         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6990                       (pc)
6991                       (label_ref (match_operand 0 "" ""))))]
6992   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6993   "*
6994   if (arm_ccfsm_state != 0)
6995     abort ();
6996
6997   return \"bvs\\t%l0\;beq\\t%l0\";
6998   "
6999   [(set_attr "conds" "jump_clob")
7000    (set_attr "length" "8")]
7001 )
7002
7003 (define_insn "*arm_cond_branch_reversed"
7004   [(set (pc)
7005         (if_then_else (match_operator 1 "arm_comparison_operator"
7006                        [(match_operand 2 "cc_register" "") (const_int 0)])
7007                       (pc)
7008                       (label_ref (match_operand 0 "" ""))))]
7009   "TARGET_ARM"
7010   "*
7011   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7012     {
7013       arm_ccfsm_state += 2;
7014       return \"\";
7015     }
7016   return \"b%D1\\t%l0\";
7017   "
7018   [(set_attr "conds" "use")
7019    (set_attr "type" "branch")]
7020 )
7021
7022 \f
7023
7024 ; scc insns
7025
7026 (define_expand "seq"
7027   [(set (match_operand:SI 0 "s_register_operand" "")
7028         (eq:SI (match_dup 1) (const_int 0)))]
7029   "TARGET_ARM"
7030   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7031 )
7032
7033 (define_expand "sne"
7034   [(set (match_operand:SI 0 "s_register_operand" "")
7035         (ne:SI (match_dup 1) (const_int 0)))]
7036   "TARGET_ARM"
7037   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7038 )
7039
7040 (define_expand "sgt"
7041   [(set (match_operand:SI 0 "s_register_operand" "")
7042         (gt:SI (match_dup 1) (const_int 0)))]
7043   "TARGET_ARM"
7044   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7045 )
7046
7047 (define_expand "sle"
7048   [(set (match_operand:SI 0 "s_register_operand" "")
7049         (le:SI (match_dup 1) (const_int 0)))]
7050   "TARGET_ARM"
7051   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7052 )
7053
7054 (define_expand "sge"
7055   [(set (match_operand:SI 0 "s_register_operand" "")
7056         (ge:SI (match_dup 1) (const_int 0)))]
7057   "TARGET_ARM"
7058   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7059 )
7060
7061 (define_expand "slt"
7062   [(set (match_operand:SI 0 "s_register_operand" "")
7063         (lt:SI (match_dup 1) (const_int 0)))]
7064   "TARGET_ARM"
7065   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7066 )
7067
7068 (define_expand "sgtu"
7069   [(set (match_operand:SI 0 "s_register_operand" "")
7070         (gtu:SI (match_dup 1) (const_int 0)))]
7071   "TARGET_ARM"
7072   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7073 )
7074
7075 (define_expand "sleu"
7076   [(set (match_operand:SI 0 "s_register_operand" "")
7077         (leu:SI (match_dup 1) (const_int 0)))]
7078   "TARGET_ARM"
7079   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7080 )
7081
7082 (define_expand "sgeu"
7083   [(set (match_operand:SI 0 "s_register_operand" "")
7084         (geu:SI (match_dup 1) (const_int 0)))]
7085   "TARGET_ARM"
7086   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7087 )
7088
7089 (define_expand "sltu"
7090   [(set (match_operand:SI 0 "s_register_operand" "")
7091         (ltu:SI (match_dup 1) (const_int 0)))]
7092   "TARGET_ARM"
7093   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7094 )
7095
7096 (define_expand "sunordered"
7097   [(set (match_operand:SI 0 "s_register_operand" "")
7098         (unordered:SI (match_dup 1) (const_int 0)))]
7099   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7100   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7101                                       arm_compare_op1);"
7102 )
7103
7104 (define_expand "sordered"
7105   [(set (match_operand:SI 0 "s_register_operand" "")
7106         (ordered:SI (match_dup 1) (const_int 0)))]
7107   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7108   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7109                                       arm_compare_op1);"
7110 )
7111
7112 (define_expand "sungt"
7113   [(set (match_operand:SI 0 "s_register_operand" "")
7114         (ungt:SI (match_dup 1) (const_int 0)))]
7115   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7116   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7117                                       arm_compare_op1);"
7118 )
7119
7120 (define_expand "sunge"
7121   [(set (match_operand:SI 0 "s_register_operand" "")
7122         (unge:SI (match_dup 1) (const_int 0)))]
7123   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7124   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7125                                       arm_compare_op1);"
7126 )
7127
7128 (define_expand "sunlt"
7129   [(set (match_operand:SI 0 "s_register_operand" "")
7130         (unlt:SI (match_dup 1) (const_int 0)))]
7131   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7132   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7133                                       arm_compare_op1);"
7134 )
7135
7136 (define_expand "sunle"
7137   [(set (match_operand:SI 0 "s_register_operand" "")
7138         (unle:SI (match_dup 1) (const_int 0)))]
7139   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7140   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7141                                       arm_compare_op1);"
7142 )
7143
7144 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7145 ;;; simple ARM instructions. 
7146 ;
7147 ; (define_expand "suneq"
7148 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7149 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7150 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7151 ;   "abort ();"
7152 ; )
7153 ;
7154 ; (define_expand "sltgt"
7155 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7156 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7157 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7158 ;   "abort ();"
7159 ; )
7160
7161 (define_insn "*mov_scc"
7162   [(set (match_operand:SI 0 "s_register_operand" "=r")
7163         (match_operator:SI 1 "arm_comparison_operator"
7164          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7165   "TARGET_ARM"
7166   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7167   [(set_attr "conds" "use")
7168    (set_attr "length" "8")]
7169 )
7170
7171 (define_insn "*mov_negscc"
7172   [(set (match_operand:SI 0 "s_register_operand" "=r")
7173         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7174                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7175   "TARGET_ARM"
7176   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7177   [(set_attr "conds" "use")
7178    (set_attr "length" "8")]
7179 )
7180
7181 (define_insn "*mov_notscc"
7182   [(set (match_operand:SI 0 "s_register_operand" "=r")
7183         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7184                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7185   "TARGET_ARM"
7186   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7187   [(set_attr "conds" "use")
7188    (set_attr "length" "8")]
7189 )
7190
7191 \f
7192 ;; Conditional move insns
7193
7194 (define_expand "movsicc"
7195   [(set (match_operand:SI 0 "s_register_operand" "")
7196         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7197                          (match_operand:SI 2 "arm_not_operand" "")
7198                          (match_operand:SI 3 "arm_not_operand" "")))]
7199   "TARGET_ARM"
7200   "
7201   {
7202     enum rtx_code code = GET_CODE (operands[1]);
7203     rtx ccreg;
7204
7205     if (code == UNEQ || code == LTGT)
7206       FAIL;
7207
7208     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7209     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7210   }"
7211 )
7212
7213 (define_expand "movsfcc"
7214   [(set (match_operand:SF 0 "s_register_operand" "")
7215         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7216                          (match_operand:SF 2 "s_register_operand" "")
7217                          (match_operand:SF 3 "nonmemory_operand" "")))]
7218   "TARGET_ARM"
7219   "
7220   {
7221     enum rtx_code code = GET_CODE (operands[1]);
7222     rtx ccreg;
7223
7224     if (code == UNEQ || code == LTGT)
7225       FAIL;
7226
7227     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7228        Otherwise, ensure it is a valid FP add operand */
7229     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7230         || (!arm_float_add_operand (operands[3], SFmode)))
7231       operands[3] = force_reg (SFmode, operands[3]);
7232
7233     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7234     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7235   }"
7236 )
7237
7238 (define_expand "movdfcc"
7239   [(set (match_operand:DF 0 "s_register_operand" "")
7240         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7241                          (match_operand:DF 2 "s_register_operand" "")
7242                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7243   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7244   "
7245   {
7246     enum rtx_code code = GET_CODE (operands[1]);
7247     rtx ccreg;
7248
7249     if (code == UNEQ || code == LTGT)
7250       FAIL;
7251
7252     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7253     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7254   }"
7255 )
7256
7257 (define_insn "*movsicc_insn"
7258   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7259         (if_then_else:SI
7260          (match_operator 3 "arm_comparison_operator"
7261           [(match_operand 4 "cc_register" "") (const_int 0)])
7262          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7263          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7264   "TARGET_ARM"
7265   "@
7266    mov%D3\\t%0, %2
7267    mvn%D3\\t%0, #%B2
7268    mov%d3\\t%0, %1
7269    mvn%d3\\t%0, #%B1
7270    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7271    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7272    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7273    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7274   [(set_attr "length" "4,4,4,4,8,8,8,8")
7275    (set_attr "conds" "use")]
7276 )
7277
7278 (define_insn "*movsfcc_soft_insn"
7279   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7280         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7281                           [(match_operand 4 "cc_register" "") (const_int 0)])
7282                          (match_operand:SF 1 "s_register_operand" "0,r")
7283                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7284   "TARGET_ARM && TARGET_SOFT_FLOAT"
7285   "@
7286    mov%D3\\t%0, %2
7287    mov%d3\\t%0, %1"
7288   [(set_attr "conds" "use")]
7289 )
7290
7291 \f
7292 ;; Jump and linkage insns
7293
7294 (define_expand "jump"
7295   [(set (pc)
7296         (label_ref (match_operand 0 "" "")))]
7297   "TARGET_EITHER"
7298   ""
7299 )
7300
7301 (define_insn "*arm_jump"
7302   [(set (pc)
7303         (label_ref (match_operand 0 "" "")))]
7304   "TARGET_ARM"
7305   "*
7306   {
7307     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7308       {
7309         arm_ccfsm_state += 2;
7310         return \"\";
7311       }
7312     return \"b%?\\t%l0\";
7313   }
7314   "
7315   [(set_attr "predicable" "yes")]
7316 )
7317
7318 (define_insn "*thumb_jump"
7319   [(set (pc)
7320         (label_ref (match_operand 0 "" "")))]
7321   "TARGET_THUMB"
7322   "*
7323   if (get_attr_length (insn) == 2)
7324     return \"b\\t%l0\";
7325   return \"bl\\t%l0\\t%@ far jump\";
7326   "
7327   [(set (attr "far_jump")
7328         (if_then_else
7329             (eq_attr "length" "4")
7330             (const_string "yes")
7331             (const_string "no")))
7332    (set (attr "length") 
7333         (if_then_else
7334             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7335                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7336             (const_int 2)
7337             (const_int 4)))]
7338 )
7339
7340 (define_expand "call"
7341   [(parallel [(call (match_operand 0 "memory_operand" "")
7342                     (match_operand 1 "general_operand" ""))
7343               (use (match_operand 2 "" ""))
7344               (clobber (reg:SI LR_REGNUM))])]
7345   "TARGET_EITHER"
7346   "
7347   {
7348     rtx callee;
7349     
7350     /* In an untyped call, we can get NULL for operand 2.  */
7351     if (operands[2] == NULL_RTX)
7352       operands[2] = const0_rtx;
7353       
7354     /* This is to decide if we should generate indirect calls by loading the
7355        32 bit address of the callee into a register before performing the
7356        branch and link.  operand[2] encodes the long_call/short_call
7357        attribute of the function being called.  This attribute is set whenever
7358        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7359        is used, and the short_call attribute can also be set if function is
7360        declared as static or if it has already been defined in the current
7361        compilation unit.  See arm.c and arm.h for info about this.  The third
7362        parameter to arm_is_longcall_p is used to tell it which pattern
7363        invoked it.  */
7364     callee  = XEXP (operands[0], 0);
7365     
7366     if (GET_CODE (callee) != REG
7367        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7368       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7369   }"
7370 )
7371
7372 (define_insn "*call_reg_armv5"
7373   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7374          (match_operand 1 "" ""))
7375    (use (match_operand 2 "" ""))
7376    (clobber (reg:SI LR_REGNUM))]
7377   "TARGET_ARM && arm_arch5"
7378   "blx%?\\t%0"
7379   [(set_attr "type" "call")]
7380 )
7381
7382 (define_insn "*call_reg_arm"
7383   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7384          (match_operand 1 "" ""))
7385    (use (match_operand 2 "" ""))
7386    (clobber (reg:SI LR_REGNUM))]
7387   "TARGET_ARM && !arm_arch5"
7388   "*
7389   return output_call (operands);
7390   "
7391   ;; length is worst case, normally it is only two
7392   [(set_attr "length" "12")
7393    (set_attr "type" "call")]
7394 )
7395
7396 (define_insn "*call_mem"
7397   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7398          (match_operand 1 "" ""))
7399    (use (match_operand 2 "" ""))
7400    (clobber (reg:SI LR_REGNUM))]
7401   "TARGET_ARM"
7402   "*
7403   return output_call_mem (operands);
7404   "
7405   [(set_attr "length" "12")
7406    (set_attr "type" "call")]
7407 )
7408
7409 (define_insn "*call_reg_thumb_v5"
7410   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7411          (match_operand 1 "" ""))
7412    (use (match_operand 2 "" ""))
7413    (clobber (reg:SI LR_REGNUM))]
7414   "TARGET_THUMB && arm_arch5"
7415   "blx\\t%0"
7416   [(set_attr "length" "2")
7417    (set_attr "type" "call")]
7418 )
7419
7420 (define_insn "*call_reg_thumb"
7421   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7422          (match_operand 1 "" ""))
7423    (use (match_operand 2 "" ""))
7424    (clobber (reg:SI LR_REGNUM))]
7425   "TARGET_THUMB && !arm_arch5"
7426   "*
7427   {
7428     if (TARGET_CALLER_INTERWORKING)
7429       return \"bl\\t%__interwork_call_via_%0\";
7430     else
7431       return \"bl\\t%__call_via_%0\";
7432   }"
7433   [(set_attr "type" "call")]
7434 )
7435
7436 (define_expand "call_value"
7437   [(parallel [(set (match_operand       0 "" "")
7438                    (call (match_operand 1 "memory_operand" "")
7439                          (match_operand 2 "general_operand" "")))
7440               (use (match_operand 3 "" ""))
7441               (clobber (reg:SI LR_REGNUM))])]
7442   "TARGET_EITHER"
7443   "
7444   {
7445     rtx callee = XEXP (operands[1], 0);
7446     
7447     /* In an untyped call, we can get NULL for operand 2.  */
7448     if (operands[3] == 0)
7449       operands[3] = const0_rtx;
7450       
7451     /* See the comment in define_expand \"call\".  */
7452     if (GET_CODE (callee) != REG
7453         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7454       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7455   }"
7456 )
7457
7458 (define_insn "*call_value_reg_armv5"
7459   [(set (match_operand 0 "" "")
7460         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7461               (match_operand 2 "" "")))
7462    (use (match_operand 3 "" ""))
7463    (clobber (reg:SI LR_REGNUM))]
7464   "TARGET_ARM && arm_arch5"
7465   "blx%?\\t%1"
7466   [(set_attr "type" "call")]
7467 )
7468
7469 (define_insn "*call_value_reg_arm"
7470   [(set (match_operand 0 "" "")
7471         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7472               (match_operand 2 "" "")))
7473    (use (match_operand 3 "" ""))
7474    (clobber (reg:SI LR_REGNUM))]
7475   "TARGET_ARM && !arm_arch5"
7476   "*
7477   return output_call (&operands[1]);
7478   "
7479   [(set_attr "length" "12")
7480    (set_attr "type" "call")]
7481 )
7482
7483 (define_insn "*call_value_mem"
7484   [(set (match_operand 0 "" "")
7485         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7486               (match_operand 2 "" "")))
7487    (use (match_operand 3 "" ""))
7488    (clobber (reg:SI LR_REGNUM))]
7489   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7490   "*
7491   return output_call_mem (&operands[1]);
7492   "
7493   [(set_attr "length" "12")
7494    (set_attr "type" "call")]
7495 )
7496
7497 (define_insn "*call_value_reg_thumb_v5"
7498   [(set (match_operand 0 "" "")
7499         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7500               (match_operand 2 "" "")))
7501    (use (match_operand 3 "" ""))
7502    (clobber (reg:SI LR_REGNUM))]
7503   "TARGET_THUMB && arm_arch5"
7504   "blx\\t%1"
7505   [(set_attr "length" "2")
7506    (set_attr "type" "call")]
7507 )
7508
7509 (define_insn "*call_value_reg_thumb"
7510   [(set (match_operand 0 "" "")
7511         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7512               (match_operand 2 "" "")))
7513    (use (match_operand 3 "" ""))
7514    (clobber (reg:SI LR_REGNUM))]
7515   "TARGET_THUMB && !arm_arch5"
7516   "*
7517   {
7518     if (TARGET_CALLER_INTERWORKING)
7519       return \"bl\\t%__interwork_call_via_%1\";
7520     else
7521       return \"bl\\t%__call_via_%1\";
7522   }"
7523   [(set_attr "type" "call")]
7524 )
7525
7526 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7527 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7528
7529 (define_insn "*call_symbol"
7530   [(call (mem:SI (match_operand:SI 0 "" ""))
7531          (match_operand 1 "" ""))
7532    (use (match_operand 2 "" ""))
7533    (clobber (reg:SI LR_REGNUM))]
7534   "TARGET_ARM
7535    && (GET_CODE (operands[0]) == SYMBOL_REF)
7536    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7537   "*
7538   {
7539     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7540   }"
7541   [(set_attr "type" "call")]
7542 )
7543
7544 (define_insn "*call_value_symbol"
7545   [(set (match_operand 0 "s_register_operand" "")
7546         (call (mem:SI (match_operand:SI 1 "" ""))
7547         (match_operand:SI 2 "" "")))
7548    (use (match_operand 3 "" ""))
7549    (clobber (reg:SI LR_REGNUM))]
7550   "TARGET_ARM
7551    && (GET_CODE (operands[1]) == SYMBOL_REF)
7552    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7553   "*
7554   {
7555     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7556   }"
7557   [(set_attr "type" "call")]
7558 )
7559
7560 (define_insn "*call_insn"
7561   [(call (mem:SI (match_operand:SI 0 "" ""))
7562          (match_operand:SI 1 "" ""))
7563    (use (match_operand 2 "" ""))
7564    (clobber (reg:SI LR_REGNUM))]
7565   "TARGET_THUMB
7566    && GET_CODE (operands[0]) == SYMBOL_REF
7567    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7568   "bl\\t%a0"
7569   [(set_attr "length" "4")
7570    (set_attr "type" "call")]
7571 )
7572
7573 (define_insn "*call_value_insn"
7574   [(set (match_operand 0 "register_operand" "")
7575         (call (mem:SI (match_operand 1 "" ""))
7576               (match_operand 2 "" "")))
7577    (use (match_operand 3 "" ""))
7578    (clobber (reg:SI LR_REGNUM))]
7579   "TARGET_THUMB
7580    && GET_CODE (operands[1]) == SYMBOL_REF
7581    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7582   "bl\\t%a1"
7583   [(set_attr "length" "4")
7584    (set_attr "type" "call")]
7585 )
7586
7587 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7588 (define_expand "sibcall"
7589   [(parallel [(call (match_operand 0 "memory_operand" "")
7590                     (match_operand 1 "general_operand" ""))
7591               (return)
7592               (use (match_operand 2 "" ""))])]
7593   "TARGET_ARM"
7594   "
7595   {
7596     if (operands[2] == NULL_RTX)
7597       operands[2] = const0_rtx;
7598   }"
7599 )
7600
7601 (define_expand "sibcall_value"
7602   [(parallel [(set (match_operand 0 "register_operand" "")
7603                    (call (match_operand 1 "memory_operand" "")
7604                          (match_operand 2 "general_operand" "")))
7605               (return)
7606               (use (match_operand 3 "" ""))])]
7607   "TARGET_ARM"
7608   "
7609   {
7610     if (operands[3] == NULL_RTX)
7611       operands[3] = const0_rtx;
7612   }"
7613 )
7614
7615 (define_insn "*sibcall_insn"
7616  [(call (mem:SI (match_operand:SI 0 "" "X"))
7617         (match_operand 1 "" ""))
7618   (return)
7619   (use (match_operand 2 "" ""))]
7620   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7621   "*
7622   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7623   "
7624   [(set_attr "type" "call")]
7625 )
7626
7627 (define_insn "*sibcall_value_insn"
7628  [(set (match_operand 0 "s_register_operand" "")
7629        (call (mem:SI (match_operand:SI 1 "" "X"))
7630              (match_operand 2 "" "")))
7631   (return)
7632   (use (match_operand 3 "" ""))]
7633   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7634   "*
7635   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7636   "
7637   [(set_attr "type" "call")]
7638 )
7639
7640 ;; Often the return insn will be the same as loading from memory, so set attr
7641 (define_insn "return"
7642   [(return)]
7643   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7644   "*
7645   {
7646     if (arm_ccfsm_state == 2)
7647       {
7648         arm_ccfsm_state += 2;
7649         return \"\";
7650       }
7651     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7652   }"
7653   [(set_attr "type" "load1")
7654    (set_attr "length" "12")
7655    (set_attr "predicable" "yes")]
7656 )
7657
7658 (define_insn "*cond_return"
7659   [(set (pc)
7660         (if_then_else (match_operator 0 "arm_comparison_operator"
7661                        [(match_operand 1 "cc_register" "") (const_int 0)])
7662                       (return)
7663                       (pc)))]
7664   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7665   "*
7666   {
7667     if (arm_ccfsm_state == 2)
7668       {
7669         arm_ccfsm_state += 2;
7670         return \"\";
7671       }
7672     return output_return_instruction (operands[0], TRUE, FALSE);
7673   }"
7674   [(set_attr "conds" "use")
7675    (set_attr "length" "12")
7676    (set_attr "type" "load1")]
7677 )
7678
7679 (define_insn "*cond_return_inverted"
7680   [(set (pc)
7681         (if_then_else (match_operator 0 "arm_comparison_operator"
7682                        [(match_operand 1 "cc_register" "") (const_int 0)])
7683                       (pc)
7684                       (return)))]
7685   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7686   "*
7687   {
7688     if (arm_ccfsm_state == 2)
7689       {
7690         arm_ccfsm_state += 2;
7691         return \"\";
7692       }
7693     return output_return_instruction (operands[0], TRUE, TRUE);
7694   }"
7695   [(set_attr "conds" "use")
7696    (set_attr "length" "12")
7697    (set_attr "type" "load1")]
7698 )
7699
7700 ;; Generate a sequence of instructions to determine if the processor is
7701 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7702 ;; mask.
7703
7704 (define_expand "return_addr_mask"
7705   [(set (match_dup 1)
7706       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7707                        (const_int 0)))
7708    (set (match_operand:SI 0 "s_register_operand" "")
7709       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7710                        (const_int -1)
7711                        (const_int 67108860)))] ; 0x03fffffc
7712   "TARGET_ARM"
7713   "
7714   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7715   ")
7716
7717 (define_insn "*check_arch2"
7718   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7719       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7720                        (const_int 0)))]
7721   "TARGET_ARM"
7722   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7723   [(set_attr "length" "8")
7724    (set_attr "conds" "set")]
7725 )
7726
7727 ;; Call subroutine returning any type.
7728
7729 (define_expand "untyped_call"
7730   [(parallel [(call (match_operand 0 "" "")
7731                     (const_int 0))
7732               (match_operand 1 "" "")
7733               (match_operand 2 "" "")])]
7734   "TARGET_ARM"
7735   "
7736   {
7737     int i;
7738
7739     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7740
7741     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7742       {
7743         rtx set = XVECEXP (operands[2], 0, i);
7744
7745         emit_move_insn (SET_DEST (set), SET_SRC (set));
7746       }
7747
7748     /* The optimizer does not know that the call sets the function value
7749        registers we stored in the result block.  We avoid problems by
7750        claiming that all hard registers are used and clobbered at this
7751        point.  */
7752     emit_insn (gen_blockage ());
7753
7754     DONE;
7755   }"
7756 )
7757
7758 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7759 ;; all of memory.  This blocks insns from being moved across this point.
7760
7761 (define_insn "blockage"
7762   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7763   "TARGET_EITHER"
7764   ""
7765   [(set_attr "length" "0")
7766    (set_attr "type" "block")]
7767 )
7768
7769 (define_expand "casesi"
7770   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7771    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7772    (match_operand:SI 2 "const_int_operand" "")  ; total range
7773    (match_operand:SI 3 "" "")                   ; table label
7774    (match_operand:SI 4 "" "")]                  ; Out of range label
7775   "TARGET_ARM"
7776   "
7777   {
7778     rtx reg;
7779     if (operands[1] != const0_rtx)
7780       {
7781         reg = gen_reg_rtx (SImode);
7782
7783         emit_insn (gen_addsi3 (reg, operands[0],
7784                                GEN_INT (-INTVAL (operands[1]))));
7785         operands[0] = reg;
7786       }
7787
7788     if (!const_ok_for_arm (INTVAL (operands[2])))
7789       operands[2] = force_reg (SImode, operands[2]);
7790
7791     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7792                                          operands[4]));
7793     DONE;
7794   }"
7795 )
7796
7797 ;; The USE in this pattern is needed to tell flow analysis that this is
7798 ;; a CASESI insn.  It has no other purpose.
7799 (define_insn "casesi_internal"
7800   [(parallel [(set (pc)
7801                (if_then_else
7802                 (leu (match_operand:SI 0 "s_register_operand" "r")
7803                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7804                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7805                                  (label_ref (match_operand 2 "" ""))))
7806                 (label_ref (match_operand 3 "" ""))))
7807               (clobber (reg:CC CC_REGNUM))
7808               (use (label_ref (match_dup 2)))])]
7809   "TARGET_ARM"
7810   "*
7811     if (flag_pic)
7812       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7813     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7814   "
7815   [(set_attr "conds" "clob")
7816    (set_attr "length" "12")]
7817 )
7818
7819 (define_expand "indirect_jump"
7820   [(set (pc)
7821         (match_operand:SI 0 "s_register_operand" ""))]
7822   "TARGET_EITHER"
7823   ""
7824 )
7825
7826 ;; NB Never uses BX.
7827 (define_insn "*arm_indirect_jump"
7828   [(set (pc)
7829         (match_operand:SI 0 "s_register_operand" "r"))]
7830   "TARGET_ARM"
7831   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7832   [(set_attr "predicable" "yes")]
7833 )
7834
7835 (define_insn "*load_indirect_jump"
7836   [(set (pc)
7837         (match_operand:SI 0 "memory_operand" "m"))]
7838   "TARGET_ARM"
7839   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7840   [(set_attr "type" "load1")
7841    (set_attr "pool_range" "4096")
7842    (set_attr "neg_pool_range" "4084")
7843    (set_attr "predicable" "yes")]
7844 )
7845
7846 ;; NB Never uses BX.
7847 (define_insn "*thumb_indirect_jump"
7848   [(set (pc)
7849         (match_operand:SI 0 "register_operand" "l*r"))]
7850   "TARGET_THUMB"
7851   "mov\\tpc, %0"
7852   [(set_attr "conds" "clob")
7853    (set_attr "length" "2")]
7854 )
7855
7856 \f
7857 ;; Misc insns
7858
7859 (define_insn "nop"
7860   [(const_int 0)]
7861   "TARGET_EITHER"
7862   "*
7863   if (TARGET_ARM)
7864     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7865   return  \"mov\\tr8, r8\";
7866   "
7867   [(set (attr "length")
7868         (if_then_else (eq_attr "is_thumb" "yes")
7869                       (const_int 2)
7870                       (const_int 4)))]
7871 )
7872
7873 \f
7874 ;; Patterns to allow combination of arithmetic, cond code and shifts
7875
7876 (define_insn "*arith_shiftsi"
7877   [(set (match_operand:SI 0 "s_register_operand" "=r")
7878         (match_operator:SI 1 "shiftable_operator"
7879           [(match_operator:SI 3 "shift_operator"
7880              [(match_operand:SI 4 "s_register_operand" "r")
7881               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7882            (match_operand:SI 2 "s_register_operand" "r")]))]
7883   "TARGET_ARM"
7884   "%i1%?\\t%0, %2, %4%S3"
7885   [(set_attr "predicable" "yes")
7886    (set_attr "shift" "4")
7887    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7888                       (const_string "alu_shift")
7889                       (const_string "alu_shift_reg")))]
7890 )
7891
7892 (define_split
7893   [(set (match_operand:SI 0 "s_register_operand" "")
7894         (match_operator:SI 1 "shiftable_operator"
7895          [(match_operator:SI 2 "shiftable_operator"
7896            [(match_operator:SI 3 "shift_operator"
7897              [(match_operand:SI 4 "s_register_operand" "")
7898               (match_operand:SI 5 "reg_or_int_operand" "")])
7899             (match_operand:SI 6 "s_register_operand" "")])
7900           (match_operand:SI 7 "arm_rhs_operand" "")]))
7901    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7902   "TARGET_ARM"
7903   [(set (match_dup 8)
7904         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7905                          (match_dup 6)]))
7906    (set (match_dup 0)
7907         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7908   "")
7909
7910 (define_insn "*arith_shiftsi_compare0"
7911   [(set (reg:CC_NOOV CC_REGNUM)
7912         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7913                           [(match_operator:SI 3 "shift_operator"
7914                             [(match_operand:SI 4 "s_register_operand" "r")
7915                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7916                            (match_operand:SI 2 "s_register_operand" "r")])
7917                          (const_int 0)))
7918    (set (match_operand:SI 0 "s_register_operand" "=r")
7919         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7920                          (match_dup 2)]))]
7921   "TARGET_ARM"
7922   "%i1%?s\\t%0, %2, %4%S3"
7923   [(set_attr "conds" "set")
7924    (set_attr "shift" "4")
7925    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7926                       (const_string "alu_shift")
7927                       (const_string "alu_shift_reg")))]
7928 )
7929
7930 (define_insn "*arith_shiftsi_compare0_scratch"
7931   [(set (reg:CC_NOOV CC_REGNUM)
7932         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7933                           [(match_operator:SI 3 "shift_operator"
7934                             [(match_operand:SI 4 "s_register_operand" "r")
7935                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7936                            (match_operand:SI 2 "s_register_operand" "r")])
7937                          (const_int 0)))
7938    (clobber (match_scratch:SI 0 "=r"))]
7939   "TARGET_ARM"
7940   "%i1%?s\\t%0, %2, %4%S3"
7941   [(set_attr "conds" "set")
7942    (set_attr "shift" "4")
7943    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7944                       (const_string "alu_shift")
7945                       (const_string "alu_shift_reg")))]
7946 )
7947
7948 (define_insn "*sub_shiftsi"
7949   [(set (match_operand:SI 0 "s_register_operand" "=r")
7950         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7951                   (match_operator:SI 2 "shift_operator"
7952                    [(match_operand:SI 3 "s_register_operand" "r")
7953                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7954   "TARGET_ARM"
7955   "sub%?\\t%0, %1, %3%S2"
7956   [(set_attr "predicable" "yes")
7957    (set_attr "shift" "3")
7958    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7959                       (const_string "alu_shift")
7960                       (const_string "alu_shift_reg")))]
7961 )
7962
7963 (define_insn "*sub_shiftsi_compare0"
7964   [(set (reg:CC_NOOV CC_REGNUM)
7965         (compare:CC_NOOV
7966          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7967                    (match_operator:SI 2 "shift_operator"
7968                     [(match_operand:SI 3 "s_register_operand" "r")
7969                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7970          (const_int 0)))
7971    (set (match_operand:SI 0 "s_register_operand" "=r")
7972         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7973                                                  (match_dup 4)])))]
7974   "TARGET_ARM"
7975   "sub%?s\\t%0, %1, %3%S2"
7976   [(set_attr "conds" "set")
7977    (set_attr "shift" "3")
7978    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7979                       (const_string "alu_shift")
7980                       (const_string "alu_shift_reg")))]
7981 )
7982
7983 (define_insn "*sub_shiftsi_compare0_scratch"
7984   [(set (reg:CC_NOOV CC_REGNUM)
7985         (compare:CC_NOOV
7986          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7987                    (match_operator:SI 2 "shift_operator"
7988                     [(match_operand:SI 3 "s_register_operand" "r")
7989                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7990          (const_int 0)))
7991    (clobber (match_scratch:SI 0 "=r"))]
7992   "TARGET_ARM"
7993   "sub%?s\\t%0, %1, %3%S2"
7994   [(set_attr "conds" "set")
7995    (set_attr "shift" "3")
7996    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7997                       (const_string "alu_shift")
7998                       (const_string "alu_shift_reg")))]
7999 )
8000
8001 \f
8002
8003 (define_insn "*and_scc"
8004   [(set (match_operand:SI 0 "s_register_operand" "=r")
8005         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8006                  [(match_operand 3 "cc_register" "") (const_int 0)])
8007                 (match_operand:SI 2 "s_register_operand" "r")))]
8008   "TARGET_ARM"
8009   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8010   [(set_attr "conds" "use")
8011    (set_attr "length" "8")]
8012 )
8013
8014 (define_insn "*ior_scc"
8015   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8016         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8017                  [(match_operand 3 "cc_register" "") (const_int 0)])
8018                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8019   "TARGET_ARM"
8020   "@
8021    orr%d2\\t%0, %1, #1
8022    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8023   [(set_attr "conds" "use")
8024    (set_attr "length" "4,8")]
8025 )
8026
8027 (define_insn "*compare_scc"
8028   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8029         (match_operator:SI 1 "arm_comparison_operator"
8030          [(match_operand:SI 2 "s_register_operand" "r,r")
8031           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8032    (clobber (reg:CC CC_REGNUM))]
8033   "TARGET_ARM"
8034   "*
8035     if (operands[3] == const0_rtx)
8036       {
8037         if (GET_CODE (operands[1]) == LT)
8038           return \"mov\\t%0, %2, lsr #31\";
8039
8040         if (GET_CODE (operands[1]) == GE)
8041           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8042
8043         if (GET_CODE (operands[1]) == EQ)
8044           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8045       }
8046
8047     if (GET_CODE (operands[1]) == NE)
8048       {
8049         if (which_alternative == 1)
8050           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8051         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8052       }
8053     if (which_alternative == 1)
8054       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8055     else
8056       output_asm_insn (\"cmp\\t%2, %3\", operands);
8057     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8058   "
8059   [(set_attr "conds" "clob")
8060    (set_attr "length" "12")]
8061 )
8062
8063 (define_insn "*cond_move"
8064   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8065         (if_then_else:SI (match_operator 3 "equality_operator"
8066                           [(match_operator 4 "arm_comparison_operator"
8067                             [(match_operand 5 "cc_register" "") (const_int 0)])
8068                            (const_int 0)])
8069                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8070                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8071   "TARGET_ARM"
8072   "*
8073     if (GET_CODE (operands[3]) == NE)
8074       {
8075         if (which_alternative != 1)
8076           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8077         if (which_alternative != 0)
8078           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8079         return \"\";
8080       }
8081     if (which_alternative != 0)
8082       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8083     if (which_alternative != 1)
8084       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8085     return \"\";
8086   "
8087   [(set_attr "conds" "use")
8088    (set_attr "length" "4,4,8")]
8089 )
8090
8091 (define_insn "*cond_arith"
8092   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8093         (match_operator:SI 5 "shiftable_operator" 
8094          [(match_operator:SI 4 "arm_comparison_operator"
8095            [(match_operand:SI 2 "s_register_operand" "r,r")
8096             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8097           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8098    (clobber (reg:CC CC_REGNUM))]
8099   "TARGET_ARM"
8100   "*
8101     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8102       return \"%i5\\t%0, %1, %2, lsr #31\";
8103
8104     output_asm_insn (\"cmp\\t%2, %3\", operands);
8105     if (GET_CODE (operands[5]) == AND)
8106       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8107     else if (GET_CODE (operands[5]) == MINUS)
8108       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8109     else if (which_alternative != 0)
8110       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8111     return \"%i5%d4\\t%0, %1, #1\";
8112   "
8113   [(set_attr "conds" "clob")
8114    (set_attr "length" "12")]
8115 )
8116
8117 (define_insn "*cond_sub"
8118   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8119         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8120                   (match_operator:SI 4 "arm_comparison_operator"
8121                    [(match_operand:SI 2 "s_register_operand" "r,r")
8122                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8123    (clobber (reg:CC CC_REGNUM))]
8124   "TARGET_ARM"
8125   "*
8126     output_asm_insn (\"cmp\\t%2, %3\", operands);
8127     if (which_alternative != 0)
8128       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8129     return \"sub%d4\\t%0, %1, #1\";
8130   "
8131   [(set_attr "conds" "clob")
8132    (set_attr "length" "8,12")]
8133 )
8134
8135 (define_insn "*cmp_ite0"
8136   [(set (match_operand 6 "dominant_cc_register" "")
8137         (compare
8138          (if_then_else:SI
8139           (match_operator 4 "arm_comparison_operator"
8140            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8141             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8142           (match_operator:SI 5 "arm_comparison_operator"
8143            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8144             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8145           (const_int 0))
8146          (const_int 0)))]
8147   "TARGET_ARM"
8148   "*
8149   {
8150     static const char * const opcodes[4][2] =
8151     {
8152       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8153        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8154       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8155        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8156       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8157        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8158       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8159        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8160     };
8161     int swap =
8162       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8163
8164     return opcodes[which_alternative][swap];
8165   }"
8166   [(set_attr "conds" "set")
8167    (set_attr "length" "8")]
8168 )
8169
8170 (define_insn "*cmp_ite1"
8171   [(set (match_operand 6 "dominant_cc_register" "")
8172         (compare
8173          (if_then_else:SI
8174           (match_operator 4 "arm_comparison_operator"
8175            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8176             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8177           (match_operator:SI 5 "arm_comparison_operator"
8178            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8179             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8180           (const_int 1))
8181          (const_int 0)))]
8182   "TARGET_ARM"
8183   "*
8184   {
8185     static const char * const opcodes[4][2] =
8186     {
8187       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8188        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8189       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8190        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8191       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8192        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8193       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8194        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8195     };
8196     int swap =
8197       comparison_dominates_p (GET_CODE (operands[5]),
8198                               reverse_condition (GET_CODE (operands[4])));
8199
8200     return opcodes[which_alternative][swap];
8201   }"
8202   [(set_attr "conds" "set")
8203    (set_attr "length" "8")]
8204 )
8205
8206 (define_insn "*cmp_and"
8207   [(set (match_operand 6 "dominant_cc_register" "")
8208         (compare
8209          (and:SI
8210           (match_operator 4 "arm_comparison_operator"
8211            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8212             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8213           (match_operator:SI 5 "arm_comparison_operator"
8214            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8215             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8216          (const_int 0)))]
8217   "TARGET_ARM"
8218   "*
8219   {
8220     static const char *const opcodes[4][2] =
8221     {
8222       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8223        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8224       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8225        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8226       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8227        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8228       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8229        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8230     };
8231     int swap =
8232       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8233
8234     return opcodes[which_alternative][swap];
8235   }"
8236   [(set_attr "conds" "set")
8237    (set_attr "predicable" "no")
8238    (set_attr "length" "8")]
8239 )
8240
8241 (define_insn "*cmp_ior"
8242   [(set (match_operand 6 "dominant_cc_register" "")
8243         (compare
8244          (ior:SI
8245           (match_operator 4 "arm_comparison_operator"
8246            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8247             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8248           (match_operator:SI 5 "arm_comparison_operator"
8249            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8250             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8251          (const_int 0)))]
8252   "TARGET_ARM"
8253   "*
8254 {
8255   static const char *const opcodes[4][2] =
8256   {
8257     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8258      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8259     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8260      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8261     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8262      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8263     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8264      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8265   };
8266   int swap =
8267     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8268
8269   return opcodes[which_alternative][swap];
8270 }
8271 "
8272   [(set_attr "conds" "set")
8273    (set_attr "length" "8")]
8274 )
8275
8276 (define_insn_and_split "*ior_scc_scc"
8277   [(set (match_operand:SI 0 "s_register_operand" "=r")
8278         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8279                  [(match_operand:SI 1 "s_register_operand" "r")
8280                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8281                 (match_operator:SI 6 "arm_comparison_operator"
8282                  [(match_operand:SI 4 "s_register_operand" "r")
8283                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8284    (clobber (reg:CC CC_REGNUM))]
8285   "TARGET_ARM
8286    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8287        != CCmode)"
8288   "#"
8289   "TARGET_ARM && reload_completed"
8290   [(set (match_dup 7)
8291         (compare
8292          (ior:SI
8293           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8294           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8295          (const_int 0)))
8296    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8297   "operands[7]
8298      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8299                                                   DOM_CC_X_OR_Y),
8300                     CC_REGNUM);"
8301   [(set_attr "conds" "clob")
8302    (set_attr "length" "16")])
8303
8304 ; If the above pattern is followed by a CMP insn, then the compare is 
8305 ; redundant, since we can rework the conditional instruction that follows.
8306 (define_insn_and_split "*ior_scc_scc_cmp"
8307   [(set (match_operand 0 "dominant_cc_register" "")
8308         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8309                           [(match_operand:SI 1 "s_register_operand" "r")
8310                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8311                          (match_operator:SI 6 "arm_comparison_operator"
8312                           [(match_operand:SI 4 "s_register_operand" "r")
8313                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8314                  (const_int 0)))
8315    (set (match_operand:SI 7 "s_register_operand" "=r")
8316         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8317                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8318   "TARGET_ARM"
8319   "#"
8320   "TARGET_ARM && reload_completed"
8321   [(set (match_dup 0)
8322         (compare
8323          (ior:SI
8324           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8325           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8326          (const_int 0)))
8327    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8328   ""
8329   [(set_attr "conds" "set")
8330    (set_attr "length" "16")])
8331
8332 (define_insn_and_split "*and_scc_scc"
8333   [(set (match_operand:SI 0 "s_register_operand" "=r")
8334         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8335                  [(match_operand:SI 1 "s_register_operand" "r")
8336                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8337                 (match_operator:SI 6 "arm_comparison_operator"
8338                  [(match_operand:SI 4 "s_register_operand" "r")
8339                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8340    (clobber (reg:CC CC_REGNUM))]
8341   "TARGET_ARM
8342    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8343        != CCmode)"
8344   "#"
8345   "TARGET_ARM && reload_completed
8346    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8347        != CCmode)"
8348   [(set (match_dup 7)
8349         (compare
8350          (and:SI
8351           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8352           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8353          (const_int 0)))
8354    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8355   "operands[7]
8356      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8357                                                   DOM_CC_X_AND_Y),
8358                     CC_REGNUM);"
8359   [(set_attr "conds" "clob")
8360    (set_attr "length" "16")])
8361
8362 ; If the above pattern is followed by a CMP insn, then the compare is 
8363 ; redundant, since we can rework the conditional instruction that follows.
8364 (define_insn_and_split "*and_scc_scc_cmp"
8365   [(set (match_operand 0 "dominant_cc_register" "")
8366         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8367                           [(match_operand:SI 1 "s_register_operand" "r")
8368                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8369                          (match_operator:SI 6 "arm_comparison_operator"
8370                           [(match_operand:SI 4 "s_register_operand" "r")
8371                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8372                  (const_int 0)))
8373    (set (match_operand:SI 7 "s_register_operand" "=r")
8374         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8375                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8376   "TARGET_ARM"
8377   "#"
8378   "TARGET_ARM && reload_completed"
8379   [(set (match_dup 0)
8380         (compare
8381          (and:SI
8382           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8383           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8384          (const_int 0)))
8385    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8386   ""
8387   [(set_attr "conds" "set")
8388    (set_attr "length" "16")])
8389
8390 ;; If there is no dominance in the comparison, then we can still save an
8391 ;; instruction in the AND case, since we can know that the second compare
8392 ;; need only zero the value if false (if true, then the value is already
8393 ;; correct).
8394 (define_insn_and_split "*and_scc_scc_nodom"
8395   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8396         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8397                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8398                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8399                 (match_operator:SI 6 "arm_comparison_operator"
8400                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8401                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8402    (clobber (reg:CC CC_REGNUM))]
8403   "TARGET_ARM
8404    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8405        == CCmode)"
8406   "#"
8407   "TARGET_ARM && reload_completed"
8408   [(parallel [(set (match_dup 0)
8409                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8410               (clobber (reg:CC CC_REGNUM))])
8411    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8412    (set (match_dup 0)
8413         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8414                          (match_dup 0)
8415                          (const_int 0)))]
8416   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8417                                               operands[4], operands[5]),
8418                               CC_REGNUM);
8419    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8420                                   operands[5]);"
8421   [(set_attr "conds" "clob")
8422    (set_attr "length" "20")])
8423
8424 (define_split
8425   [(set (reg:CC_NOOV CC_REGNUM)
8426         (compare:CC_NOOV (ior:SI
8427                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8428                                   (const_int 1))
8429                           (match_operator:SI 1 "comparison_operator"
8430                            [(match_operand:SI 2 "s_register_operand" "")
8431                             (match_operand:SI 3 "arm_add_operand" "")]))
8432                          (const_int 0)))
8433    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8434   "TARGET_ARM"
8435   [(set (match_dup 4)
8436         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8437                 (match_dup 0)))
8438    (set (reg:CC_NOOV CC_REGNUM)
8439         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8440                          (const_int 0)))]
8441   "")
8442
8443 (define_split
8444   [(set (reg:CC_NOOV CC_REGNUM)
8445         (compare:CC_NOOV (ior:SI
8446                           (match_operator:SI 1 "comparison_operator"
8447                            [(match_operand:SI 2 "s_register_operand" "")
8448                             (match_operand:SI 3 "arm_add_operand" "")])
8449                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8450                                   (const_int 1)))
8451                          (const_int 0)))
8452    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8453   "TARGET_ARM"
8454   [(set (match_dup 4)
8455         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8456                 (match_dup 0)))
8457    (set (reg:CC_NOOV CC_REGNUM)
8458         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8459                          (const_int 0)))]
8460   "")
8461
8462 (define_insn "*negscc"
8463   [(set (match_operand:SI 0 "s_register_operand" "=r")
8464         (neg:SI (match_operator 3 "arm_comparison_operator"
8465                  [(match_operand:SI 1 "s_register_operand" "r")
8466                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8467    (clobber (reg:CC CC_REGNUM))]
8468   "TARGET_ARM"
8469   "*
8470   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8471     return \"mov\\t%0, %1, asr #31\";
8472
8473   if (GET_CODE (operands[3]) == NE)
8474     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8475
8476   if (GET_CODE (operands[3]) == GT)
8477     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8478
8479   output_asm_insn (\"cmp\\t%1, %2\", operands);
8480   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8481   return \"mvn%d3\\t%0, #0\";
8482   "
8483   [(set_attr "conds" "clob")
8484    (set_attr "length" "12")]
8485 )
8486
8487 (define_insn "movcond"
8488   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8489         (if_then_else:SI
8490          (match_operator 5 "arm_comparison_operator"
8491           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8492            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8493          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8494          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8495    (clobber (reg:CC CC_REGNUM))]
8496   "TARGET_ARM"
8497   "*
8498   if (GET_CODE (operands[5]) == LT
8499       && (operands[4] == const0_rtx))
8500     {
8501       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8502         {
8503           if (operands[2] == const0_rtx)
8504             return \"and\\t%0, %1, %3, asr #31\";
8505           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8506         }
8507       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8508         {
8509           if (operands[1] == const0_rtx)
8510             return \"bic\\t%0, %2, %3, asr #31\";
8511           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8512         }
8513       /* The only case that falls through to here is when both ops 1 & 2
8514          are constants.  */
8515     }
8516
8517   if (GET_CODE (operands[5]) == GE
8518       && (operands[4] == const0_rtx))
8519     {
8520       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8521         {
8522           if (operands[2] == const0_rtx)
8523             return \"bic\\t%0, %1, %3, asr #31\";
8524           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8525         }
8526       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8527         {
8528           if (operands[1] == const0_rtx)
8529             return \"and\\t%0, %2, %3, asr #31\";
8530           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8531         }
8532       /* The only case that falls through to here is when both ops 1 & 2
8533          are constants.  */
8534     }
8535   if (GET_CODE (operands[4]) == CONST_INT
8536       && !const_ok_for_arm (INTVAL (operands[4])))
8537     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8538   else
8539     output_asm_insn (\"cmp\\t%3, %4\", operands);
8540   if (which_alternative != 0)
8541     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8542   if (which_alternative != 1)
8543     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8544   return \"\";
8545   "
8546   [(set_attr "conds" "clob")
8547    (set_attr "length" "8,8,12")]
8548 )
8549
8550 (define_insn "*ifcompare_plus_move"
8551   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8552         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8553                           [(match_operand:SI 4 "s_register_operand" "r,r")
8554                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8555                          (plus:SI
8556                           (match_operand:SI 2 "s_register_operand" "r,r")
8557                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8558                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8559    (clobber (reg:CC CC_REGNUM))]
8560   "TARGET_ARM"
8561   "#"
8562   [(set_attr "conds" "clob")
8563    (set_attr "length" "8,12")]
8564 )
8565
8566 (define_insn "*if_plus_move"
8567   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8568         (if_then_else:SI
8569          (match_operator 4 "arm_comparison_operator"
8570           [(match_operand 5 "cc_register" "") (const_int 0)])
8571          (plus:SI
8572           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8573           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8574          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8575   "TARGET_ARM"
8576   "@
8577    add%d4\\t%0, %2, %3
8578    sub%d4\\t%0, %2, #%n3
8579    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8580    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8581   [(set_attr "conds" "use")
8582    (set_attr "length" "4,4,8,8")
8583    (set_attr "type" "*,*,*,*")]
8584 )
8585
8586 (define_insn "*ifcompare_move_plus"
8587   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8588         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8589                           [(match_operand:SI 4 "s_register_operand" "r,r")
8590                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8591                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8592                          (plus:SI
8593                           (match_operand:SI 2 "s_register_operand" "r,r")
8594                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8595    (clobber (reg:CC CC_REGNUM))]
8596   "TARGET_ARM"
8597   "#"
8598   [(set_attr "conds" "clob")
8599    (set_attr "length" "8,12")]
8600 )
8601
8602 (define_insn "*if_move_plus"
8603   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8604         (if_then_else:SI
8605          (match_operator 4 "arm_comparison_operator"
8606           [(match_operand 5 "cc_register" "") (const_int 0)])
8607          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8608          (plus:SI
8609           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8610           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8611   "TARGET_ARM"
8612   "@
8613    add%D4\\t%0, %2, %3
8614    sub%D4\\t%0, %2, #%n3
8615    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8616    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8617   [(set_attr "conds" "use")
8618    (set_attr "length" "4,4,8,8")
8619    (set_attr "type" "*,*,*,*")]
8620 )
8621
8622 (define_insn "*ifcompare_arith_arith"
8623   [(set (match_operand:SI 0 "s_register_operand" "=r")
8624         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8625                           [(match_operand:SI 5 "s_register_operand" "r")
8626                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8627                          (match_operator:SI 8 "shiftable_operator"
8628                           [(match_operand:SI 1 "s_register_operand" "r")
8629                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8630                          (match_operator:SI 7 "shiftable_operator"
8631                           [(match_operand:SI 3 "s_register_operand" "r")
8632                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8633    (clobber (reg:CC CC_REGNUM))]
8634   "TARGET_ARM"
8635   "#"
8636   [(set_attr "conds" "clob")
8637    (set_attr "length" "12")]
8638 )
8639
8640 (define_insn "*if_arith_arith"
8641   [(set (match_operand:SI 0 "s_register_operand" "=r")
8642         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8643                           [(match_operand 8 "cc_register" "") (const_int 0)])
8644                          (match_operator:SI 6 "shiftable_operator"
8645                           [(match_operand:SI 1 "s_register_operand" "r")
8646                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8647                          (match_operator:SI 7 "shiftable_operator"
8648                           [(match_operand:SI 3 "s_register_operand" "r")
8649                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8650   "TARGET_ARM"
8651   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8652   [(set_attr "conds" "use")
8653    (set_attr "length" "8")]
8654 )
8655
8656 (define_insn "*ifcompare_arith_move"
8657   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8658         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8659                           [(match_operand:SI 2 "s_register_operand" "r,r")
8660                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8661                          (match_operator:SI 7 "shiftable_operator"
8662                           [(match_operand:SI 4 "s_register_operand" "r,r")
8663                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8664                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8665    (clobber (reg:CC CC_REGNUM))]
8666   "TARGET_ARM"
8667   "*
8668   /* If we have an operation where (op x 0) is the identity operation and
8669      the conditional operator is LT or GE and we are comparing against zero and
8670      everything is in registers then we can do this in two instructions.  */
8671   if (operands[3] == const0_rtx
8672       && GET_CODE (operands[7]) != AND
8673       && GET_CODE (operands[5]) == REG
8674       && GET_CODE (operands[1]) == REG 
8675       && REGNO (operands[1]) == REGNO (operands[4])
8676       && REGNO (operands[4]) != REGNO (operands[0]))
8677     {
8678       if (GET_CODE (operands[6]) == LT)
8679         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8680       else if (GET_CODE (operands[6]) == GE)
8681         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8682     }
8683   if (GET_CODE (operands[3]) == CONST_INT
8684       && !const_ok_for_arm (INTVAL (operands[3])))
8685     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8686   else
8687     output_asm_insn (\"cmp\\t%2, %3\", operands);
8688   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8689   if (which_alternative != 0)
8690     return \"mov%D6\\t%0, %1\";
8691   return \"\";
8692   "
8693   [(set_attr "conds" "clob")
8694    (set_attr "length" "8,12")]
8695 )
8696
8697 (define_insn "*if_arith_move"
8698   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8699         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8700                           [(match_operand 6 "cc_register" "") (const_int 0)])
8701                          (match_operator:SI 5 "shiftable_operator"
8702                           [(match_operand:SI 2 "s_register_operand" "r,r")
8703                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8704                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8705   "TARGET_ARM"
8706   "@
8707    %I5%d4\\t%0, %2, %3
8708    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8709   [(set_attr "conds" "use")
8710    (set_attr "length" "4,8")
8711    (set_attr "type" "*,*")]
8712 )
8713
8714 (define_insn "*ifcompare_move_arith"
8715   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8716         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8717                           [(match_operand:SI 4 "s_register_operand" "r,r")
8718                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8719                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8720                          (match_operator:SI 7 "shiftable_operator"
8721                           [(match_operand:SI 2 "s_register_operand" "r,r")
8722                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8723    (clobber (reg:CC CC_REGNUM))]
8724   "TARGET_ARM"
8725   "*
8726   /* If we have an operation where (op x 0) is the identity operation and
8727      the conditional operator is LT or GE and we are comparing against zero and
8728      everything is in registers then we can do this in two instructions */
8729   if (operands[5] == const0_rtx
8730       && GET_CODE (operands[7]) != AND
8731       && GET_CODE (operands[3]) == REG
8732       && GET_CODE (operands[1]) == REG 
8733       && REGNO (operands[1]) == REGNO (operands[2])
8734       && REGNO (operands[2]) != REGNO (operands[0]))
8735     {
8736       if (GET_CODE (operands[6]) == GE)
8737         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8738       else if (GET_CODE (operands[6]) == LT)
8739         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8740     }
8741
8742   if (GET_CODE (operands[5]) == CONST_INT
8743       && !const_ok_for_arm (INTVAL (operands[5])))
8744     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8745   else
8746     output_asm_insn (\"cmp\\t%4, %5\", operands);
8747
8748   if (which_alternative != 0)
8749     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8750   return \"%I7%D6\\t%0, %2, %3\";
8751   "
8752   [(set_attr "conds" "clob")
8753    (set_attr "length" "8,12")]
8754 )
8755
8756 (define_insn "*if_move_arith"
8757   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8758         (if_then_else:SI
8759          (match_operator 4 "arm_comparison_operator"
8760           [(match_operand 6 "cc_register" "") (const_int 0)])
8761          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8762          (match_operator:SI 5 "shiftable_operator"
8763           [(match_operand:SI 2 "s_register_operand" "r,r")
8764            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8765   "TARGET_ARM"
8766   "@
8767    %I5%D4\\t%0, %2, %3
8768    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8769   [(set_attr "conds" "use")
8770    (set_attr "length" "4,8")
8771    (set_attr "type" "*,*")]
8772 )
8773
8774 (define_insn "*ifcompare_move_not"
8775   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8776         (if_then_else:SI
8777          (match_operator 5 "arm_comparison_operator"
8778           [(match_operand:SI 3 "s_register_operand" "r,r")
8779            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8780          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8781          (not:SI
8782           (match_operand:SI 2 "s_register_operand" "r,r"))))
8783    (clobber (reg:CC CC_REGNUM))]
8784   "TARGET_ARM"
8785   "#"
8786   [(set_attr "conds" "clob")
8787    (set_attr "length" "8,12")]
8788 )
8789
8790 (define_insn "*if_move_not"
8791   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8792         (if_then_else:SI
8793          (match_operator 4 "arm_comparison_operator"
8794           [(match_operand 3 "cc_register" "") (const_int 0)])
8795          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8796          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8797   "TARGET_ARM"
8798   "@
8799    mvn%D4\\t%0, %2
8800    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8801    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8802   [(set_attr "conds" "use")
8803    (set_attr "length" "4,8,8")]
8804 )
8805
8806 (define_insn "*ifcompare_not_move"
8807   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8808         (if_then_else:SI 
8809          (match_operator 5 "arm_comparison_operator"
8810           [(match_operand:SI 3 "s_register_operand" "r,r")
8811            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8812          (not:SI
8813           (match_operand:SI 2 "s_register_operand" "r,r"))
8814          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8815    (clobber (reg:CC CC_REGNUM))]
8816   "TARGET_ARM"
8817   "#"
8818   [(set_attr "conds" "clob")
8819    (set_attr "length" "8,12")]
8820 )
8821
8822 (define_insn "*if_not_move"
8823   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8824         (if_then_else:SI
8825          (match_operator 4 "arm_comparison_operator"
8826           [(match_operand 3 "cc_register" "") (const_int 0)])
8827          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8828          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8829   "TARGET_ARM"
8830   "@
8831    mvn%d4\\t%0, %2
8832    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8833    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8834   [(set_attr "conds" "use")
8835    (set_attr "length" "4,8,8")]
8836 )
8837
8838 (define_insn "*ifcompare_shift_move"
8839   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8840         (if_then_else:SI
8841          (match_operator 6 "arm_comparison_operator"
8842           [(match_operand:SI 4 "s_register_operand" "r,r")
8843            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8844          (match_operator:SI 7 "shift_operator"
8845           [(match_operand:SI 2 "s_register_operand" "r,r")
8846            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8847          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8848    (clobber (reg:CC CC_REGNUM))]
8849   "TARGET_ARM"
8850   "#"
8851   [(set_attr "conds" "clob")
8852    (set_attr "length" "8,12")]
8853 )
8854
8855 (define_insn "*if_shift_move"
8856   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8857         (if_then_else:SI
8858          (match_operator 5 "arm_comparison_operator"
8859           [(match_operand 6 "cc_register" "") (const_int 0)])
8860          (match_operator:SI 4 "shift_operator"
8861           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8862            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8863          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8864   "TARGET_ARM"
8865   "@
8866    mov%d5\\t%0, %2%S4
8867    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8868    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8869   [(set_attr "conds" "use")
8870    (set_attr "shift" "2")
8871    (set_attr "length" "4,8,8")
8872    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8873                       (const_string "alu_shift")
8874                       (const_string "alu_shift_reg")))]
8875 )
8876
8877 (define_insn "*ifcompare_move_shift"
8878   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8879         (if_then_else:SI
8880          (match_operator 6 "arm_comparison_operator"
8881           [(match_operand:SI 4 "s_register_operand" "r,r")
8882            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8883          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8884          (match_operator:SI 7 "shift_operator"
8885           [(match_operand:SI 2 "s_register_operand" "r,r")
8886            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8887    (clobber (reg:CC CC_REGNUM))]
8888   "TARGET_ARM"
8889   "#"
8890   [(set_attr "conds" "clob")
8891    (set_attr "length" "8,12")]
8892 )
8893
8894 (define_insn "*if_move_shift"
8895   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8896         (if_then_else:SI
8897          (match_operator 5 "arm_comparison_operator"
8898           [(match_operand 6 "cc_register" "") (const_int 0)])
8899          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8900          (match_operator:SI 4 "shift_operator"
8901           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8902            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8903   "TARGET_ARM"
8904   "@
8905    mov%D5\\t%0, %2%S4
8906    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8907    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8908   [(set_attr "conds" "use")
8909    (set_attr "shift" "2")
8910    (set_attr "length" "4,8,8")
8911    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8912                       (const_string "alu_shift")
8913                       (const_string "alu_shift_reg")))]
8914 )
8915
8916 (define_insn "*ifcompare_shift_shift"
8917   [(set (match_operand:SI 0 "s_register_operand" "=r")
8918         (if_then_else:SI
8919          (match_operator 7 "arm_comparison_operator"
8920           [(match_operand:SI 5 "s_register_operand" "r")
8921            (match_operand:SI 6 "arm_add_operand" "rIL")])
8922          (match_operator:SI 8 "shift_operator"
8923           [(match_operand:SI 1 "s_register_operand" "r")
8924            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8925          (match_operator:SI 9 "shift_operator"
8926           [(match_operand:SI 3 "s_register_operand" "r")
8927            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8928    (clobber (reg:CC CC_REGNUM))]
8929   "TARGET_ARM"
8930   "#"
8931   [(set_attr "conds" "clob")
8932    (set_attr "length" "12")]
8933 )
8934
8935 (define_insn "*if_shift_shift"
8936   [(set (match_operand:SI 0 "s_register_operand" "=r")
8937         (if_then_else:SI
8938          (match_operator 5 "arm_comparison_operator"
8939           [(match_operand 8 "cc_register" "") (const_int 0)])
8940          (match_operator:SI 6 "shift_operator"
8941           [(match_operand:SI 1 "s_register_operand" "r")
8942            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8943          (match_operator:SI 7 "shift_operator"
8944           [(match_operand:SI 3 "s_register_operand" "r")
8945            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8946   "TARGET_ARM"
8947   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8948   [(set_attr "conds" "use")
8949    (set_attr "shift" "1")
8950    (set_attr "length" "8")
8951    (set (attr "type") (if_then_else
8952                         (and (match_operand 2 "const_int_operand" "")
8953                              (match_operand 4 "const_int_operand" ""))
8954                       (const_string "alu_shift")
8955                       (const_string "alu_shift_reg")))]
8956 )
8957
8958 (define_insn "*ifcompare_not_arith"
8959   [(set (match_operand:SI 0 "s_register_operand" "=r")
8960         (if_then_else:SI
8961          (match_operator 6 "arm_comparison_operator"
8962           [(match_operand:SI 4 "s_register_operand" "r")
8963            (match_operand:SI 5 "arm_add_operand" "rIL")])
8964          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8965          (match_operator:SI 7 "shiftable_operator"
8966           [(match_operand:SI 2 "s_register_operand" "r")
8967            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8968    (clobber (reg:CC CC_REGNUM))]
8969   "TARGET_ARM"
8970   "#"
8971   [(set_attr "conds" "clob")
8972    (set_attr "length" "12")]
8973 )
8974
8975 (define_insn "*if_not_arith"
8976   [(set (match_operand:SI 0 "s_register_operand" "=r")
8977         (if_then_else:SI
8978          (match_operator 5 "arm_comparison_operator"
8979           [(match_operand 4 "cc_register" "") (const_int 0)])
8980          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8981          (match_operator:SI 6 "shiftable_operator"
8982           [(match_operand:SI 2 "s_register_operand" "r")
8983            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8984   "TARGET_ARM"
8985   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8986   [(set_attr "conds" "use")
8987    (set_attr "length" "8")]
8988 )
8989
8990 (define_insn "*ifcompare_arith_not"
8991   [(set (match_operand:SI 0 "s_register_operand" "=r")
8992         (if_then_else:SI
8993          (match_operator 6 "arm_comparison_operator"
8994           [(match_operand:SI 4 "s_register_operand" "r")
8995            (match_operand:SI 5 "arm_add_operand" "rIL")])
8996          (match_operator:SI 7 "shiftable_operator"
8997           [(match_operand:SI 2 "s_register_operand" "r")
8998            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8999          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9000    (clobber (reg:CC CC_REGNUM))]
9001   "TARGET_ARM"
9002   "#"
9003   [(set_attr "conds" "clob")
9004    (set_attr "length" "12")]
9005 )
9006
9007 (define_insn "*if_arith_not"
9008   [(set (match_operand:SI 0 "s_register_operand" "=r")
9009         (if_then_else:SI
9010          (match_operator 5 "arm_comparison_operator"
9011           [(match_operand 4 "cc_register" "") (const_int 0)])
9012          (match_operator:SI 6 "shiftable_operator"
9013           [(match_operand:SI 2 "s_register_operand" "r")
9014            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9015          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9016   "TARGET_ARM"
9017   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9018   [(set_attr "conds" "use")
9019    (set_attr "length" "8")]
9020 )
9021
9022 (define_insn "*ifcompare_neg_move"
9023   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9024         (if_then_else:SI
9025          (match_operator 5 "arm_comparison_operator"
9026           [(match_operand:SI 3 "s_register_operand" "r,r")
9027            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9028          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9029          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9030    (clobber (reg:CC CC_REGNUM))]
9031   "TARGET_ARM"
9032   "#"
9033   [(set_attr "conds" "clob")
9034    (set_attr "length" "8,12")]
9035 )
9036
9037 (define_insn "*if_neg_move"
9038   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9039         (if_then_else:SI
9040          (match_operator 4 "arm_comparison_operator"
9041           [(match_operand 3 "cc_register" "") (const_int 0)])
9042          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9043          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9044   "TARGET_ARM"
9045   "@
9046    rsb%d4\\t%0, %2, #0
9047    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9048    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9049   [(set_attr "conds" "use")
9050    (set_attr "length" "4,8,8")]
9051 )
9052
9053 (define_insn "*ifcompare_move_neg"
9054   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9055         (if_then_else:SI
9056          (match_operator 5 "arm_comparison_operator"
9057           [(match_operand:SI 3 "s_register_operand" "r,r")
9058            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9059          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9060          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9061    (clobber (reg:CC CC_REGNUM))]
9062   "TARGET_ARM"
9063   "#"
9064   [(set_attr "conds" "clob")
9065    (set_attr "length" "8,12")]
9066 )
9067
9068 (define_insn "*if_move_neg"
9069   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9070         (if_then_else:SI
9071          (match_operator 4 "arm_comparison_operator"
9072           [(match_operand 3 "cc_register" "") (const_int 0)])
9073          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9074          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9075   "TARGET_ARM"
9076   "@
9077    rsb%D4\\t%0, %2, #0
9078    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9079    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9080   [(set_attr "conds" "use")
9081    (set_attr "length" "4,8,8")]
9082 )
9083
9084 (define_insn "*arith_adjacentmem"
9085   [(set (match_operand:SI 0 "s_register_operand" "=r")
9086         (match_operator:SI 1 "shiftable_operator"
9087          [(match_operand:SI 2 "memory_operand" "m")
9088           (match_operand:SI 3 "memory_operand" "m")]))
9089    (clobber (match_scratch:SI 4 "=r"))]
9090   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9091   "*
9092   {
9093     rtx ldm[3];
9094     rtx arith[4];
9095     int val1 = 0, val2 = 0;
9096
9097     if (REGNO (operands[0]) > REGNO (operands[4]))
9098       {
9099         ldm[1] = operands[4];
9100         ldm[2] = operands[0];
9101       }
9102     else
9103       {
9104         ldm[1] = operands[0];
9105         ldm[2] = operands[4];
9106       }
9107     if (GET_CODE (XEXP (operands[2], 0)) != REG)
9108       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9109     if (GET_CODE (XEXP (operands[3], 0)) != REG)
9110       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9111     arith[0] = operands[0];
9112     arith[3] = operands[1];
9113     if (val1 < val2)
9114       {
9115         arith[1] = ldm[1];
9116         arith[2] = ldm[2];
9117       }
9118     else
9119       {
9120         arith[1] = ldm[2];
9121         arith[2] = ldm[1];
9122       }
9123    if (val1 && val2)
9124       {
9125         rtx ops[3];
9126         ldm[0] = ops[0] = operands[4];
9127         ops[1] = XEXP (XEXP (operands[2], 0), 0);
9128         ops[2] = XEXP (XEXP (operands[2], 0), 1);
9129         output_add_immediate (ops);
9130         if (val1 < val2)
9131           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9132         else
9133           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9134       }
9135     else if (val1)
9136       {
9137         ldm[0] = XEXP (operands[3], 0);
9138         if (val1 < val2)
9139           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9140         else
9141           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9142       }
9143     else
9144       {
9145         ldm[0] = XEXP (operands[2], 0);
9146         if (val1 < val2)
9147           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9148         else
9149           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9150       }
9151     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9152     return \"\";
9153   }"
9154   [(set_attr "length" "12")
9155    (set_attr "predicable" "yes")
9156    (set_attr "type" "load1")]
9157 )
9158
9159 ;; the arm can support extended pre-inc instructions
9160
9161 ;; In all these cases, we use operands 0 and 1 for the register being
9162 ;; incremented because those are the operands that local-alloc will
9163 ;; tie and these are the pair most likely to be tieable (and the ones
9164 ;; that will benefit the most).
9165
9166 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9167 ;; elimination will cause too many headaches.
9168
9169 (define_insn "*strqi_preinc"
9170   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9171                          (match_operand:SI 2 "index_operand" "rJ")))
9172         (match_operand:QI 3 "s_register_operand" "r"))
9173    (set (match_operand:SI 0 "s_register_operand" "=r")
9174         (plus:SI (match_dup 1) (match_dup 2)))]
9175   "TARGET_ARM
9176    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9177    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9178    && (GET_CODE (operands[2]) != REG
9179        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9180   "str%?b\\t%3, [%0, %2]!"
9181   [(set_attr "type" "store1")
9182    (set_attr "predicable" "yes")]
9183 )
9184
9185 (define_insn "*strqi_predec"
9186   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9187                           (match_operand:SI 2 "s_register_operand" "r")))
9188         (match_operand:QI 3 "s_register_operand" "r"))
9189    (set (match_operand:SI 0 "s_register_operand" "=r")
9190         (minus:SI (match_dup 1) (match_dup 2)))]
9191   "TARGET_ARM
9192    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9193    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9194    && (GET_CODE (operands[2]) != REG
9195        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9196   "str%?b\\t%3, [%0, -%2]!"
9197   [(set_attr "type" "store1")
9198    (set_attr "predicable" "yes")]
9199 )
9200
9201 (define_insn "*loadqi_preinc"
9202   [(set (match_operand:QI 3 "s_register_operand" "=r")
9203         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9204                          (match_operand:SI 2 "index_operand" "rJ"))))
9205    (set (match_operand:SI 0 "s_register_operand" "=r")
9206         (plus:SI (match_dup 1) (match_dup 2)))]
9207   "TARGET_ARM
9208    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9209    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9210    && (GET_CODE (operands[2]) != REG
9211        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9212   "ldr%?b\\t%3, [%0, %2]!"
9213   [(set_attr "type" "load_byte")
9214    (set_attr "predicable" "yes")]
9215 )
9216
9217 (define_insn "*loadqi_predec"
9218   [(set (match_operand:QI 3 "s_register_operand" "=r")
9219         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9220                           (match_operand:SI 2 "s_register_operand" "r"))))
9221    (set (match_operand:SI 0 "s_register_operand" "=r")
9222         (minus:SI (match_dup 1) (match_dup 2)))]
9223   "TARGET_ARM
9224    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9225    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9226    && (GET_CODE (operands[2]) != REG
9227        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9228   "ldr%?b\\t%3, [%0, -%2]!"
9229   [(set_attr "type" "load_byte")
9230    (set_attr "predicable" "yes")]
9231 )
9232
9233 (define_insn "*loadqisi_preinc"
9234   [(set (match_operand:SI 3 "s_register_operand" "=r")
9235         (zero_extend:SI
9236          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9237                           (match_operand:SI 2 "index_operand" "rJ")))))
9238    (set (match_operand:SI 0 "s_register_operand" "=r")
9239         (plus:SI (match_dup 1) (match_dup 2)))]
9240   "TARGET_ARM
9241    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9242    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9243    && (GET_CODE (operands[2]) != REG
9244        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9245   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9246   [(set_attr "type" "load_byte")
9247    (set_attr "predicable" "yes")]
9248 )
9249
9250 (define_insn "*loadqisi_predec"
9251   [(set (match_operand:SI 3 "s_register_operand" "=r")
9252         (zero_extend:SI
9253          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9254                            (match_operand:SI 2 "s_register_operand" "r")))))
9255    (set (match_operand:SI 0 "s_register_operand" "=r")
9256         (minus:SI (match_dup 1) (match_dup 2)))]
9257   "TARGET_ARM
9258    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9259    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9260    && (GET_CODE (operands[2]) != REG
9261        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9262   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9263   [(set_attr "type" "load_byte")
9264    (set_attr "predicable" "yes")]
9265 )
9266
9267 (define_insn "*strsi_preinc"
9268   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9269                          (match_operand:SI 2 "index_operand" "rJ")))
9270         (match_operand:SI 3 "s_register_operand" "r"))
9271    (set (match_operand:SI 0 "s_register_operand" "=r")
9272         (plus:SI (match_dup 1) (match_dup 2)))]
9273   "TARGET_ARM
9274    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9275    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9276    && (GET_CODE (operands[2]) != REG
9277        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9278   "str%?\\t%3, [%0, %2]!"
9279   [(set_attr "type" "store1")
9280    (set_attr "predicable" "yes")]
9281 )
9282
9283 (define_insn "*strsi_predec"
9284   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9285                           (match_operand:SI 2 "s_register_operand" "r")))
9286         (match_operand:SI 3 "s_register_operand" "r"))
9287    (set (match_operand:SI 0 "s_register_operand" "=r")
9288         (minus:SI (match_dup 1) (match_dup 2)))]
9289   "TARGET_ARM
9290    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9291    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9292    && (GET_CODE (operands[2]) != REG
9293        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9294   "str%?\\t%3, [%0, -%2]!"
9295   [(set_attr "type" "store1")
9296    (set_attr "predicable" "yes")]
9297 )
9298
9299 (define_insn "*loadsi_preinc"
9300   [(set (match_operand:SI 3 "s_register_operand" "=r")
9301         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9302                          (match_operand:SI 2 "index_operand" "rJ"))))
9303    (set (match_operand:SI 0 "s_register_operand" "=r")
9304         (plus:SI (match_dup 1) (match_dup 2)))]
9305   "TARGET_ARM
9306    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9307    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9308    && (GET_CODE (operands[2]) != REG
9309        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9310   "ldr%?\\t%3, [%0, %2]!"
9311   [(set_attr "type" "load1")
9312    (set_attr "predicable" "yes")]
9313 )
9314
9315 (define_insn "*loadsi_predec"
9316   [(set (match_operand:SI 3 "s_register_operand" "=r")
9317         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9318                           (match_operand:SI 2 "s_register_operand" "r"))))
9319    (set (match_operand:SI 0 "s_register_operand" "=r")
9320         (minus:SI (match_dup 1) (match_dup 2)))]
9321   "TARGET_ARM
9322    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9323    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9324    && (GET_CODE (operands[2]) != REG
9325        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9326   "ldr%?\\t%3, [%0, -%2]!"
9327   [(set_attr "type" "load1")
9328    (set_attr "predicable" "yes")]
9329 )
9330
9331 (define_insn "*strqi_shiftpreinc"
9332   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9333                           [(match_operand:SI 3 "s_register_operand" "r")
9334                            (match_operand:SI 4 "const_shift_operand" "n")])
9335                          (match_operand:SI 1 "s_register_operand" "0")))
9336         (match_operand:QI 5 "s_register_operand" "r"))
9337    (set (match_operand:SI 0 "s_register_operand" "=r")
9338         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9339                  (match_dup 1)))]
9340   "TARGET_ARM
9341    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9342    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9343    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9344   "str%?b\\t%5, [%0, %3%S2]!"
9345   [(set_attr "type" "store1")
9346    (set_attr "predicable" "yes")]
9347 )
9348
9349 (define_insn "*strqi_shiftpredec"
9350   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9351                           (match_operator:SI 2 "shift_operator"
9352                            [(match_operand:SI 3 "s_register_operand" "r")
9353                             (match_operand:SI 4 "const_shift_operand" "n")])))
9354         (match_operand:QI 5 "s_register_operand" "r"))
9355    (set (match_operand:SI 0 "s_register_operand" "=r")
9356         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9357                                                  (match_dup 4)])))]
9358   "TARGET_ARM
9359    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9360    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9361    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9362   "str%?b\\t%5, [%0, -%3%S2]!"
9363   [(set_attr "type" "store1")
9364    (set_attr "predicable" "yes")]
9365 )
9366
9367 (define_insn "*loadqi_shiftpreinc"
9368   [(set (match_operand:QI 5 "s_register_operand" "=r")
9369         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9370                           [(match_operand:SI 3 "s_register_operand" "r")
9371                            (match_operand:SI 4 "const_shift_operand" "n")])
9372                          (match_operand:SI 1 "s_register_operand" "0"))))
9373    (set (match_operand:SI 0 "s_register_operand" "=r")
9374         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9375                  (match_dup 1)))]
9376   "TARGET_ARM
9377    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9378    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9379    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9380   "ldr%?b\\t%5, [%0, %3%S2]!"
9381   [(set_attr "type" "load_byte")
9382    (set_attr "predicable" "yes")]
9383 )
9384
9385 (define_insn "*loadqi_shiftpredec"
9386   [(set (match_operand:QI 5 "s_register_operand" "=r")
9387         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9388                           (match_operator:SI 2 "shift_operator"
9389                            [(match_operand:SI 3 "s_register_operand" "r")
9390                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9391    (set (match_operand:SI 0 "s_register_operand" "=r")
9392         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9393                                                  (match_dup 4)])))]
9394   "TARGET_ARM
9395    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9396    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9397    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9398   "ldr%?b\\t%5, [%0, -%3%S2]!"
9399   [(set_attr "type" "load_byte")
9400    (set_attr "predicable" "yes")]
9401 )
9402
9403 (define_insn "*strsi_shiftpreinc"
9404   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9405                           [(match_operand:SI 3 "s_register_operand" "r")
9406                            (match_operand:SI 4 "const_shift_operand" "n")])
9407                          (match_operand:SI 1 "s_register_operand" "0")))
9408         (match_operand:SI 5 "s_register_operand" "r"))
9409    (set (match_operand:SI 0 "s_register_operand" "=r")
9410         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9411                  (match_dup 1)))]
9412   "TARGET_ARM
9413    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9414    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9415    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9416   "str%?\\t%5, [%0, %3%S2]!"
9417   [(set_attr "type" "store1")
9418    (set_attr "predicable" "yes")]
9419 )
9420
9421 (define_insn "*strsi_shiftpredec"
9422   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9423                           (match_operator:SI 2 "shift_operator"
9424                            [(match_operand:SI 3 "s_register_operand" "r")
9425                             (match_operand:SI 4 "const_shift_operand" "n")])))
9426         (match_operand:SI 5 "s_register_operand" "r"))
9427    (set (match_operand:SI 0 "s_register_operand" "=r")
9428         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9429                                                  (match_dup 4)])))]
9430   "TARGET_ARM
9431    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9432    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9433    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9434   "str%?\\t%5, [%0, -%3%S2]!"
9435   [(set_attr "type" "store1")
9436    (set_attr "predicable" "yes")]
9437 )
9438
9439 (define_insn "*loadsi_shiftpreinc"
9440   [(set (match_operand:SI 5 "s_register_operand" "=r")
9441         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9442                           [(match_operand:SI 3 "s_register_operand" "r")
9443                            (match_operand:SI 4 "const_shift_operand" "n")])
9444                          (match_operand:SI 1 "s_register_operand" "0"))))
9445    (set (match_operand:SI 0 "s_register_operand" "=r")
9446         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9447                  (match_dup 1)))]
9448   "TARGET_ARM
9449    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9450    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9451    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9452   "ldr%?\\t%5, [%0, %3%S2]!"
9453   [(set_attr "type" "load1")
9454    (set_attr "predicable" "yes")]
9455 )
9456
9457 (define_insn "*loadsi_shiftpredec"
9458   [(set (match_operand:SI 5 "s_register_operand" "=r")
9459         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9460                           (match_operator:SI 2 "shift_operator"
9461                            [(match_operand:SI 3 "s_register_operand" "r")
9462                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9463    (set (match_operand:SI 0 "s_register_operand" "=r")
9464         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9465                                                  (match_dup 4)])))]
9466   "TARGET_ARM
9467    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9468    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9469    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9470   "ldr%?\\t%5, [%0, -%3%S2]!"
9471   [(set_attr "type" "load1")
9472    (set_attr "predicable" "yes")])
9473
9474 ; It can also support extended post-inc expressions, but combine doesn't
9475 ; try these....
9476 ; It doesn't seem worth adding peepholes for anything but the most common
9477 ; cases since, unlike combine, the increment must immediately follow the load
9478 ; for this pattern to match.
9479 ; We must watch to see that the source/destination register isn't also the
9480 ; same as the base address register, and that if the index is a register,
9481 ; that it is not the same as the base address register.  In such cases the
9482 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9483 ; we cannot use it.
9484
9485 (define_peephole
9486   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9487         (match_operand:QI 2 "s_register_operand" "r"))
9488    (set (match_dup 0)
9489         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9490   "TARGET_ARM
9491    && (REGNO (operands[2]) != REGNO (operands[0]))
9492    && (GET_CODE (operands[1]) != REG
9493        || (REGNO (operands[1]) != REGNO (operands[0])))"
9494   "str%?b\\t%2, [%0], %1"
9495 )
9496
9497 (define_peephole
9498   [(set (match_operand:QI 0 "s_register_operand" "=r")
9499         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9500    (set (match_dup 1)
9501         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9502   "TARGET_ARM
9503    && REGNO (operands[0]) != REGNO(operands[1])
9504    && (GET_CODE (operands[2]) != REG
9505        || REGNO(operands[0]) != REGNO (operands[2]))"
9506   "ldr%?b\\t%0, [%1], %2"
9507 )
9508
9509 (define_peephole
9510   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9511         (match_operand:SI 2 "s_register_operand" "r"))
9512    (set (match_dup 0)
9513         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9514   "TARGET_ARM
9515    && (REGNO (operands[2]) != REGNO (operands[0]))
9516    && (GET_CODE (operands[1]) != REG
9517        || (REGNO (operands[1]) != REGNO (operands[0])))"
9518   "str%?\\t%2, [%0], %1"
9519 )
9520
9521 (define_peephole
9522   [(set (match_operand:SI 0 "s_register_operand" "=r")
9523         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9524    (set (match_dup 1)
9525         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9526   "TARGET_ARM
9527    && REGNO (operands[0]) != REGNO(operands[1])
9528    && (GET_CODE (operands[2]) != REG
9529        || REGNO(operands[0]) != REGNO (operands[2]))"
9530   "ldr%?\\t%0, [%1], %2"
9531 )
9532
9533 (define_peephole
9534   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9535                          (match_operand:SI 1 "index_operand" "rJ")))
9536         (match_operand:QI 2 "s_register_operand" "r"))
9537    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9538   "TARGET_ARM
9539    && (REGNO (operands[2]) != REGNO (operands[0]))
9540    && (GET_CODE (operands[1]) != REG
9541        || (REGNO (operands[1]) != REGNO (operands[0])))"
9542   "str%?b\\t%2, [%0, %1]!"
9543 )
9544
9545 (define_peephole
9546   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9547                           [(match_operand:SI 0 "s_register_operand" "r")
9548                            (match_operand:SI 1 "const_int_operand" "n")])
9549                          (match_operand:SI 2 "s_register_operand" "+r")))
9550         (match_operand:QI 3 "s_register_operand" "r"))
9551    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9552                                (match_dup 2)))]
9553   "TARGET_ARM
9554    && (REGNO (operands[3]) != REGNO (operands[2]))
9555    && (REGNO (operands[0]) != REGNO (operands[2]))"
9556   "str%?b\\t%3, [%2, %0%S4]!"
9557 )
9558
9559 ; This pattern is never tried by combine, so do it as a peephole
9560
9561 (define_peephole2
9562   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9563         (match_operand:SI 1 "arm_general_register_operand" ""))
9564    (set (reg:CC CC_REGNUM)
9565         (compare:CC (match_dup 1) (const_int 0)))]
9566   "TARGET_ARM"
9567   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9568               (set (match_dup 0) (match_dup 1))])]
9569   ""
9570 )
9571
9572 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9573 ; reversed, check that the memory references aren't volatile.
9574
9575 (define_peephole
9576   [(set (match_operand:SI 0 "s_register_operand" "=r")
9577         (match_operand:SI 4 "memory_operand" "m"))
9578    (set (match_operand:SI 1 "s_register_operand" "=r")
9579         (match_operand:SI 5 "memory_operand" "m"))
9580    (set (match_operand:SI 2 "s_register_operand" "=r")
9581         (match_operand:SI 6 "memory_operand" "m"))
9582    (set (match_operand:SI 3 "s_register_operand" "=r")
9583         (match_operand:SI 7 "memory_operand" "m"))]
9584   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9585   "*
9586   return emit_ldm_seq (operands, 4);
9587   "
9588 )
9589
9590 (define_peephole
9591   [(set (match_operand:SI 0 "s_register_operand" "=r")
9592         (match_operand:SI 3 "memory_operand" "m"))
9593    (set (match_operand:SI 1 "s_register_operand" "=r")
9594         (match_operand:SI 4 "memory_operand" "m"))
9595    (set (match_operand:SI 2 "s_register_operand" "=r")
9596         (match_operand:SI 5 "memory_operand" "m"))]
9597   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9598   "*
9599   return emit_ldm_seq (operands, 3);
9600   "
9601 )
9602
9603 (define_peephole
9604   [(set (match_operand:SI 0 "s_register_operand" "=r")
9605         (match_operand:SI 2 "memory_operand" "m"))
9606    (set (match_operand:SI 1 "s_register_operand" "=r")
9607         (match_operand:SI 3 "memory_operand" "m"))]
9608   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9609   "*
9610   return emit_ldm_seq (operands, 2);
9611   "
9612 )
9613
9614 (define_peephole
9615   [(set (match_operand:SI 4 "memory_operand" "=m")
9616         (match_operand:SI 0 "s_register_operand" "r"))
9617    (set (match_operand:SI 5 "memory_operand" "=m")
9618         (match_operand:SI 1 "s_register_operand" "r"))
9619    (set (match_operand:SI 6 "memory_operand" "=m")
9620         (match_operand:SI 2 "s_register_operand" "r"))
9621    (set (match_operand:SI 7 "memory_operand" "=m")
9622         (match_operand:SI 3 "s_register_operand" "r"))]
9623   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9624   "*
9625   return emit_stm_seq (operands, 4);
9626   "
9627 )
9628
9629 (define_peephole
9630   [(set (match_operand:SI 3 "memory_operand" "=m")
9631         (match_operand:SI 0 "s_register_operand" "r"))
9632    (set (match_operand:SI 4 "memory_operand" "=m")
9633         (match_operand:SI 1 "s_register_operand" "r"))
9634    (set (match_operand:SI 5 "memory_operand" "=m")
9635         (match_operand:SI 2 "s_register_operand" "r"))]
9636   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9637   "*
9638   return emit_stm_seq (operands, 3);
9639   "
9640 )
9641
9642 (define_peephole
9643   [(set (match_operand:SI 2 "memory_operand" "=m")
9644         (match_operand:SI 0 "s_register_operand" "r"))
9645    (set (match_operand:SI 3 "memory_operand" "=m")
9646         (match_operand:SI 1 "s_register_operand" "r"))]
9647   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9648   "*
9649   return emit_stm_seq (operands, 2);
9650   "
9651 )
9652
9653 (define_split
9654   [(set (match_operand:SI 0 "s_register_operand" "")
9655         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9656                        (const_int 0))
9657                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9658                          [(match_operand:SI 3 "s_register_operand" "")
9659                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9660    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9661   "TARGET_ARM"
9662   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9663    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9664                               (match_dup 5)))]
9665   ""
9666 )
9667
9668 ;; This split can be used because CC_Z mode implies that the following
9669 ;; branch will be an equality, or an unsigned inequality, so the sign
9670 ;; extension is not needed.
9671
9672 (define_split
9673   [(set (reg:CC_Z CC_REGNUM)
9674         (compare:CC_Z
9675          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9676                     (const_int 24))
9677          (match_operand 1 "const_int_operand" "")))
9678    (clobber (match_scratch:SI 2 ""))]
9679   "TARGET_ARM
9680    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9681        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9682   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9683    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9684   "
9685   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9686   "
9687 )
9688
9689 (define_expand "prologue"
9690   [(clobber (const_int 0))]
9691   "TARGET_EITHER"
9692   "if (TARGET_ARM)
9693      arm_expand_prologue ();
9694    else
9695      thumb_expand_prologue ();
9696   DONE;
9697   "
9698 )
9699
9700 (define_expand "epilogue"
9701   [(clobber (const_int 0))]
9702   "TARGET_EITHER"
9703   "
9704   if (current_function_calls_eh_return)
9705     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9706   if (TARGET_THUMB)
9707     thumb_expand_epilogue ();
9708   else if (USE_RETURN_INSN (FALSE))
9709     {
9710       emit_jump_insn (gen_return ());
9711       DONE;
9712     }
9713   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9714         gen_rtvec (1,
9715                 gen_rtx_RETURN (VOIDmode)),
9716         VUNSPEC_EPILOGUE));
9717   DONE;
9718   "
9719 )
9720
9721 ;; Note - although unspec_volatile's USE all hard registers,
9722 ;; USEs are ignored after relaod has completed.  Thus we need
9723 ;; to add an unspec of the link register to ensure that flow
9724 ;; does not think that it is unused by the sibcall branch that
9725 ;; will replace the standard function epilogue.
9726 (define_insn "sibcall_epilogue"
9727   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9728               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9729   "TARGET_ARM"
9730   "*
9731   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9732     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9733   return arm_output_epilogue (next_nonnote_insn (insn));
9734   "
9735 ;; Length is absolute worst case
9736   [(set_attr "length" "44")
9737    (set_attr "type" "block")
9738    ;; We don't clobber the conditions, but the potential length of this
9739    ;; operation is sufficient to make conditionalizing the sequence 
9740    ;; unlikely to be profitable.
9741    (set_attr "conds" "clob")]
9742 )
9743
9744 (define_insn "*epilogue_insns"
9745   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9746   "TARGET_EITHER"
9747   "*
9748   if (TARGET_ARM)
9749     return arm_output_epilogue (NULL);
9750   else /* TARGET_THUMB */
9751     return thumb_unexpanded_epilogue ();
9752   "
9753   ; Length is absolute worst case
9754   [(set_attr "length" "44")
9755    (set_attr "type" "block")
9756    ;; We don't clobber the conditions, but the potential length of this
9757    ;; operation is sufficient to make conditionalizing the sequence 
9758    ;; unlikely to be profitable.
9759    (set_attr "conds" "clob")]
9760 )
9761
9762 (define_expand "eh_epilogue"
9763   [(use (match_operand:SI 0 "register_operand" ""))
9764    (use (match_operand:SI 1 "register_operand" ""))
9765    (use (match_operand:SI 2 "register_operand" ""))]
9766   "TARGET_EITHER"
9767   "
9768   {
9769     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9770     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9771       {
9772         rtx ra = gen_rtx_REG (Pmode, 2);
9773
9774         emit_move_insn (ra, operands[2]);
9775         operands[2] = ra;
9776       }
9777     /* This is a hack -- we may have crystalized the function type too
9778        early.  */
9779     cfun->machine->func_type = 0;
9780   }"
9781 )
9782
9783 ;; This split is only used during output to reduce the number of patterns
9784 ;; that need assembler instructions adding to them.  We allowed the setting
9785 ;; of the conditions to be implicit during rtl generation so that
9786 ;; the conditional compare patterns would work.  However this conflicts to
9787 ;; some extent with the conditional data operations, so we have to split them
9788 ;; up again here.
9789
9790 (define_split
9791   [(set (match_operand:SI 0 "s_register_operand" "")
9792         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9793                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9794                          (match_dup 0)
9795                          (match_operand 4 "" "")))
9796    (clobber (reg:CC CC_REGNUM))]
9797   "TARGET_ARM && reload_completed"
9798   [(set (match_dup 5) (match_dup 6))
9799    (cond_exec (match_dup 7)
9800               (set (match_dup 0) (match_dup 4)))]
9801   "
9802   {
9803     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9804                                              operands[2], operands[3]);
9805     enum rtx_code rc = GET_CODE (operands[1]);
9806
9807     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9808     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9809     if (mode == CCFPmode || mode == CCFPEmode)
9810       rc = reverse_condition_maybe_unordered (rc);
9811     else
9812       rc = reverse_condition (rc);
9813
9814     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9815   }"
9816 )
9817
9818 (define_split
9819   [(set (match_operand:SI 0 "s_register_operand" "")
9820         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9821                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9822                          (match_operand 4 "" "")
9823                          (match_dup 0)))
9824    (clobber (reg:CC CC_REGNUM))]
9825   "TARGET_ARM && reload_completed"
9826   [(set (match_dup 5) (match_dup 6))
9827    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9828               (set (match_dup 0) (match_dup 4)))]
9829   "
9830   {
9831     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9832                                              operands[2], operands[3]);
9833
9834     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9835     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9836   }"
9837 )
9838
9839 (define_split
9840   [(set (match_operand:SI 0 "s_register_operand" "")
9841         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9842                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9843                          (match_operand 4 "" "")
9844                          (match_operand 5 "" "")))
9845    (clobber (reg:CC CC_REGNUM))]
9846   "TARGET_ARM && reload_completed"
9847   [(set (match_dup 6) (match_dup 7))
9848    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9849               (set (match_dup 0) (match_dup 4)))
9850    (cond_exec (match_dup 8)
9851               (set (match_dup 0) (match_dup 5)))]
9852   "
9853   {
9854     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9855                                              operands[2], operands[3]);
9856     enum rtx_code rc = GET_CODE (operands[1]);
9857
9858     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9859     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9860     if (mode == CCFPmode || mode == CCFPEmode)
9861       rc = reverse_condition_maybe_unordered (rc);
9862     else
9863       rc = reverse_condition (rc);
9864
9865     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9866   }"
9867 )
9868
9869 (define_split
9870   [(set (match_operand:SI 0 "s_register_operand" "")
9871         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9872                           [(match_operand:SI 2 "s_register_operand" "")
9873                            (match_operand:SI 3 "arm_add_operand" "")])
9874                          (match_operand:SI 4 "arm_rhs_operand" "")
9875                          (not:SI
9876                           (match_operand:SI 5 "s_register_operand" ""))))
9877    (clobber (reg:CC CC_REGNUM))]
9878   "TARGET_ARM && reload_completed"
9879   [(set (match_dup 6) (match_dup 7))
9880    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9881               (set (match_dup 0) (match_dup 4)))
9882    (cond_exec (match_dup 8)
9883               (set (match_dup 0) (not:SI (match_dup 5))))]
9884   "
9885   {
9886     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9887                                              operands[2], operands[3]);
9888     enum rtx_code rc = GET_CODE (operands[1]);
9889
9890     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9891     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9892     if (mode == CCFPmode || mode == CCFPEmode)
9893       rc = reverse_condition_maybe_unordered (rc);
9894     else
9895       rc = reverse_condition (rc);
9896
9897     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9898   }"
9899 )
9900
9901 (define_insn "*cond_move_not"
9902   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9903         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9904                           [(match_operand 3 "cc_register" "") (const_int 0)])
9905                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9906                          (not:SI
9907                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9908   "TARGET_ARM"
9909   "@
9910    mvn%D4\\t%0, %2
9911    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9912   [(set_attr "conds" "use")
9913    (set_attr "length" "4,8")]
9914 )
9915
9916 ;; The next two patterns occur when an AND operation is followed by a
9917 ;; scc insn sequence 
9918
9919 (define_insn "*sign_extract_onebit"
9920   [(set (match_operand:SI 0 "s_register_operand" "=r")
9921         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9922                          (const_int 1)
9923                          (match_operand:SI 2 "const_int_operand" "n")))
9924     (clobber (reg:CC CC_REGNUM))]
9925   "TARGET_ARM"
9926   "*
9927     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9928     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9929     return \"mvnne\\t%0, #0\";
9930   "
9931   [(set_attr "conds" "clob")
9932    (set_attr "length" "8")]
9933 )
9934
9935 (define_insn "*not_signextract_onebit"
9936   [(set (match_operand:SI 0 "s_register_operand" "=r")
9937         (not:SI
9938          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9939                           (const_int 1)
9940                           (match_operand:SI 2 "const_int_operand" "n"))))
9941    (clobber (reg:CC CC_REGNUM))]
9942   "TARGET_ARM"
9943   "*
9944     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9945     output_asm_insn (\"tst\\t%1, %2\", operands);
9946     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9947     return \"movne\\t%0, #0\";
9948   "
9949   [(set_attr "conds" "clob")
9950    (set_attr "length" "12")]
9951 )
9952
9953 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9954 ;; expressions.  For simplicity, the first register is also in the unspec
9955 ;; part.
9956 (define_insn "*push_multi"
9957   [(match_parallel 2 "multi_register_push"
9958     [(set (match_operand:BLK 0 "memory_operand" "=m")
9959           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9960                       UNSPEC_PUSH_MULT))])]
9961   "TARGET_ARM"
9962   "*
9963   {
9964     int num_saves = XVECLEN (operands[2], 0);
9965      
9966     /* For the StrongARM at least it is faster to
9967        use STR to store only a single register.  */
9968     if (num_saves == 1)
9969       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9970     else
9971       {
9972         int i;
9973         char pattern[100];
9974
9975         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9976
9977         for (i = 1; i < num_saves; i++)
9978           {
9979             strcat (pattern, \", %|\");
9980             strcat (pattern,
9981                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9982           }
9983
9984         strcat (pattern, \"}\");
9985         output_asm_insn (pattern, operands);
9986       }
9987
9988     return \"\";
9989   }"
9990   [(set_attr "type" "store4")]
9991 )
9992
9993 (define_insn "stack_tie"
9994   [(set (mem:BLK (scratch))
9995         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9996                      (match_operand:SI 1 "s_register_operand" "r")]
9997                     UNSPEC_PRLG_STK))]
9998   ""
9999   ""
10000   [(set_attr "length" "0")]
10001 )
10002
10003 ;; Similarly for the floating point registers
10004 (define_insn "*push_fp_multi"
10005   [(match_parallel 2 "multi_register_push"
10006     [(set (match_operand:BLK 0 "memory_operand" "=m")
10007           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10008                       UNSPEC_PUSH_MULT))])]
10009   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10010   "*
10011   {
10012     char pattern[100];
10013
10014     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10015     output_asm_insn (pattern, operands);
10016     return \"\";
10017   }"
10018   [(set_attr "type" "f_store")]
10019 )
10020
10021 ;; Special patterns for dealing with the constant pool
10022
10023 (define_insn "align_4"
10024   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10025   "TARGET_EITHER"
10026   "*
10027   assemble_align (32);
10028   return \"\";
10029   "
10030 )
10031
10032 (define_insn "align_8"
10033   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10034   "TARGET_EITHER"
10035   "*
10036   assemble_align (64);
10037   return \"\";
10038   "
10039 )
10040
10041 (define_insn "consttable_end"
10042   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10043   "TARGET_EITHER"
10044   "*
10045   making_const_table = FALSE;
10046   return \"\";
10047   "
10048 )
10049
10050 (define_insn "consttable_1"
10051   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10052   "TARGET_THUMB"
10053   "*
10054   making_const_table = TRUE;
10055   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10056   assemble_zeros (3);
10057   return \"\";
10058   "
10059   [(set_attr "length" "4")]
10060 )
10061
10062 (define_insn "consttable_2"
10063   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10064   "TARGET_THUMB"
10065   "*
10066   making_const_table = TRUE;
10067   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10068   assemble_zeros (2);
10069   return \"\";
10070   "
10071   [(set_attr "length" "4")]
10072 )
10073
10074 (define_insn "consttable_4"
10075   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10076   "TARGET_EITHER"
10077   "*
10078   {
10079     making_const_table = TRUE;
10080     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10081       {
10082       case MODE_FLOAT:
10083       {
10084         REAL_VALUE_TYPE r;
10085         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10086         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10087         break;
10088       }
10089       default:
10090         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10091         break;
10092       }
10093     return \"\";
10094   }"
10095   [(set_attr "length" "4")]
10096 )
10097
10098 (define_insn "consttable_8"
10099   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10100   "TARGET_EITHER"
10101   "*
10102   {
10103     making_const_table = TRUE;
10104     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10105       {
10106        case MODE_FLOAT:
10107         {
10108           REAL_VALUE_TYPE r;
10109           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10110           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10111           break;
10112         }
10113       default:
10114         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10115         break;
10116       }
10117     return \"\";
10118   }"
10119   [(set_attr "length" "8")]
10120 )
10121
10122 ;; Miscellaneous Thumb patterns
10123
10124 (define_expand "tablejump"
10125   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10126               (use (label_ref (match_operand 1 "" "")))])]
10127   "TARGET_THUMB"
10128   "
10129   if (flag_pic)
10130     {
10131       /* Hopefully, CSE will eliminate this copy.  */
10132       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10133       rtx reg2 = gen_reg_rtx (SImode);
10134
10135       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10136       operands[0] = reg2;
10137     }
10138   "
10139 )
10140
10141 ;; NB never uses BX.
10142 (define_insn "*thumb_tablejump"
10143   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10144    (use (label_ref (match_operand 1 "" "")))]
10145   "TARGET_THUMB"
10146   "mov\\t%|pc, %0"
10147   [(set_attr "length" "2")]
10148 )
10149
10150 ;; V5 Instructions,
10151
10152 (define_insn "clzsi2"
10153   [(set (match_operand:SI 0 "s_register_operand" "=r")
10154         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10155   "TARGET_ARM && arm_arch5"
10156   "clz%?\\t%0, %1"
10157   [(set_attr "predicable" "yes")])
10158
10159 (define_expand "ffssi2"
10160   [(set (match_operand:SI 0 "s_register_operand" "")
10161         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10162   "TARGET_ARM && arm_arch5"
10163   "
10164   {
10165     rtx t1, t2, t3;
10166
10167     t1 = gen_reg_rtx (SImode);
10168     t2 = gen_reg_rtx (SImode);
10169     t3 = gen_reg_rtx (SImode);
10170
10171     emit_insn (gen_negsi2 (t1, operands[1]));
10172     emit_insn (gen_andsi3 (t2, operands[1], t1));
10173     emit_insn (gen_clzsi2 (t3, t2));
10174     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10175     DONE;
10176   }"
10177 )
10178
10179 (define_expand "ctzsi2"
10180   [(set (match_operand:SI 0 "s_register_operand" "")
10181         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10182   "TARGET_ARM && arm_arch5"
10183   "
10184   {
10185     rtx t1, t2, t3;
10186
10187     t1 = gen_reg_rtx (SImode);
10188     t2 = gen_reg_rtx (SImode);
10189     t3 = gen_reg_rtx (SImode);
10190
10191     emit_insn (gen_negsi2 (t1, operands[1]));
10192     emit_insn (gen_andsi3 (t2, operands[1], t1));
10193     emit_insn (gen_clzsi2 (t3, t2));
10194     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10195     DONE;
10196   }"
10197 )
10198
10199 ;; V5E instructions.
10200
10201 (define_insn "prefetch"
10202   [(prefetch (match_operand:SI 0 "address_operand" "p")
10203              (match_operand:SI 1 "" "")
10204              (match_operand:SI 2 "" ""))]
10205   "TARGET_ARM && arm_arch5e"
10206   "pld\\t%a0")
10207
10208 ;; General predication pattern
10209
10210 (define_cond_exec
10211   [(match_operator 0 "arm_comparison_operator"
10212     [(match_operand 1 "cc_register" "")
10213      (const_int 0)])]
10214   "TARGET_ARM"
10215   ""
10216 )
10217
10218 (define_insn "prologue_use"
10219   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10220   ""
10221   "%@ %0 needed for prologue"
10222 )
10223
10224
10225 ;; Patterns for exception handling
10226
10227 (define_expand "eh_return"
10228   [(use (match_operand 0 "general_operand" ""))]
10229   "TARGET_EITHER"
10230   "
10231   {
10232     if (TARGET_ARM)
10233       emit_insn (gen_arm_eh_return (operands[0]));
10234     else
10235       emit_insn (gen_thumb_eh_return (operands[0]));
10236     DONE;
10237   }"
10238 )
10239                                    
10240 ;; We can't expand this before we know where the link register is stored.
10241 (define_insn_and_split "arm_eh_return"
10242   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10243                     VUNSPEC_EH_RETURN)
10244    (clobber (match_scratch:SI 1 "=&r"))]
10245   "TARGET_ARM"
10246   "#"
10247   "&& reload_completed"
10248   [(const_int 0)]
10249   "
10250   {
10251     arm_set_return_address (operands[0], operands[1]);
10252     DONE;
10253   }"
10254 )
10255
10256 (define_insn_and_split "thumb_eh_return"
10257   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10258                     VUNSPEC_EH_RETURN)
10259    (clobber (match_scratch:SI 1 "=&l"))]
10260   "TARGET_THUMB"
10261   "#"
10262   "&& reload_completed"
10263   [(const_int 0)]
10264   "
10265   {
10266     thumb_set_return_address (operands[0], operands[1]);
10267     DONE;
10268   }"
10269 )
10270
10271 ;; Load the FPA co-processor patterns
10272 (include "fpa.md")
10273 ;; Load the Maverick co-processor patterns
10274 (include "cirrus.md")
10275 ;; Load the Intel Wireless Multimedia Extension patterns
10276 (include "iwmmxt.md")
10277 ;; Load the VFP co-processor patterns
10278 (include "vfp.md")
10279