OSDN Git Service

a3a75568cdac88c873d310d513e263445c54b833
[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, 2005, 2006  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, 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, 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   [(R0_REGNUM        0)         ; First CORE register
34    (IP_REGNUM       12)         ; Scratch register
35    (SP_REGNUM       13)         ; Stack pointer
36    (LR_REGNUM       14)         ; Return address register
37    (PC_REGNUM       15)         ; Program counter
38    (CC_REGNUM       24)         ; Condition code pseudo register
39    (LAST_ARM_REGNUM 15)         ;
40    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
41    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
42   ]
43 )
44 ;; 3rd operand to select_dominance_cc_mode
45 (define_constants
46   [(DOM_CC_X_AND_Y  0)
47    (DOM_CC_NX_OR_Y  1)
48    (DOM_CC_X_OR_Y   2)
49   ]
50 )
51
52 ;; UNSPEC Usage:
53 ;; Note: sin and cos are no-longer used.
54
55 (define_constants
56   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
60                         ;   operand 0 is the result,
61                         ;   operand 1 the parameter.
62    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63                         ;   operand 0 is the first register,
64                         ;   subsequent registers are in parallel (use ...)
65                         ;   expressions.
66    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
67                         ;   usage, that is, we will add the pic_register
68                         ;   value to it before trying to dereference it.
69    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
70                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
71                         ;   described by the RTL but must be wrapped to
72                         ;   prevent combine from trying to rip it apart.
73    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
74                         ;   being scheduled before the stack adjustment insn.
75    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76                         ; this unspec is used to prevent the deletion of
77                         ; instructions setting registers for EH handling
78                         ; and stack frame generation.  Operand 0 is the
79                         ; register to "use".
80    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93    (UNSPEC_TLS      20) ; A symbol that has been treated properly for TLS usage.
94    (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95                          ; instruction stream.
96   ]
97 )
98
99 ;; UNSPEC_VOLATILE Usage:
100
101 (define_constants
102   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
103                         ;   insn in the code.
104    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
105                         ;   instruction epilogue sequence that isn't expanded
106                         ;   into normal RTL.  Used for both normal and sibcall
107                         ;   epilogues.
108    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
109                         ;   for inlined constants.
110    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
111                         ;   table.
112    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
113                         ;   an 8-bit object.
114    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
115                         ;   a 16-bit object.
116    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
117                         ;   a 32-bit object.
118    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
119                         ;   a 64-bit object.
120    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
121    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
122    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
123    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
124    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
125    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
126    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
127                          ; handling.
128   ]
129 )
130 \f
131 ;;---------------------------------------------------------------------------
132 ;; Attributes
133
134 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
135 ; generating ARM code.  This is used to control the length of some insn
136 ; patterns that share the same RTL in both ARM and Thumb code.
137 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
138
139 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
140 ; scheduling decisions for the load unit and the multiplier.
141 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
142
143 ; IS_XSCALE is set to 'yes' when compiling for XScale.
144 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
145
146 ;; Operand number of an input operand that is shifted.  Zero if the
147 ;; given instruction does not shift one of its input operands.
148 (define_attr "shift" "" (const_int 0))
149
150 ; Floating Point Unit.  If we only have floating point emulation, then there
151 ; is no point in scheduling the floating point insns.  (Well, for best
152 ; performance we should try and group them together).
153 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
154   (const (symbol_ref "arm_fpu_attr")))
155
156 ; LENGTH of an instruction (in bytes)
157 (define_attr "length" "" (const_int 4))
158
159 ; POOL_RANGE is how far away from a constant pool entry that this insn
160 ; can be placed.  If the distance is zero, then this insn will never
161 ; reference the pool.
162 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
163 ; before its address.
164 (define_attr "pool_range" "" (const_int 0))
165 (define_attr "neg_pool_range" "" (const_int 0))
166
167 ; An assembler sequence may clobber the condition codes without us knowing.
168 ; If such an insn references the pool, then we have no way of knowing how,
169 ; so use the most conservative value for pool_range.
170 (define_asm_attributes
171  [(set_attr "conds" "clob")
172   (set_attr "length" "4")
173   (set_attr "pool_range" "250")])
174
175 ;; The instruction used to implement a particular pattern.  This
176 ;; information is used by pipeline descriptions to provide accurate
177 ;; scheduling information.
178
179 (define_attr "insn"
180         "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"
181         (const_string "other"))
182
183 ; TYPE attribute is used to detect floating point instructions which, if
184 ; running on a co-processor can run in parallel with other, basic instructions
185 ; If write-buffer scheduling is enabled then it can also be used in the
186 ; scheduling of writes.
187
188 ; Classification of each insn
189 ; alu           any alu  instruction that doesn't hit memory or fp
190 ;               regs or have a shifted source operand
191 ; alu_shift     any data instruction that doesn't hit memory or fp
192 ;               regs, but has a source operand shifted by a constant
193 ; alu_shift_reg any data instruction that doesn't hit memory or fp
194 ;               regs, but has a source operand shifted by a register value
195 ; mult          a multiply instruction
196 ; block         blockage insn, this blocks all functional units
197 ; float         a floating point arithmetic operation (subject to expansion)
198 ; fdivd         DFmode floating point division
199 ; fdivs         SFmode floating point division
200 ; fmul          Floating point multiply
201 ; ffmul         Fast floating point multiply
202 ; farith        Floating point arithmetic (4 cycle)
203 ; ffarith       Fast floating point arithmetic (2 cycle)
204 ; float_em      a floating point arithmetic operation that is normally emulated
205 ;               even on a machine with an fpa.
206 ; f_load        a floating point load from memory
207 ; f_store       a floating point store to memory
208 ; f_load[sd]    single/double load from memory
209 ; f_store[sd]   single/double store to memory
210 ; f_flag        a transfer of co-processor flags to the CPSR
211 ; f_mem_r       a transfer of a floating point register to a real reg via mem
212 ; r_mem_f       the reverse of f_mem_r
213 ; f_2_r         fast transfer float to arm (no memory needed)
214 ; r_2_f         fast transfer arm to float
215 ; f_cvt         convert floating<->integral
216 ; branch        a branch
217 ; call          a subroutine call
218 ; load_byte     load byte(s) from memory to arm registers
219 ; load1         load 1 word from memory to arm registers
220 ; load2         load 2 words from memory to arm registers
221 ; load3         load 3 words from memory to arm registers
222 ; load4         load 4 words from memory to arm registers
223 ; store         store 1 word to memory from arm registers
224 ; store2        store 2 words
225 ; store3        store 3 words
226 ; store4        store 4 (or more) words
227 ;  Additions for Cirrus Maverick co-processor:
228 ; mav_farith    Floating point arithmetic (4 cycle)
229 ; mav_dmult     Double multiplies (7 cycle)
230 ;
231 (define_attr "type"
232         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
233         (if_then_else 
234          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
235          (const_string "mult")
236          (const_string "alu")))
237
238 ; Load scheduling, set from the arm_ld_sched variable
239 ; initialized by arm_override_options() 
240 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
241
242 ; condition codes: this one is used by final_prescan_insn to speed up
243 ; conditionalizing instructions.  It saves having to scan the rtl to see if
244 ; it uses or alters the condition codes.
245
246 ; USE means that the condition codes are used by the insn in the process of
247 ;   outputting code, this means (at present) that we can't use the insn in
248 ;   inlined branches
249 ;
250 ; SET means that the purpose of the insn is to set the condition codes in a
251 ;   well defined manner.
252 ;
253 ; CLOB means that the condition codes are altered in an undefined manner, if
254 ;   they are altered at all
255 ;
256 ; JUMP_CLOB is used when the condition cannot be represented by a single
257 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
258 ;
259 ; NOCOND means that the condition codes are neither altered nor affect the
260 ;   output of this insn
261
262 (define_attr "conds" "use,set,clob,jump_clob,nocond"
263         (if_then_else (eq_attr "type" "call")
264          (const_string "clob")
265          (const_string "nocond")))
266
267 ; Predicable means that the insn can be conditionally executed based on
268 ; an automatically added predicate (additional patterns are generated by 
269 ; gen...).  We default to 'no' because no Thumb patterns match this rule
270 ; and not all ARM patterns do.
271 (define_attr "predicable" "no,yes" (const_string "no"))
272
273 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
274 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
275 ; suffer blockages enough to warrant modelling this (and it can adversely
276 ; affect the schedule).
277 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
278
279 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
280 ; to stall the processor.  Used with model_wbuf above.
281 (define_attr "write_conflict" "no,yes"
282   (if_then_else (eq_attr "type"
283                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
284                 (const_string "yes")
285                 (const_string "no")))
286
287 ; Classify the insns into those that take one cycle and those that take more
288 ; than one on the main cpu execution unit.
289 (define_attr "core_cycles" "single,multi"
290   (if_then_else (eq_attr "type"
291                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
292                 (const_string "single")
293                 (const_string "multi")))
294
295 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
296 ;; distant label.  Only applicable to Thumb code.
297 (define_attr "far_jump" "yes,no" (const_string "no"))
298
299
300 ;;---------------------------------------------------------------------------
301 ;; Mode macros
302
303 ; A list of modes that are exactly 64 bits in size.  We use this to expand
304 ; some splits that are the same for all modes when operating on ARM 
305 ; registers.
306 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
307
308 ;;---------------------------------------------------------------------------
309 ;; Predicates
310
311 (include "predicates.md")
312
313 ;;---------------------------------------------------------------------------
314 ;; Pipeline descriptions
315
316 ;; Processor type.  This is created automatically from arm-cores.def.
317 (include "arm-tune.md")
318
319 ;; True if the generic scheduling description should be used.
320
321 (define_attr "generic_sched" "yes,no"
322   (const (if_then_else 
323           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 
324           (const_string "no")
325           (const_string "yes"))))
326
327 (define_attr "generic_vfp" "yes,no"
328   (const (if_then_else
329           (and (eq_attr "fpu" "vfp")
330                (eq_attr "tune" "!arm1020e,arm1022e"))
331           (const_string "yes")
332           (const_string "no"))))
333
334 (include "arm-generic.md")
335 (include "arm926ejs.md")
336 (include "arm1020e.md")
337 (include "arm1026ejs.md")
338 (include "arm1136jfs.md")
339
340 \f
341 ;;---------------------------------------------------------------------------
342 ;; Insn patterns
343 ;;
344 ;; Addition insns.
345
346 ;; Note: For DImode insns, there is normally no reason why operands should
347 ;; not be in the same register, what we don't want is for something being
348 ;; written to partially overlap something that is an input.
349 ;; Cirrus 64bit additions should not be split because we have a native
350 ;; 64bit addition instructions.
351
352 (define_expand "adddi3"
353  [(parallel
354    [(set (match_operand:DI           0 "s_register_operand" "")
355           (plus:DI (match_operand:DI 1 "s_register_operand" "")
356                    (match_operand:DI 2 "s_register_operand" "")))
357     (clobber (reg:CC CC_REGNUM))])]
358   "TARGET_EITHER"
359   "
360   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
361     {
362       if (!cirrus_fp_register (operands[0], DImode))
363         operands[0] = force_reg (DImode, operands[0]);
364       if (!cirrus_fp_register (operands[1], DImode))
365         operands[1] = force_reg (DImode, operands[1]);
366       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
367       DONE;
368     }
369
370   if (TARGET_THUMB)
371     {
372       if (GET_CODE (operands[1]) != REG)
373         operands[1] = force_reg (SImode, operands[1]);
374       if (GET_CODE (operands[2]) != REG)
375         operands[2] = force_reg (SImode, operands[2]);
376      }
377   "
378 )
379
380 (define_insn "*thumb_adddi3"
381   [(set (match_operand:DI          0 "register_operand" "=l")
382         (plus:DI (match_operand:DI 1 "register_operand" "%0")
383                  (match_operand:DI 2 "register_operand" "l")))
384    (clobber (reg:CC CC_REGNUM))
385   ]
386   "TARGET_THUMB"
387   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
388   [(set_attr "length" "4")]
389 )
390
391 (define_insn_and_split "*arm_adddi3"
392   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
393         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
394                  (match_operand:DI 2 "s_register_operand" "r,  0")))
395    (clobber (reg:CC CC_REGNUM))]
396   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
397   "#"
398   "TARGET_ARM && reload_completed"
399   [(parallel [(set (reg:CC_C CC_REGNUM)
400                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
401                                  (match_dup 1)))
402               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
403    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
404                                (plus:SI (match_dup 4) (match_dup 5))))]
405   "
406   {
407     operands[3] = gen_highpart (SImode, operands[0]);
408     operands[0] = gen_lowpart (SImode, operands[0]);
409     operands[4] = gen_highpart (SImode, operands[1]);
410     operands[1] = gen_lowpart (SImode, operands[1]);
411     operands[5] = gen_highpart (SImode, operands[2]);
412     operands[2] = gen_lowpart (SImode, operands[2]);
413   }"
414   [(set_attr "conds" "clob")
415    (set_attr "length" "8")]
416 )
417
418 (define_insn_and_split "*adddi_sesidi_di"
419   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
420         (plus:DI (sign_extend:DI
421                   (match_operand:SI 2 "s_register_operand" "r,r"))
422                  (match_operand:DI 1 "s_register_operand" "r,0")))
423    (clobber (reg:CC CC_REGNUM))]
424   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
425   "#"
426   "TARGET_ARM && reload_completed"
427   [(parallel [(set (reg:CC_C CC_REGNUM)
428                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
429                                  (match_dup 1)))
430               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
431    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
432                                (plus:SI (ashiftrt:SI (match_dup 2)
433                                                      (const_int 31))
434                                         (match_dup 4))))]
435   "
436   {
437     operands[3] = gen_highpart (SImode, operands[0]);
438     operands[0] = gen_lowpart (SImode, operands[0]);
439     operands[4] = gen_highpart (SImode, operands[1]);
440     operands[1] = gen_lowpart (SImode, operands[1]);
441     operands[2] = gen_lowpart (SImode, operands[2]);
442   }"
443   [(set_attr "conds" "clob")
444    (set_attr "length" "8")]
445 )
446
447 (define_insn_and_split "*adddi_zesidi_di"
448   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
449         (plus:DI (zero_extend:DI
450                   (match_operand:SI 2 "s_register_operand" "r,r"))
451                  (match_operand:DI 1 "s_register_operand" "r,0")))
452    (clobber (reg:CC CC_REGNUM))]
453   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
454   "#"
455   "TARGET_ARM && reload_completed"
456   [(parallel [(set (reg:CC_C CC_REGNUM)
457                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
458                                  (match_dup 1)))
459               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
460    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
461                                (plus:SI (match_dup 4) (const_int 0))))]
462   "
463   {
464     operands[3] = gen_highpart (SImode, operands[0]);
465     operands[0] = gen_lowpart (SImode, operands[0]);
466     operands[4] = gen_highpart (SImode, operands[1]);
467     operands[1] = gen_lowpart (SImode, operands[1]);
468     operands[2] = gen_lowpart (SImode, operands[2]);
469   }"
470   [(set_attr "conds" "clob")
471    (set_attr "length" "8")]
472 )
473
474 (define_expand "addsi3"
475   [(set (match_operand:SI          0 "s_register_operand" "")
476         (plus:SI (match_operand:SI 1 "s_register_operand" "")
477                  (match_operand:SI 2 "reg_or_int_operand" "")))]
478   "TARGET_EITHER"
479   "
480   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
481     {
482       arm_split_constant (PLUS, SImode, NULL_RTX,
483                           INTVAL (operands[2]), operands[0], operands[1],
484                           optimize && !no_new_pseudos);
485       DONE;
486     }
487   "
488 )
489
490 ; If there is a scratch available, this will be faster than synthesizing the
491 ; addition.
492 (define_peephole2
493   [(match_scratch:SI 3 "r")
494    (set (match_operand:SI          0 "arm_general_register_operand" "")
495         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
496                  (match_operand:SI 2 "const_int_operand"  "")))]
497   "TARGET_ARM &&
498    !(const_ok_for_arm (INTVAL (operands[2]))
499      || const_ok_for_arm (-INTVAL (operands[2])))
500     && const_ok_for_arm (~INTVAL (operands[2]))"
501   [(set (match_dup 3) (match_dup 2))
502    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
503   ""
504 )
505
506 (define_insn_and_split "*arm_addsi3"
507   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
508         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
509                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
510   "TARGET_ARM"
511   "@
512    add%?\\t%0, %1, %2
513    sub%?\\t%0, %1, #%n2
514    #"
515   "TARGET_ARM &&
516    GET_CODE (operands[2]) == CONST_INT
517    && !(const_ok_for_arm (INTVAL (operands[2]))
518         || const_ok_for_arm (-INTVAL (operands[2])))"
519   [(clobber (const_int 0))]
520   "
521   arm_split_constant (PLUS, SImode, curr_insn,
522                       INTVAL (operands[2]), operands[0],
523                       operands[1], 0);
524   DONE;
525   "
526   [(set_attr "length" "4,4,16")
527    (set_attr "predicable" "yes")]
528 )
529
530 ;; Register group 'k' is a single register group containing only the stack
531 ;; register.  Trying to reload it will always fail catastrophically,
532 ;; so never allow those alternatives to match if reloading is needed.
533
534 (define_insn "*thumb_addsi3"
535   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
536         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
537                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
538   "TARGET_THUMB"
539   "*
540    static const char * const asms[] = 
541    {
542      \"add\\t%0, %0, %2\",
543      \"sub\\t%0, %0, #%n2\",
544      \"add\\t%0, %1, %2\",
545      \"add\\t%0, %0, %2\",
546      \"add\\t%0, %0, %2\",
547      \"add\\t%0, %1, %2\",
548      \"add\\t%0, %1, %2\"
549    };
550    if ((which_alternative == 2 || which_alternative == 6)
551        && GET_CODE (operands[2]) == CONST_INT
552        && INTVAL (operands[2]) < 0)
553      return \"sub\\t%0, %1, #%n2\";
554    return asms[which_alternative];
555   "
556   [(set_attr "length" "2")]
557 )
558
559 ;; Reloading and elimination of the frame pointer can
560 ;; sometimes cause this optimization to be missed.
561 (define_peephole2
562   [(set (match_operand:SI 0 "arm_general_register_operand" "")
563         (match_operand:SI 1 "const_int_operand" ""))
564    (set (match_dup 0)
565         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
566   "TARGET_THUMB
567    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
568    && (INTVAL (operands[1]) & 3) == 0"
569   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
570   ""
571 )
572
573 (define_insn "*addsi3_compare0"
574   [(set (reg:CC_NOOV CC_REGNUM)
575         (compare:CC_NOOV
576          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
577                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
578          (const_int 0)))
579    (set (match_operand:SI 0 "s_register_operand" "=r,r")
580         (plus:SI (match_dup 1) (match_dup 2)))]
581   "TARGET_ARM"
582   "@
583    add%?s\\t%0, %1, %2
584    sub%?s\\t%0, %1, #%n2"
585   [(set_attr "conds" "set")]
586 )
587
588 (define_insn "*addsi3_compare0_scratch"
589   [(set (reg:CC_NOOV CC_REGNUM)
590         (compare:CC_NOOV
591          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
592                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
593          (const_int 0)))]
594   "TARGET_ARM"
595   "@
596    cmn%?\\t%0, %1
597    cmp%?\\t%0, #%n1"
598   [(set_attr "conds" "set")]
599 )
600
601 (define_insn "*compare_negsi_si"
602   [(set (reg:CC_Z CC_REGNUM)
603         (compare:CC_Z
604          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
605          (match_operand:SI 1 "s_register_operand" "r")))]
606   "TARGET_ARM"
607   "cmn%?\\t%1, %0"
608   [(set_attr "conds" "set")]
609 )
610
611 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
612 ;; addend is a constant.
613 (define_insn "*cmpsi2_addneg"
614   [(set (reg:CC CC_REGNUM)
615         (compare:CC
616          (match_operand:SI 1 "s_register_operand" "r,r")
617          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
618    (set (match_operand:SI 0 "s_register_operand" "=r,r")
619         (plus:SI (match_dup 1)
620                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
621   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
622   "@
623    sub%?s\\t%0, %1, %2
624    add%?s\\t%0, %1, #%n2"
625   [(set_attr "conds" "set")]
626 )
627
628 ;; Convert the sequence
629 ;;  sub  rd, rn, #1
630 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
631 ;;  bne  dest
632 ;; into
633 ;;  subs rd, rn, #1
634 ;;  bcs  dest   ((unsigned)rn >= 1)
635 ;; similarly for the beq variant using bcc.
636 ;; This is a common looping idiom (while (n--))
637 (define_peephole2
638   [(set (match_operand:SI 0 "arm_general_register_operand" "")
639         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
640                  (const_int -1)))
641    (set (match_operand 2 "cc_register" "")
642         (compare (match_dup 0) (const_int -1)))
643    (set (pc)
644         (if_then_else (match_operator 3 "equality_operator"
645                        [(match_dup 2) (const_int 0)])
646                       (match_operand 4 "" "")
647                       (match_operand 5 "" "")))]
648   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
649   [(parallel[
650     (set (match_dup 2)
651          (compare:CC
652           (match_dup 1) (const_int 1)))
653     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
654    (set (pc)
655         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
656                       (match_dup 4)
657                       (match_dup 5)))]
658   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
659    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
660                                   ? GEU : LTU),
661                                  VOIDmode, 
662                                  operands[2], const0_rtx);"
663 )
664
665 ;; The next four insns work because they compare the result with one of
666 ;; the operands, and we know that the use of the condition code is
667 ;; either GEU or LTU, so we can use the carry flag from the addition
668 ;; instead of doing the compare a second time.
669 (define_insn "*addsi3_compare_op1"
670   [(set (reg:CC_C CC_REGNUM)
671         (compare:CC_C
672          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
674          (match_dup 1)))
675    (set (match_operand:SI 0 "s_register_operand" "=r,r")
676         (plus:SI (match_dup 1) (match_dup 2)))]
677   "TARGET_ARM"
678   "@
679    add%?s\\t%0, %1, %2
680    sub%?s\\t%0, %1, #%n2"
681   [(set_attr "conds" "set")]
682 )
683
684 (define_insn "*addsi3_compare_op2"
685   [(set (reg:CC_C CC_REGNUM)
686         (compare:CC_C
687          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
689          (match_dup 2)))
690    (set (match_operand:SI 0 "s_register_operand" "=r,r")
691         (plus:SI (match_dup 1) (match_dup 2)))]
692   "TARGET_ARM"
693   "@
694    add%?s\\t%0, %1, %2
695    sub%?s\\t%0, %1, #%n2"
696   [(set_attr "conds" "set")]
697 )
698
699 (define_insn "*compare_addsi2_op0"
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 0)))]
705   "TARGET_ARM"
706   "@
707    cmn%?\\t%0, %1
708    cmp%?\\t%0, #%n1"
709   [(set_attr "conds" "set")]
710 )
711
712 (define_insn "*compare_addsi2_op1"
713   [(set (reg:CC_C CC_REGNUM)
714         (compare:CC_C
715          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
716                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
717          (match_dup 1)))]
718   "TARGET_ARM"
719   "@
720    cmn%?\\t%0, %1
721    cmp%?\\t%0, #%n1"
722   [(set_attr "conds" "set")]
723 )
724
725 (define_insn "*addsi3_carryin"
726   [(set (match_operand:SI 0 "s_register_operand" "=r")
727         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
728                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
730   "TARGET_ARM"
731   "adc%?\\t%0, %1, %2"
732   [(set_attr "conds" "use")]
733 )
734
735 (define_insn "*addsi3_carryin_shift"
736   [(set (match_operand:SI 0 "s_register_operand" "=r")
737         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
738                  (plus:SI
739                    (match_operator:SI 2 "shift_operator"
740                       [(match_operand:SI 3 "s_register_operand" "r")
741                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
742                     (match_operand:SI 1 "s_register_operand" "r"))))]
743   "TARGET_ARM"
744   "adc%?\\t%0, %1, %3%S2"
745   [(set_attr "conds" "use")
746    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
747                       (const_string "alu_shift")
748                       (const_string "alu_shift_reg")))]
749 )
750
751 (define_insn "*addsi3_carryin_alt1"
752   [(set (match_operand:SI 0 "s_register_operand" "=r")
753         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
755                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
756   "TARGET_ARM"
757   "adc%?\\t%0, %1, %2"
758   [(set_attr "conds" "use")]
759 )
760
761 (define_insn "*addsi3_carryin_alt2"
762   [(set (match_operand:SI 0 "s_register_operand" "=r")
763         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
764                           (match_operand:SI 1 "s_register_operand" "r"))
765                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
766   "TARGET_ARM"
767   "adc%?\\t%0, %1, %2"
768   [(set_attr "conds" "use")]
769 )
770
771 (define_insn "*addsi3_carryin_alt3"
772   [(set (match_operand:SI 0 "s_register_operand" "=r")
773         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
774                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
775                  (match_operand:SI 1 "s_register_operand" "r")))]
776   "TARGET_ARM"
777   "adc%?\\t%0, %1, %2"
778   [(set_attr "conds" "use")]
779 )
780
781 (define_insn "incscc"
782   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
783         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
784                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
785                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
786   "TARGET_ARM"
787   "@
788   add%d2\\t%0, %1, #1
789   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
790   [(set_attr "conds" "use")
791    (set_attr "length" "4,8")]
792 )
793
794 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
795 (define_split
796   [(set (match_operand:SI 0 "s_register_operand" "")
797         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
798                             (match_operand:SI 2 "s_register_operand" ""))
799                  (const_int -1)))
800    (clobber (match_operand:SI 3 "s_register_operand" ""))]
801   "TARGET_ARM"
802   [(set (match_dup 3) (match_dup 1))
803    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
804   "
805   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
806 ")
807
808 (define_expand "addsf3"
809   [(set (match_operand:SF          0 "s_register_operand" "")
810         (plus:SF (match_operand:SF 1 "s_register_operand" "")
811                  (match_operand:SF 2 "arm_float_add_operand" "")))]
812   "TARGET_ARM && TARGET_HARD_FLOAT"
813   "
814   if (TARGET_MAVERICK
815       && !cirrus_fp_register (operands[2], SFmode))
816     operands[2] = force_reg (SFmode, operands[2]);
817 ")
818
819 (define_expand "adddf3"
820   [(set (match_operand:DF          0 "s_register_operand" "")
821         (plus:DF (match_operand:DF 1 "s_register_operand" "")
822                  (match_operand:DF 2 "arm_float_add_operand" "")))]
823   "TARGET_ARM && TARGET_HARD_FLOAT"
824   "
825   if (TARGET_MAVERICK
826       && !cirrus_fp_register (operands[2], DFmode))
827     operands[2] = force_reg (DFmode, operands[2]);
828 ")
829
830 (define_expand "subdi3"
831  [(parallel
832    [(set (match_operand:DI            0 "s_register_operand" "")
833           (minus:DI (match_operand:DI 1 "s_register_operand" "")
834                     (match_operand:DI 2 "s_register_operand" "")))
835     (clobber (reg:CC CC_REGNUM))])]
836   "TARGET_EITHER"
837   "
838   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
839       && TARGET_ARM
840       && cirrus_fp_register (operands[0], DImode)
841       && cirrus_fp_register (operands[1], DImode))
842     {
843       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
844       DONE;
845     }
846
847   if (TARGET_THUMB)
848     {
849       if (GET_CODE (operands[1]) != REG)
850         operands[1] = force_reg (SImode, operands[1]);
851       if (GET_CODE (operands[2]) != REG)
852         operands[2] = force_reg (SImode, operands[2]);
853      }  
854   "
855 )
856
857 (define_insn "*arm_subdi3"
858   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
859         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
860                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
861    (clobber (reg:CC CC_REGNUM))]
862   "TARGET_ARM"
863   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
864   [(set_attr "conds" "clob")
865    (set_attr "length" "8")]
866 )
867
868 (define_insn "*thumb_subdi3"
869   [(set (match_operand:DI           0 "register_operand" "=l")
870         (minus:DI (match_operand:DI 1 "register_operand"  "0")
871                   (match_operand:DI 2 "register_operand"  "l")))
872    (clobber (reg:CC CC_REGNUM))]
873   "TARGET_THUMB"
874   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
875   [(set_attr "length" "4")]
876 )
877
878 (define_insn "*subdi_di_zesidi"
879   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
880         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
881                   (zero_extend:DI
882                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
883    (clobber (reg:CC CC_REGNUM))]
884   "TARGET_ARM"
885   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
886   [(set_attr "conds" "clob")
887    (set_attr "length" "8")]
888 )
889
890 (define_insn "*subdi_di_sesidi"
891   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
892         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
893                   (sign_extend:DI
894                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
895    (clobber (reg:CC CC_REGNUM))]
896   "TARGET_ARM"
897   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
898   [(set_attr "conds" "clob")
899    (set_attr "length" "8")]
900 )
901
902 (define_insn "*subdi_zesidi_di"
903   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
904         (minus:DI (zero_extend:DI
905                    (match_operand:SI 2 "s_register_operand"  "r,r"))
906                   (match_operand:DI  1 "s_register_operand" "?r,0")))
907    (clobber (reg:CC CC_REGNUM))]
908   "TARGET_ARM"
909   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
910   [(set_attr "conds" "clob")
911    (set_attr "length" "8")]
912 )
913
914 (define_insn "*subdi_sesidi_di"
915   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
916         (minus:DI (sign_extend:DI
917                    (match_operand:SI 2 "s_register_operand"   "r,r"))
918                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
919    (clobber (reg:CC CC_REGNUM))]
920   "TARGET_ARM"
921   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
922   [(set_attr "conds" "clob")
923    (set_attr "length" "8")]
924 )
925
926 (define_insn "*subdi_zesidi_zesidi"
927   [(set (match_operand:DI            0 "s_register_operand" "=r")
928         (minus:DI (zero_extend:DI
929                    (match_operand:SI 1 "s_register_operand"  "r"))
930                   (zero_extend:DI
931                    (match_operand:SI 2 "s_register_operand"  "r"))))
932    (clobber (reg:CC CC_REGNUM))]
933   "TARGET_ARM"
934   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
935   [(set_attr "conds" "clob")
936    (set_attr "length" "8")]
937 )
938
939 (define_expand "subsi3"
940   [(set (match_operand:SI           0 "s_register_operand" "")
941         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
942                   (match_operand:SI 2 "s_register_operand" "")))]
943   "TARGET_EITHER"
944   "
945   if (GET_CODE (operands[1]) == CONST_INT)
946     {
947       if (TARGET_ARM)
948         {
949           arm_split_constant (MINUS, SImode, NULL_RTX,
950                               INTVAL (operands[1]), operands[0],
951                               operands[2], optimize && !no_new_pseudos);
952           DONE;
953         }
954       else /* TARGET_THUMB */
955         operands[1] = force_reg (SImode, operands[1]);
956     }
957   "
958 )
959
960 (define_insn "*thumb_subsi3_insn"
961   [(set (match_operand:SI           0 "register_operand" "=l")
962         (minus:SI (match_operand:SI 1 "register_operand" "l")
963                   (match_operand:SI 2 "register_operand" "l")))]
964   "TARGET_THUMB"
965   "sub\\t%0, %1, %2"
966   [(set_attr "length" "2")]
967 )
968
969 (define_insn_and_split "*arm_subsi3_insn"
970   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
971         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
972                   (match_operand:SI 2 "s_register_operand" "r,r")))]
973   "TARGET_ARM"
974   "@
975    rsb%?\\t%0, %2, %1
976    #"
977   "TARGET_ARM
978    && GET_CODE (operands[1]) == CONST_INT
979    && !const_ok_for_arm (INTVAL (operands[1]))"
980   [(clobber (const_int 0))]
981   "
982   arm_split_constant (MINUS, SImode, curr_insn,
983                       INTVAL (operands[1]), operands[0], operands[2], 0);
984   DONE;
985   "
986   [(set_attr "length" "4,16")
987    (set_attr "predicable" "yes")]
988 )
989
990 (define_peephole2
991   [(match_scratch:SI 3 "r")
992    (set (match_operand:SI 0 "arm_general_register_operand" "")
993         (minus:SI (match_operand:SI 1 "const_int_operand" "")
994                   (match_operand:SI 2 "arm_general_register_operand" "")))]
995   "TARGET_ARM
996    && !const_ok_for_arm (INTVAL (operands[1]))
997    && const_ok_for_arm (~INTVAL (operands[1]))"
998   [(set (match_dup 3) (match_dup 1))
999    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1000   ""
1001 )
1002
1003 (define_insn "*subsi3_compare0"
1004   [(set (reg:CC_NOOV CC_REGNUM)
1005         (compare:CC_NOOV
1006          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1007                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1008          (const_int 0)))
1009    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1010         (minus:SI (match_dup 1) (match_dup 2)))]
1011   "TARGET_ARM"
1012   "@
1013    sub%?s\\t%0, %1, %2
1014    rsb%?s\\t%0, %2, %1"
1015   [(set_attr "conds" "set")]
1016 )
1017
1018 (define_insn "decscc"
1019   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1020         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1021                   (match_operator:SI 2 "arm_comparison_operator"
1022                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1023   "TARGET_ARM"
1024   "@
1025    sub%d2\\t%0, %1, #1
1026    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1027   [(set_attr "conds" "use")
1028    (set_attr "length" "*,8")]
1029 )
1030
1031 (define_expand "subsf3"
1032   [(set (match_operand:SF           0 "s_register_operand" "")
1033         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1034                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1035   "TARGET_ARM && TARGET_HARD_FLOAT"
1036   "
1037   if (TARGET_MAVERICK)
1038     {
1039       if (!cirrus_fp_register (operands[1], SFmode))
1040         operands[1] = force_reg (SFmode, operands[1]);
1041       if (!cirrus_fp_register (operands[2], SFmode))
1042         operands[2] = force_reg (SFmode, operands[2]);
1043     }
1044 ")
1045
1046 (define_expand "subdf3"
1047   [(set (match_operand:DF           0 "s_register_operand" "")
1048         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1049                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1050   "TARGET_ARM && TARGET_HARD_FLOAT"
1051   "
1052   if (TARGET_MAVERICK)
1053     {
1054        if (!cirrus_fp_register (operands[1], DFmode))
1055          operands[1] = force_reg (DFmode, operands[1]);
1056        if (!cirrus_fp_register (operands[2], DFmode))
1057          operands[2] = force_reg (DFmode, operands[2]);
1058     }
1059 ")
1060
1061 \f
1062 ;; Multiplication insns
1063
1064 (define_expand "mulsi3"
1065   [(set (match_operand:SI          0 "s_register_operand" "")
1066         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1067                  (match_operand:SI 1 "s_register_operand" "")))]
1068   "TARGET_EITHER"
1069   ""
1070 )
1071
1072 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1073 (define_insn "*arm_mulsi3"
1074   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1075         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1076                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1077   "TARGET_ARM"
1078   "mul%?\\t%0, %2, %1"
1079   [(set_attr "insn" "mul")
1080    (set_attr "predicable" "yes")]
1081 )
1082
1083 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1084 ; 1 and 2; are the same, because reload will make operand 0 match 
1085 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1086 ; this by adding another alternative to match this case, and then `reload' 
1087 ; it ourselves.  This alternative must come first.
1088 (define_insn "*thumb_mulsi3"
1089   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1090         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1091                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1092   "TARGET_THUMB"
1093   "*
1094   if (which_alternative < 2)
1095     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1096   else
1097     return \"mul\\t%0, %2\";
1098   "
1099   [(set_attr "length" "4,4,2")
1100    (set_attr "insn" "mul")]
1101 )
1102
1103 (define_insn "*mulsi3_compare0"
1104   [(set (reg:CC_NOOV CC_REGNUM)
1105         (compare:CC_NOOV (mult:SI
1106                           (match_operand:SI 2 "s_register_operand" "r,r")
1107                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1108                          (const_int 0)))
1109    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1110         (mult:SI (match_dup 2) (match_dup 1)))]
1111   "TARGET_ARM"
1112   "mul%?s\\t%0, %2, %1"
1113   [(set_attr "conds" "set")
1114    (set_attr "insn" "muls")]
1115 )
1116
1117 (define_insn "*mulsi_compare0_scratch"
1118   [(set (reg:CC_NOOV CC_REGNUM)
1119         (compare:CC_NOOV (mult:SI
1120                           (match_operand:SI 2 "s_register_operand" "r,r")
1121                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1122                          (const_int 0)))
1123    (clobber (match_scratch:SI 0 "=&r,&r"))]
1124   "TARGET_ARM"
1125   "mul%?s\\t%0, %2, %1"
1126   [(set_attr "conds" "set")
1127    (set_attr "insn" "muls")]
1128 )
1129
1130 ;; Unnamed templates to match MLA instruction.
1131
1132 (define_insn "*mulsi3addsi"
1133   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1134         (plus:SI
1135           (mult:SI (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   "TARGET_ARM"
1139   "mla%?\\t%0, %2, %1, %3"
1140   [(set_attr "insn" "mla")
1141    (set_attr "predicable" "yes")]
1142 )
1143
1144 (define_insn "*mulsi3addsi_compare0"
1145   [(set (reg:CC_NOOV CC_REGNUM)
1146         (compare:CC_NOOV
1147          (plus:SI (mult:SI
1148                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1149                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1150                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1151          (const_int 0)))
1152    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1153         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1154                  (match_dup 3)))]
1155   "TARGET_ARM"
1156   "mla%?s\\t%0, %2, %1, %3"
1157   [(set_attr "conds" "set")
1158    (set_attr "insn" "mlas")]
1159 )
1160
1161 (define_insn "*mulsi3addsi_compare0_scratch"
1162   [(set (reg:CC_NOOV CC_REGNUM)
1163         (compare:CC_NOOV
1164          (plus:SI (mult:SI
1165                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1166                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1167                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1168          (const_int 0)))
1169    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1170   "TARGET_ARM"
1171   "mla%?s\\t%0, %2, %1, %3"
1172   [(set_attr "conds" "set")
1173    (set_attr "insn" "mlas")]
1174 )
1175
1176 ;; Unnamed template to match long long multiply-accumulate (smlal)
1177
1178 (define_insn "*mulsidi3adddi"
1179   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1180         (plus:DI
1181          (mult:DI
1182           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1183           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1184          (match_operand:DI 1 "s_register_operand" "0")))]
1185   "TARGET_ARM && arm_arch3m"
1186   "smlal%?\\t%Q0, %R0, %3, %2"
1187   [(set_attr "insn" "smlal")
1188    (set_attr "predicable" "yes")]
1189 )
1190
1191 (define_insn "mulsidi3"
1192   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1193         (mult:DI
1194          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196   "TARGET_ARM && arm_arch3m"
1197   "smull%?\\t%Q0, %R0, %1, %2"
1198   [(set_attr "insn" "smull")
1199    (set_attr "predicable" "yes")]
1200 )
1201
1202 (define_insn "umulsidi3"
1203   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1204         (mult:DI
1205          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1206          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1207   "TARGET_ARM && arm_arch3m"
1208   "umull%?\\t%Q0, %R0, %1, %2"
1209   [(set_attr "insn" "umull")
1210    (set_attr "predicable" "yes")]
1211 )
1212
1213 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1214
1215 (define_insn "*umulsidi3adddi"
1216   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1217         (plus:DI
1218          (mult:DI
1219           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1220           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1221          (match_operand:DI 1 "s_register_operand" "0")))]
1222   "TARGET_ARM && arm_arch3m"
1223   "umlal%?\\t%Q0, %R0, %3, %2"
1224   [(set_attr "insn" "umlal")
1225    (set_attr "predicable" "yes")]
1226 )
1227
1228 (define_insn "smulsi3_highpart"
1229   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230         (truncate:SI
1231          (lshiftrt:DI
1232           (mult:DI
1233            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1235           (const_int 32))))
1236    (clobber (match_scratch:SI 3 "=&r,&r"))]
1237   "TARGET_ARM && arm_arch3m"
1238   "smull%?\\t%3, %0, %2, %1"
1239   [(set_attr "insn" "smull")
1240    (set_attr "predicable" "yes")]
1241 )
1242
1243 (define_insn "umulsi3_highpart"
1244   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1245         (truncate:SI
1246          (lshiftrt:DI
1247           (mult:DI
1248            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1249            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1250           (const_int 32))))
1251    (clobber (match_scratch:SI 3 "=&r,&r"))]
1252   "TARGET_ARM && arm_arch3m"
1253   "umull%?\\t%3, %0, %2, %1"
1254   [(set_attr "insn" "umull")
1255    (set_attr "predicable" "yes")]
1256 )
1257
1258 (define_insn "mulhisi3"
1259   [(set (match_operand:SI 0 "s_register_operand" "=r")
1260         (mult:SI (sign_extend:SI
1261                   (match_operand:HI 1 "s_register_operand" "%r"))
1262                  (sign_extend:SI
1263                   (match_operand:HI 2 "s_register_operand" "r"))))]
1264   "TARGET_ARM && arm_arch5e"
1265   "smulbb%?\\t%0, %1, %2"
1266   [(set_attr "insn" "smulxy")
1267    (set_attr "predicable" "yes")]
1268 )
1269
1270 (define_insn "*mulhisi3tb"
1271   [(set (match_operand:SI 0 "s_register_operand" "=r")
1272         (mult:SI (ashiftrt:SI
1273                   (match_operand:SI 1 "s_register_operand" "r")
1274                   (const_int 16))
1275                  (sign_extend:SI
1276                   (match_operand:HI 2 "s_register_operand" "r"))))]
1277   "TARGET_ARM && arm_arch5e"
1278   "smultb%?\\t%0, %1, %2"
1279   [(set_attr "insn" "smulxy")
1280    (set_attr "predicable" "yes")]
1281 )
1282
1283 (define_insn "*mulhisi3bt"
1284   [(set (match_operand:SI 0 "s_register_operand" "=r")
1285         (mult:SI (sign_extend:SI
1286                   (match_operand:HI 1 "s_register_operand" "r"))
1287                  (ashiftrt:SI
1288                   (match_operand:SI 2 "s_register_operand" "r")
1289                   (const_int 16))))]
1290   "TARGET_ARM && arm_arch5e"
1291   "smulbt%?\\t%0, %1, %2"
1292   [(set_attr "insn" "smulxy")
1293    (set_attr "predicable" "yes")]
1294 )
1295
1296 (define_insn "*mulhisi3tt"
1297   [(set (match_operand:SI 0 "s_register_operand" "=r")
1298         (mult:SI (ashiftrt:SI
1299                   (match_operand:SI 1 "s_register_operand" "r")
1300                   (const_int 16))
1301                  (ashiftrt:SI
1302                   (match_operand:SI 2 "s_register_operand" "r")
1303                   (const_int 16))))]
1304   "TARGET_ARM && arm_arch5e"
1305   "smultt%?\\t%0, %1, %2"
1306   [(set_attr "insn" "smulxy")
1307    (set_attr "predicable" "yes")]
1308 )
1309
1310 (define_insn "*mulhisi3addsi"
1311   [(set (match_operand:SI 0 "s_register_operand" "=r")
1312         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1313                  (mult:SI (sign_extend:SI
1314                            (match_operand:HI 2 "s_register_operand" "%r"))
1315                           (sign_extend:SI
1316                            (match_operand:HI 3 "s_register_operand" "r")))))]
1317   "TARGET_ARM && arm_arch5e"
1318   "smlabb%?\\t%0, %2, %3, %1"
1319   [(set_attr "insn" "smlaxy")
1320    (set_attr "predicable" "yes")]
1321 )
1322
1323 (define_insn "*mulhidi3adddi"
1324   [(set (match_operand:DI 0 "s_register_operand" "=r")
1325         (plus:DI
1326           (match_operand:DI 1 "s_register_operand" "0")
1327           (mult:DI (sign_extend:DI
1328                     (match_operand:HI 2 "s_register_operand" "%r"))
1329                    (sign_extend:DI
1330                     (match_operand:HI 3 "s_register_operand" "r")))))]
1331   "TARGET_ARM && arm_arch5e"
1332   "smlalbb%?\\t%Q0, %R0, %2, %3"
1333   [(set_attr "insn" "smlalxy")
1334    (set_attr "predicable" "yes")])
1335
1336 (define_expand "mulsf3"
1337   [(set (match_operand:SF          0 "s_register_operand" "")
1338         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1339                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1340   "TARGET_ARM && TARGET_HARD_FLOAT"
1341   "
1342   if (TARGET_MAVERICK
1343       && !cirrus_fp_register (operands[2], SFmode))
1344     operands[2] = force_reg (SFmode, operands[2]);
1345 ")
1346
1347 (define_expand "muldf3"
1348   [(set (match_operand:DF          0 "s_register_operand" "")
1349         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1350                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1351   "TARGET_ARM && TARGET_HARD_FLOAT"
1352   "
1353   if (TARGET_MAVERICK
1354       && !cirrus_fp_register (operands[2], DFmode))
1355     operands[2] = force_reg (DFmode, operands[2]);
1356 ")
1357 \f
1358 ;; Division insns
1359
1360 (define_expand "divsf3"
1361   [(set (match_operand:SF 0 "s_register_operand" "")
1362         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1363                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1364   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1365   "")
1366
1367 (define_expand "divdf3"
1368   [(set (match_operand:DF 0 "s_register_operand" "")
1369         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1370                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1371   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1372   "")
1373 \f
1374 ;; Modulo insns
1375
1376 (define_expand "modsf3"
1377   [(set (match_operand:SF 0 "s_register_operand" "")
1378         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1379                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1380   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1381   "")
1382
1383 (define_expand "moddf3"
1384   [(set (match_operand:DF 0 "s_register_operand" "")
1385         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1386                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1387   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1388   "")
1389 \f
1390 ;; Boolean and,ior,xor insns
1391
1392 ;; Split up double word logical operations
1393
1394 ;; Split up simple DImode logical operations.  Simply perform the logical
1395 ;; operation on the upper and lower halves of the registers.
1396 (define_split
1397   [(set (match_operand:DI 0 "s_register_operand" "")
1398         (match_operator:DI 6 "logical_binary_operator"
1399           [(match_operand:DI 1 "s_register_operand" "")
1400            (match_operand:DI 2 "s_register_operand" "")]))]
1401   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1402   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1403    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1404   "
1405   {
1406     operands[3] = gen_highpart (SImode, operands[0]);
1407     operands[0] = gen_lowpart (SImode, operands[0]);
1408     operands[4] = gen_highpart (SImode, operands[1]);
1409     operands[1] = gen_lowpart (SImode, operands[1]);
1410     operands[5] = gen_highpart (SImode, operands[2]);
1411     operands[2] = gen_lowpart (SImode, operands[2]);
1412   }"
1413 )
1414
1415 (define_split
1416   [(set (match_operand:DI 0 "s_register_operand" "")
1417         (match_operator:DI 6 "logical_binary_operator"
1418           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1419            (match_operand:DI 1 "s_register_operand" "")]))]
1420   "TARGET_ARM && reload_completed"
1421   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1422    (set (match_dup 3) (match_op_dup:SI 6
1423                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1424                          (match_dup 4)]))]
1425   "
1426   {
1427     operands[3] = gen_highpart (SImode, operands[0]);
1428     operands[0] = gen_lowpart (SImode, operands[0]);
1429     operands[4] = gen_highpart (SImode, operands[1]);
1430     operands[1] = gen_lowpart (SImode, operands[1]);
1431     operands[5] = gen_highpart (SImode, operands[2]);
1432     operands[2] = gen_lowpart (SImode, operands[2]);
1433   }"
1434 )
1435
1436 ;; The zero extend of operand 2 means we can just copy the high part of
1437 ;; operand1 into operand0.
1438 (define_split
1439   [(set (match_operand:DI 0 "s_register_operand" "")
1440         (ior:DI
1441           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1442           (match_operand:DI 1 "s_register_operand" "")))]
1443   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1444   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1445    (set (match_dup 3) (match_dup 4))]
1446   "
1447   {
1448     operands[4] = gen_highpart (SImode, operands[1]);
1449     operands[3] = gen_highpart (SImode, operands[0]);
1450     operands[0] = gen_lowpart (SImode, operands[0]);
1451     operands[1] = gen_lowpart (SImode, operands[1]);
1452   }"
1453 )
1454
1455 ;; The zero extend of operand 2 means we can just copy the high part of
1456 ;; operand1 into operand0.
1457 (define_split
1458   [(set (match_operand:DI 0 "s_register_operand" "")
1459         (xor:DI
1460           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1461           (match_operand:DI 1 "s_register_operand" "")))]
1462   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1463   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1464    (set (match_dup 3) (match_dup 4))]
1465   "
1466   {
1467     operands[4] = gen_highpart (SImode, operands[1]);
1468     operands[3] = gen_highpart (SImode, operands[0]);
1469     operands[0] = gen_lowpart (SImode, operands[0]);
1470     operands[1] = gen_lowpart (SImode, operands[1]);
1471   }"
1472 )
1473
1474 (define_insn "anddi3"
1475   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1476         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1477                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1478   "TARGET_ARM && ! TARGET_IWMMXT"
1479   "#"
1480   [(set_attr "length" "8")]
1481 )
1482
1483 (define_insn_and_split "*anddi_zesidi_di"
1484   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1485         (and:DI (zero_extend:DI
1486                  (match_operand:SI 2 "s_register_operand" "r,r"))
1487                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1488   "TARGET_ARM"
1489   "#"
1490   "TARGET_ARM && reload_completed"
1491   ; The zero extend of operand 2 clears the high word of the output
1492   ; operand.
1493   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1494    (set (match_dup 3) (const_int 0))]
1495   "
1496   {
1497     operands[3] = gen_highpart (SImode, operands[0]);
1498     operands[0] = gen_lowpart (SImode, operands[0]);
1499     operands[1] = gen_lowpart (SImode, operands[1]);
1500   }"
1501   [(set_attr "length" "8")]
1502 )
1503
1504 (define_insn "*anddi_sesdi_di"
1505   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1506         (and:DI (sign_extend:DI
1507                  (match_operand:SI 2 "s_register_operand" "r,r"))
1508                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1509   "TARGET_ARM"
1510   "#"
1511   [(set_attr "length" "8")]
1512 )
1513
1514 (define_expand "andsi3"
1515   [(set (match_operand:SI         0 "s_register_operand" "")
1516         (and:SI (match_operand:SI 1 "s_register_operand" "")
1517                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1518   "TARGET_EITHER"
1519   "
1520   if (TARGET_ARM)
1521     {
1522       if (GET_CODE (operands[2]) == CONST_INT)
1523         {
1524           arm_split_constant (AND, SImode, NULL_RTX,
1525                               INTVAL (operands[2]), operands[0],
1526                               operands[1], optimize && !no_new_pseudos);
1527
1528           DONE;
1529         }
1530     }
1531   else /* TARGET_THUMB */
1532     {
1533       if (GET_CODE (operands[2]) != CONST_INT)
1534         operands[2] = force_reg (SImode, operands[2]);
1535       else
1536         {
1537           int i;
1538           
1539           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1540             {
1541               operands[2] = force_reg (SImode,
1542                                        GEN_INT (~INTVAL (operands[2])));
1543               
1544               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1545               
1546               DONE;
1547             }
1548
1549           for (i = 9; i <= 31; i++)
1550             {
1551               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1552                 {
1553                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1554                                         const0_rtx));
1555                   DONE;
1556                 }
1557               else if ((((HOST_WIDE_INT) 1) << i) - 1
1558                        == ~INTVAL (operands[2]))
1559                 {
1560                   rtx shift = GEN_INT (i);
1561                   rtx reg = gen_reg_rtx (SImode);
1562                 
1563                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1564                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1565                   
1566                   DONE;
1567                 }
1568             }
1569
1570           operands[2] = force_reg (SImode, operands[2]);
1571         }
1572     }
1573   "
1574 )
1575
1576 (define_insn_and_split "*arm_andsi3_insn"
1577   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1578         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1579                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1580   "TARGET_ARM"
1581   "@
1582    and%?\\t%0, %1, %2
1583    bic%?\\t%0, %1, #%B2
1584    #"
1585   "TARGET_ARM
1586    && GET_CODE (operands[2]) == CONST_INT
1587    && !(const_ok_for_arm (INTVAL (operands[2]))
1588         || const_ok_for_arm (~INTVAL (operands[2])))"
1589   [(clobber (const_int 0))]
1590   "
1591   arm_split_constant  (AND, SImode, curr_insn, 
1592                        INTVAL (operands[2]), operands[0], operands[1], 0);
1593   DONE;
1594   "
1595   [(set_attr "length" "4,4,16")
1596    (set_attr "predicable" "yes")]
1597 )
1598
1599 (define_insn "*thumb_andsi3_insn"
1600   [(set (match_operand:SI         0 "register_operand" "=l")
1601         (and:SI (match_operand:SI 1 "register_operand" "%0")
1602                 (match_operand:SI 2 "register_operand" "l")))]
1603   "TARGET_THUMB"
1604   "and\\t%0, %0, %2"
1605   [(set_attr "length" "2")]
1606 )
1607
1608 (define_insn "*andsi3_compare0"
1609   [(set (reg:CC_NOOV CC_REGNUM)
1610         (compare:CC_NOOV
1611          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1612                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1613          (const_int 0)))
1614    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1615         (and:SI (match_dup 1) (match_dup 2)))]
1616   "TARGET_ARM"
1617   "@
1618    and%?s\\t%0, %1, %2
1619    bic%?s\\t%0, %1, #%B2"
1620   [(set_attr "conds" "set")]
1621 )
1622
1623 (define_insn "*andsi3_compare0_scratch"
1624   [(set (reg:CC_NOOV CC_REGNUM)
1625         (compare:CC_NOOV
1626          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1627                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1628          (const_int 0)))
1629    (clobber (match_scratch:SI 2 "=X,r"))]
1630   "TARGET_ARM"
1631   "@
1632    tst%?\\t%0, %1
1633    bic%?s\\t%2, %0, #%B1"
1634   [(set_attr "conds" "set")]
1635 )
1636
1637 (define_insn "*zeroextractsi_compare0_scratch"
1638   [(set (reg:CC_NOOV CC_REGNUM)
1639         (compare:CC_NOOV (zero_extract:SI
1640                           (match_operand:SI 0 "s_register_operand" "r")
1641                           (match_operand 1 "const_int_operand" "n")
1642                           (match_operand 2 "const_int_operand" "n"))
1643                          (const_int 0)))]
1644   "TARGET_ARM
1645   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1646       && INTVAL (operands[1]) > 0 
1647       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1648       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1649   "*
1650   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1651                          << INTVAL (operands[2]));
1652   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1653   return \"\";
1654   "
1655   [(set_attr "conds" "set")]
1656 )
1657
1658 (define_insn_and_split "*ne_zeroextractsi"
1659   [(set (match_operand:SI 0 "s_register_operand" "=r")
1660         (ne:SI (zero_extract:SI
1661                 (match_operand:SI 1 "s_register_operand" "r")
1662                 (match_operand:SI 2 "const_int_operand" "n")
1663                 (match_operand:SI 3 "const_int_operand" "n"))
1664                (const_int 0)))
1665    (clobber (reg:CC CC_REGNUM))]
1666   "TARGET_ARM
1667    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1668        && INTVAL (operands[2]) > 0 
1669        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1670        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1671   "#"
1672   "TARGET_ARM
1673    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1674        && INTVAL (operands[2]) > 0 
1675        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1676        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1677   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1678                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1679                                     (const_int 0)))
1680               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1681    (set (match_dup 0)
1682         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1683                          (match_dup 0) (const_int 1)))]
1684   "
1685   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1686                          << INTVAL (operands[3])); 
1687   "
1688   [(set_attr "conds" "clob")
1689    (set_attr "length" "8")]
1690 )
1691
1692 (define_insn_and_split "*ne_zeroextractsi_shifted"
1693   [(set (match_operand:SI 0 "s_register_operand" "=r")
1694         (ne:SI (zero_extract:SI
1695                 (match_operand:SI 1 "s_register_operand" "r")
1696                 (match_operand:SI 2 "const_int_operand" "n")
1697                 (const_int 0))
1698                (const_int 0)))
1699    (clobber (reg:CC CC_REGNUM))]
1700   "TARGET_ARM"
1701   "#"
1702   "TARGET_ARM"
1703   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1704                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1705                                     (const_int 0)))
1706               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1707    (set (match_dup 0)
1708         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1709                          (match_dup 0) (const_int 1)))]
1710   "
1711   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1712   "
1713   [(set_attr "conds" "clob")
1714    (set_attr "length" "8")]
1715 )
1716
1717 (define_insn_and_split "*ite_ne_zeroextractsi"
1718   [(set (match_operand:SI 0 "s_register_operand" "=r")
1719         (if_then_else:SI (ne (zero_extract:SI
1720                               (match_operand:SI 1 "s_register_operand" "r")
1721                               (match_operand:SI 2 "const_int_operand" "n")
1722                               (match_operand:SI 3 "const_int_operand" "n"))
1723                              (const_int 0))
1724                          (match_operand:SI 4 "arm_not_operand" "rIK")
1725                          (const_int 0)))
1726    (clobber (reg:CC CC_REGNUM))]
1727   "TARGET_ARM
1728    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1729        && INTVAL (operands[2]) > 0 
1730        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1731        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1732    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1733   "#"
1734   "TARGET_ARM
1735    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1736        && INTVAL (operands[2]) > 0 
1737        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1738        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1739    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1740   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1741                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1742                                     (const_int 0)))
1743               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1744    (set (match_dup 0)
1745         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1746                          (match_dup 0) (match_dup 4)))]
1747   "
1748   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1749                          << INTVAL (operands[3])); 
1750   "
1751   [(set_attr "conds" "clob")
1752    (set_attr "length" "8")]
1753 )
1754
1755 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1756   [(set (match_operand:SI 0 "s_register_operand" "=r")
1757         (if_then_else:SI (ne (zero_extract:SI
1758                               (match_operand:SI 1 "s_register_operand" "r")
1759                               (match_operand:SI 2 "const_int_operand" "n")
1760                               (const_int 0))
1761                              (const_int 0))
1762                          (match_operand:SI 3 "arm_not_operand" "rIK")
1763                          (const_int 0)))
1764    (clobber (reg:CC CC_REGNUM))]
1765   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1766   "#"
1767   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1768   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1769                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1770                                     (const_int 0)))
1771               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1772    (set (match_dup 0)
1773         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1774                          (match_dup 0) (match_dup 3)))]
1775   "
1776   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1777   "
1778   [(set_attr "conds" "clob")
1779    (set_attr "length" "8")]
1780 )
1781
1782 (define_split
1783   [(set (match_operand:SI 0 "s_register_operand" "")
1784         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1785                          (match_operand:SI 2 "const_int_operand" "")
1786                          (match_operand:SI 3 "const_int_operand" "")))
1787    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1788   "TARGET_THUMB"
1789   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1790    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1791   "{
1792      HOST_WIDE_INT temp = INTVAL (operands[2]);
1793
1794      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1795      operands[3] = GEN_INT (32 - temp);
1796    }"
1797 )
1798
1799 (define_split
1800   [(set (match_operand:SI 0 "s_register_operand" "")
1801         (match_operator:SI 1 "shiftable_operator"
1802          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1803                            (match_operand:SI 3 "const_int_operand" "")
1804                            (match_operand:SI 4 "const_int_operand" ""))
1805           (match_operand:SI 5 "s_register_operand" "")]))
1806    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1807   "TARGET_ARM"
1808   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1809    (set (match_dup 0)
1810         (match_op_dup 1
1811          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1812           (match_dup 5)]))]
1813   "{
1814      HOST_WIDE_INT temp = INTVAL (operands[3]);
1815
1816      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1817      operands[4] = GEN_INT (32 - temp);
1818    }"
1819 )
1820   
1821 (define_split
1822   [(set (match_operand:SI 0 "s_register_operand" "")
1823         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1824                          (match_operand:SI 2 "const_int_operand" "")
1825                          (match_operand:SI 3 "const_int_operand" "")))]
1826   "TARGET_THUMB"
1827   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1828    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1829   "{
1830      HOST_WIDE_INT temp = INTVAL (operands[2]);
1831
1832      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1833      operands[3] = GEN_INT (32 - temp);
1834    }"
1835 )
1836
1837 (define_split
1838   [(set (match_operand:SI 0 "s_register_operand" "")
1839         (match_operator:SI 1 "shiftable_operator"
1840          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1841                            (match_operand:SI 3 "const_int_operand" "")
1842                            (match_operand:SI 4 "const_int_operand" ""))
1843           (match_operand:SI 5 "s_register_operand" "")]))
1844    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1845   "TARGET_ARM"
1846   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1847    (set (match_dup 0)
1848         (match_op_dup 1
1849          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1850           (match_dup 5)]))]
1851   "{
1852      HOST_WIDE_INT temp = INTVAL (operands[3]);
1853
1854      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1855      operands[4] = GEN_INT (32 - temp);
1856    }"
1857 )
1858   
1859 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1860 ;;; represented by the bitfield, then this will produce incorrect results.
1861 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1862 ;;; which have a real bit-field insert instruction, the truncation happens
1863 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1864 ;;; bit-field insert instruction, we would have to emit code here to truncate
1865 ;;; the value before we insert.  This loses some of the advantage of having
1866 ;;; this insv pattern, so this pattern needs to be reevalutated.
1867
1868 (define_expand "insv"
1869   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1870                          (match_operand:SI 1 "general_operand" "")
1871                          (match_operand:SI 2 "general_operand" ""))
1872         (match_operand:SI 3 "reg_or_int_operand" ""))]
1873   "TARGET_ARM"
1874   "
1875   {
1876     int start_bit = INTVAL (operands[2]);
1877     int width = INTVAL (operands[1]);
1878     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1879     rtx target, subtarget;
1880
1881     target = operands[0];
1882     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1883        subreg as the final target.  */
1884     if (GET_CODE (target) == SUBREG)
1885       {
1886         subtarget = gen_reg_rtx (SImode);
1887         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1888             < GET_MODE_SIZE (SImode))
1889           target = SUBREG_REG (target);
1890       }
1891     else
1892       subtarget = target;    
1893
1894     if (GET_CODE (operands[3]) == CONST_INT)
1895       {
1896         /* Since we are inserting a known constant, we may be able to
1897            reduce the number of bits that we have to clear so that
1898            the mask becomes simple.  */
1899         /* ??? This code does not check to see if the new mask is actually
1900            simpler.  It may not be.  */
1901         rtx op1 = gen_reg_rtx (SImode);
1902         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1903            start of this pattern.  */
1904         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1905         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1906
1907         emit_insn (gen_andsi3 (op1, operands[0],
1908                                gen_int_mode (~mask2, SImode)));
1909         emit_insn (gen_iorsi3 (subtarget, op1,
1910                                gen_int_mode (op3_value << start_bit, SImode)));
1911       }
1912     else if (start_bit == 0
1913              && !(const_ok_for_arm (mask)
1914                   || const_ok_for_arm (~mask)))
1915       {
1916         /* A Trick, since we are setting the bottom bits in the word,
1917            we can shift operand[3] up, operand[0] down, OR them together
1918            and rotate the result back again.  This takes 3 insns, and
1919            the third might be mergeable into another op.  */
1920         /* The shift up copes with the possibility that operand[3] is
1921            wider than the bitfield.  */
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_lshrsi3 (op1, operands[0], operands[1]));
1927         emit_insn (gen_iorsi3  (op1, op1, op0));
1928         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1929       }
1930     else if ((width + start_bit == 32)
1931              && !(const_ok_for_arm (mask)
1932                   || const_ok_for_arm (~mask)))
1933       {
1934         /* Similar trick, but slightly less efficient.  */
1935
1936         rtx op0 = gen_reg_rtx (SImode);
1937         rtx op1 = gen_reg_rtx (SImode);
1938
1939         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1940         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1941         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1942         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1943       }
1944     else
1945       {
1946         rtx op0 = gen_int_mode (mask, SImode);
1947         rtx op1 = gen_reg_rtx (SImode);
1948         rtx op2 = gen_reg_rtx (SImode);
1949
1950         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1951           {
1952             rtx tmp = gen_reg_rtx (SImode);
1953
1954             emit_insn (gen_movsi (tmp, op0));
1955             op0 = tmp;
1956           }
1957
1958         /* Mask out any bits in operand[3] that are not needed.  */
1959            emit_insn (gen_andsi3 (op1, operands[3], op0));
1960
1961         if (GET_CODE (op0) == CONST_INT
1962             && (const_ok_for_arm (mask << start_bit)
1963                 || const_ok_for_arm (~(mask << start_bit))))
1964           {
1965             op0 = gen_int_mode (~(mask << start_bit), SImode);
1966             emit_insn (gen_andsi3 (op2, operands[0], op0));
1967           }
1968         else
1969           {
1970             if (GET_CODE (op0) == CONST_INT)
1971               {
1972                 rtx tmp = gen_reg_rtx (SImode);
1973
1974                 emit_insn (gen_movsi (tmp, op0));
1975                 op0 = tmp;
1976               }
1977
1978             if (start_bit != 0)
1979               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1980             
1981             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1982           }
1983
1984         if (start_bit != 0)
1985           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1986
1987         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1988       }
1989
1990     if (subtarget != target)
1991       {
1992         /* If TARGET is still a SUBREG, then it must be wider than a word,
1993            so we must be careful only to set the subword we were asked to.  */
1994         if (GET_CODE (target) == SUBREG)
1995           emit_move_insn (target, subtarget);
1996         else
1997           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1998       }
1999
2000     DONE;
2001   }"
2002 )
2003
2004 ; constants for op 2 will never be given to these patterns.
2005 (define_insn_and_split "*anddi_notdi_di"
2006   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2007         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2008                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2009   "TARGET_ARM"
2010   "#"
2011   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2012   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2013    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2014   "
2015   {
2016     operands[3] = gen_highpart (SImode, operands[0]);
2017     operands[0] = gen_lowpart (SImode, operands[0]);
2018     operands[4] = gen_highpart (SImode, operands[1]);
2019     operands[1] = gen_lowpart (SImode, operands[1]);
2020     operands[5] = gen_highpart (SImode, operands[2]);
2021     operands[2] = gen_lowpart (SImode, operands[2]);
2022   }"
2023   [(set_attr "length" "8")
2024    (set_attr "predicable" "yes")]
2025 )
2026   
2027 (define_insn_and_split "*anddi_notzesidi_di"
2028   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2029         (and:DI (not:DI (zero_extend:DI
2030                          (match_operand:SI 2 "s_register_operand" "r,r")))
2031                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2032   "TARGET_ARM"
2033   "@
2034    bic%?\\t%Q0, %Q1, %2
2035    #"
2036   ; (not (zero_extend ...)) allows us to just copy the high word from
2037   ; operand1 to operand0.
2038   "TARGET_ARM
2039    && reload_completed
2040    && operands[0] != operands[1]"
2041   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2042    (set (match_dup 3) (match_dup 4))]
2043   "
2044   {
2045     operands[3] = gen_highpart (SImode, operands[0]);
2046     operands[0] = gen_lowpart (SImode, operands[0]);
2047     operands[4] = gen_highpart (SImode, operands[1]);
2048     operands[1] = gen_lowpart (SImode, operands[1]);
2049   }"
2050   [(set_attr "length" "4,8")
2051    (set_attr "predicable" "yes")]
2052 )
2053   
2054 (define_insn_and_split "*anddi_notsesidi_di"
2055   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056         (and:DI (not:DI (sign_extend:DI
2057                          (match_operand:SI 2 "s_register_operand" "r,r")))
2058                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2059   "TARGET_ARM"
2060   "#"
2061   "TARGET_ARM && reload_completed"
2062   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2063    (set (match_dup 3) (and:SI (not:SI
2064                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2065                                (match_dup 4)))]
2066   "
2067   {
2068     operands[3] = gen_highpart (SImode, operands[0]);
2069     operands[0] = gen_lowpart (SImode, operands[0]);
2070     operands[4] = gen_highpart (SImode, operands[1]);
2071     operands[1] = gen_lowpart (SImode, operands[1]);
2072   }"
2073   [(set_attr "length" "8")
2074    (set_attr "predicable" "yes")]
2075 )
2076   
2077 (define_insn "andsi_notsi_si"
2078   [(set (match_operand:SI 0 "s_register_operand" "=r")
2079         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080                 (match_operand:SI 1 "s_register_operand" "r")))]
2081   "TARGET_ARM"
2082   "bic%?\\t%0, %1, %2"
2083   [(set_attr "predicable" "yes")]
2084 )
2085
2086 (define_insn "bicsi3"
2087   [(set (match_operand:SI                 0 "register_operand" "=l")
2088         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2089                 (match_operand:SI         2 "register_operand" "0")))]
2090   "TARGET_THUMB"
2091   "bic\\t%0, %0, %1"
2092   [(set_attr "length" "2")]
2093 )
2094
2095 (define_insn "andsi_not_shiftsi_si"
2096   [(set (match_operand:SI 0 "s_register_operand" "=r")
2097         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2098                          [(match_operand:SI 2 "s_register_operand" "r")
2099                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2100                 (match_operand:SI 1 "s_register_operand" "r")))]
2101   "TARGET_ARM"
2102   "bic%?\\t%0, %1, %2%S4"
2103   [(set_attr "predicable" "yes")
2104    (set_attr "shift" "2")
2105    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2106                       (const_string "alu_shift")
2107                       (const_string "alu_shift_reg")))]
2108 )
2109
2110 (define_insn "*andsi_notsi_si_compare0"
2111   [(set (reg:CC_NOOV CC_REGNUM)
2112         (compare:CC_NOOV
2113          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114                  (match_operand:SI 1 "s_register_operand" "r"))
2115          (const_int 0)))
2116    (set (match_operand:SI 0 "s_register_operand" "=r")
2117         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2118   "TARGET_ARM"
2119   "bic%?s\\t%0, %1, %2"
2120   [(set_attr "conds" "set")]
2121 )
2122
2123 (define_insn "*andsi_notsi_si_compare0_scratch"
2124   [(set (reg:CC_NOOV CC_REGNUM)
2125         (compare:CC_NOOV
2126          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2127                  (match_operand:SI 1 "s_register_operand" "r"))
2128          (const_int 0)))
2129    (clobber (match_scratch:SI 0 "=r"))]
2130   "TARGET_ARM"
2131   "bic%?s\\t%0, %1, %2"
2132   [(set_attr "conds" "set")]
2133 )
2134
2135 (define_insn "iordi3"
2136   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2137         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2138                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2139   "TARGET_ARM && ! TARGET_IWMMXT"
2140   "#"
2141   [(set_attr "length" "8")
2142    (set_attr "predicable" "yes")]
2143 )
2144
2145 (define_insn "*iordi_zesidi_di"
2146   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147         (ior:DI (zero_extend:DI
2148                  (match_operand:SI 2 "s_register_operand" "r,r"))
2149                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2150   "TARGET_ARM"
2151   "@
2152    orr%?\\t%Q0, %Q1, %2
2153    #"
2154   [(set_attr "length" "4,8")
2155    (set_attr "predicable" "yes")]
2156 )
2157
2158 (define_insn "*iordi_sesidi_di"
2159   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160         (ior:DI (sign_extend:DI
2161                  (match_operand:SI 2 "s_register_operand" "r,r"))
2162                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2163   "TARGET_ARM"
2164   "#"
2165   [(set_attr "length" "8")
2166    (set_attr "predicable" "yes")]
2167 )
2168
2169 (define_expand "iorsi3"
2170   [(set (match_operand:SI         0 "s_register_operand" "")
2171         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2172                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2173   "TARGET_EITHER"
2174   "
2175   if (GET_CODE (operands[2]) == CONST_INT)
2176     {
2177       if (TARGET_ARM)
2178         {
2179           arm_split_constant (IOR, SImode, NULL_RTX,
2180                               INTVAL (operands[2]), operands[0], operands[1],
2181                               optimize && !no_new_pseudos);
2182           DONE;
2183         }
2184       else /* TARGET_THUMB */
2185         operands [2] = force_reg (SImode, operands [2]);
2186     }
2187   "
2188 )
2189
2190 (define_insn_and_split "*arm_iorsi3"
2191   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2192         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2193                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2194   "TARGET_ARM"
2195   "@
2196    orr%?\\t%0, %1, %2
2197    #"
2198   "TARGET_ARM
2199    && GET_CODE (operands[2]) == CONST_INT
2200    && !const_ok_for_arm (INTVAL (operands[2]))"
2201   [(clobber (const_int 0))]
2202   "
2203   arm_split_constant (IOR, SImode, curr_insn, 
2204                       INTVAL (operands[2]), operands[0], operands[1], 0);
2205   DONE;
2206   "
2207   [(set_attr "length" "4,16")
2208    (set_attr "predicable" "yes")]
2209 )
2210
2211 (define_insn "*thumb_iorsi3"
2212   [(set (match_operand:SI         0 "register_operand" "=l")
2213         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2214                 (match_operand:SI 2 "register_operand" "l")))]
2215   "TARGET_THUMB"
2216   "orr\\t%0, %0, %2"
2217   [(set_attr "length" "2")]
2218 )
2219
2220 (define_peephole2
2221   [(match_scratch:SI 3 "r")
2222    (set (match_operand:SI 0 "arm_general_register_operand" "")
2223         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2224                 (match_operand:SI 2 "const_int_operand" "")))]
2225   "TARGET_ARM
2226    && !const_ok_for_arm (INTVAL (operands[2]))
2227    && const_ok_for_arm (~INTVAL (operands[2]))"
2228   [(set (match_dup 3) (match_dup 2))
2229    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2230   ""
2231 )
2232
2233 (define_insn "*iorsi3_compare0"
2234   [(set (reg:CC_NOOV CC_REGNUM)
2235         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2237                          (const_int 0)))
2238    (set (match_operand:SI 0 "s_register_operand" "=r")
2239         (ior:SI (match_dup 1) (match_dup 2)))]
2240   "TARGET_ARM"
2241   "orr%?s\\t%0, %1, %2"
2242   [(set_attr "conds" "set")]
2243 )
2244
2245 (define_insn "*iorsi3_compare0_scratch"
2246   [(set (reg:CC_NOOV CC_REGNUM)
2247         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2248                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2249                          (const_int 0)))
2250    (clobber (match_scratch:SI 0 "=r"))]
2251   "TARGET_ARM"
2252   "orr%?s\\t%0, %1, %2"
2253   [(set_attr "conds" "set")]
2254 )
2255
2256 (define_insn "xordi3"
2257   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2258         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2259                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2260   "TARGET_ARM && !TARGET_IWMMXT"
2261   "#"
2262   [(set_attr "length" "8")
2263    (set_attr "predicable" "yes")]
2264 )
2265
2266 (define_insn "*xordi_zesidi_di"
2267   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2268         (xor:DI (zero_extend:DI
2269                  (match_operand:SI 2 "s_register_operand" "r,r"))
2270                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2271   "TARGET_ARM"
2272   "@
2273    eor%?\\t%Q0, %Q1, %2
2274    #"
2275   [(set_attr "length" "4,8")
2276    (set_attr "predicable" "yes")]
2277 )
2278
2279 (define_insn "*xordi_sesidi_di"
2280   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2281         (xor:DI (sign_extend:DI
2282                  (match_operand:SI 2 "s_register_operand" "r,r"))
2283                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2284   "TARGET_ARM"
2285   "#"
2286   [(set_attr "length" "8")
2287    (set_attr "predicable" "yes")]
2288 )
2289
2290 (define_expand "xorsi3"
2291   [(set (match_operand:SI         0 "s_register_operand" "")
2292         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2293                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2294   "TARGET_EITHER"
2295   "if (TARGET_THUMB)
2296      if (GET_CODE (operands[2]) == CONST_INT)
2297        operands[2] = force_reg (SImode, operands[2]);
2298   "
2299 )
2300
2301 (define_insn "*arm_xorsi3"
2302   [(set (match_operand:SI         0 "s_register_operand" "=r")
2303         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2304                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2305   "TARGET_ARM"
2306   "eor%?\\t%0, %1, %2"
2307   [(set_attr "predicable" "yes")]
2308 )
2309
2310 (define_insn "*thumb_xorsi3"
2311   [(set (match_operand:SI         0 "register_operand" "=l")
2312         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2313                 (match_operand:SI 2 "register_operand" "l")))]
2314   "TARGET_THUMB"
2315   "eor\\t%0, %0, %2"
2316   [(set_attr "length" "2")]
2317 )
2318
2319 (define_insn "*xorsi3_compare0"
2320   [(set (reg:CC_NOOV CC_REGNUM)
2321         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2322                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2323                          (const_int 0)))
2324    (set (match_operand:SI 0 "s_register_operand" "=r")
2325         (xor:SI (match_dup 1) (match_dup 2)))]
2326   "TARGET_ARM"
2327   "eor%?s\\t%0, %1, %2"
2328   [(set_attr "conds" "set")]
2329 )
2330
2331 (define_insn "*xorsi3_compare0_scratch"
2332   [(set (reg:CC_NOOV CC_REGNUM)
2333         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2334                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2335                          (const_int 0)))]
2336   "TARGET_ARM"
2337   "teq%?\\t%0, %1"
2338   [(set_attr "conds" "set")]
2339 )
2340
2341 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2342 ; (NOT D) we can sometimes merge the final NOT into one of the following
2343 ; insns.
2344
2345 (define_split
2346   [(set (match_operand:SI 0 "s_register_operand" "")
2347         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2348                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2349                 (match_operand:SI 3 "arm_rhs_operand" "")))
2350    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2351   "TARGET_ARM"
2352   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2353                               (not:SI (match_dup 3))))
2354    (set (match_dup 0) (not:SI (match_dup 4)))]
2355   ""
2356 )
2357
2358 (define_insn "*andsi_iorsi3_notsi"
2359   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2360         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2361                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2362                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2363   "TARGET_ARM"
2364   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2365   [(set_attr "length" "8")
2366    (set_attr "predicable" "yes")]
2367 )
2368
2369 (define_split
2370   [(set (match_operand:SI 0 "s_register_operand" "")
2371         (match_operator:SI 1 "logical_binary_operator"
2372          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2373                            (match_operand:SI 3 "const_int_operand" "")
2374                            (match_operand:SI 4 "const_int_operand" ""))
2375           (match_operator:SI 9 "logical_binary_operator"
2376            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2377                          (match_operand:SI 6 "const_int_operand" ""))
2378             (match_operand:SI 7 "s_register_operand" "")])]))
2379    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2380   "TARGET_ARM
2381    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2382    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2383   [(set (match_dup 8)
2384         (match_op_dup 1
2385          [(ashift:SI (match_dup 2) (match_dup 4))
2386           (match_dup 5)]))
2387    (set (match_dup 0)
2388         (match_op_dup 1
2389          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2390           (match_dup 7)]))]
2391   "
2392   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2393 ")
2394
2395 (define_split
2396   [(set (match_operand:SI 0 "s_register_operand" "")
2397         (match_operator:SI 1 "logical_binary_operator"
2398          [(match_operator:SI 9 "logical_binary_operator"
2399            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2400                          (match_operand:SI 6 "const_int_operand" ""))
2401             (match_operand:SI 7 "s_register_operand" "")])
2402           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2403                            (match_operand:SI 3 "const_int_operand" "")
2404                            (match_operand:SI 4 "const_int_operand" ""))]))
2405    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2406   "TARGET_ARM
2407    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2408    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2409   [(set (match_dup 8)
2410         (match_op_dup 1
2411          [(ashift:SI (match_dup 2) (match_dup 4))
2412           (match_dup 5)]))
2413    (set (match_dup 0)
2414         (match_op_dup 1
2415          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2416           (match_dup 7)]))]
2417   "
2418   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2419 ")
2420
2421 (define_split
2422   [(set (match_operand:SI 0 "s_register_operand" "")
2423         (match_operator:SI 1 "logical_binary_operator"
2424          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2425                            (match_operand:SI 3 "const_int_operand" "")
2426                            (match_operand:SI 4 "const_int_operand" ""))
2427           (match_operator:SI 9 "logical_binary_operator"
2428            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2429                          (match_operand:SI 6 "const_int_operand" ""))
2430             (match_operand:SI 7 "s_register_operand" "")])]))
2431    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2432   "TARGET_ARM
2433    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2434    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2435   [(set (match_dup 8)
2436         (match_op_dup 1
2437          [(ashift:SI (match_dup 2) (match_dup 4))
2438           (match_dup 5)]))
2439    (set (match_dup 0)
2440         (match_op_dup 1
2441          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2442           (match_dup 7)]))]
2443   "
2444   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2445 ")
2446
2447 (define_split
2448   [(set (match_operand:SI 0 "s_register_operand" "")
2449         (match_operator:SI 1 "logical_binary_operator"
2450          [(match_operator:SI 9 "logical_binary_operator"
2451            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2452                          (match_operand:SI 6 "const_int_operand" ""))
2453             (match_operand:SI 7 "s_register_operand" "")])
2454           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2455                            (match_operand:SI 3 "const_int_operand" "")
2456                            (match_operand:SI 4 "const_int_operand" ""))]))
2457    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2458   "TARGET_ARM
2459    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2460    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2461   [(set (match_dup 8)
2462         (match_op_dup 1
2463          [(ashift:SI (match_dup 2) (match_dup 4))
2464           (match_dup 5)]))
2465    (set (match_dup 0)
2466         (match_op_dup 1
2467          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2468           (match_dup 7)]))]
2469   "
2470   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2471 ")
2472 \f
2473
2474 ;; Minimum and maximum insns
2475
2476 (define_insn "smaxsi3"
2477   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2478         (smax: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\;movlt\\t%0, %2
2484    cmp\\t%1, %2\;movge\\t%0, %1
2485    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2486   [(set_attr "conds" "clob")
2487    (set_attr "length" "8,8,12")]
2488 )
2489
2490 (define_insn "sminsi3"
2491   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2492         (smin: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\;movge\\t%0, %2
2498    cmp\\t%1, %2\;movlt\\t%0, %1
2499    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2500   [(set_attr "conds" "clob")
2501    (set_attr "length" "8,8,12")]
2502 )
2503
2504 (define_insn "umaxsi3"
2505   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2506         (umax: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\;movcc\\t%0, %2
2512    cmp\\t%1, %2\;movcs\\t%0, %1
2513    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2514   [(set_attr "conds" "clob")
2515    (set_attr "length" "8,8,12")]
2516 )
2517
2518 (define_insn "uminsi3"
2519   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2520         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2521                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2522    (clobber (reg:CC CC_REGNUM))]
2523   "TARGET_ARM"
2524   "@
2525    cmp\\t%1, %2\;movcs\\t%0, %2
2526    cmp\\t%1, %2\;movcc\\t%0, %1
2527    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2528   [(set_attr "conds" "clob")
2529    (set_attr "length" "8,8,12")]
2530 )
2531
2532 (define_insn "*store_minmaxsi"
2533   [(set (match_operand:SI 0 "memory_operand" "=m")
2534         (match_operator:SI 3 "minmax_operator"
2535          [(match_operand:SI 1 "s_register_operand" "r")
2536           (match_operand:SI 2 "s_register_operand" "r")]))
2537    (clobber (reg:CC CC_REGNUM))]
2538   "TARGET_ARM"
2539   "*
2540   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2541                                 operands[1], operands[2]);
2542   output_asm_insn (\"cmp\\t%1, %2\", operands);
2543   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2544   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2545   return \"\";
2546   "
2547   [(set_attr "conds" "clob")
2548    (set_attr "length" "12")
2549    (set_attr "type" "store1")]
2550 )
2551
2552 ; Reject the frame pointer in operand[1], since reloading this after
2553 ; it has been eliminated can cause carnage.
2554 (define_insn "*minmax_arithsi"
2555   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2556         (match_operator:SI 4 "shiftable_operator"
2557          [(match_operator:SI 5 "minmax_operator"
2558            [(match_operand:SI 2 "s_register_operand" "r,r")
2559             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2560           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2561    (clobber (reg:CC CC_REGNUM))]
2562   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2563   "*
2564   {
2565     enum rtx_code code = GET_CODE (operands[4]);
2566
2567     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2568                                   operands[2], operands[3]);
2569     output_asm_insn (\"cmp\\t%2, %3\", operands);
2570     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2571     if (which_alternative != 0 || operands[3] != const0_rtx
2572         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2573       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2574     return \"\";
2575   }"
2576   [(set_attr "conds" "clob")
2577    (set_attr "length" "12")]
2578 )
2579
2580 \f
2581 ;; Shift and rotation insns
2582
2583 (define_expand "ashldi3"
2584   [(set (match_operand:DI            0 "s_register_operand" "")
2585         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2586                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2587   "TARGET_ARM"
2588   "
2589   if (GET_CODE (operands[2]) == CONST_INT)
2590     {
2591       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2592         {
2593           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2594           DONE;
2595         }
2596         /* Ideally we shouldn't fail here if we could know that operands[1] 
2597            ends up already living in an iwmmxt register. Otherwise it's
2598            cheaper to have the alternate code being generated than moving
2599            values to iwmmxt regs and back.  */
2600         FAIL;
2601     }
2602   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2603     FAIL;
2604   "
2605 )
2606
2607 (define_insn "arm_ashldi3_1bit"
2608   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2609         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2610                    (const_int 1)))
2611    (clobber (reg:CC CC_REGNUM))]
2612   "TARGET_ARM"
2613   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2614   [(set_attr "conds" "clob")
2615    (set_attr "length" "8")]
2616 )
2617
2618 (define_expand "ashlsi3"
2619   [(set (match_operand:SI            0 "s_register_operand" "")
2620         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2621                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2622   "TARGET_EITHER"
2623   "
2624   if (GET_CODE (operands[2]) == CONST_INT
2625       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2626     {
2627       emit_insn (gen_movsi (operands[0], const0_rtx));
2628       DONE;
2629     }
2630   "
2631 )
2632
2633 (define_insn "*thumb_ashlsi3"
2634   [(set (match_operand:SI            0 "register_operand" "=l,l")
2635         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2636                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2637   "TARGET_THUMB"
2638   "lsl\\t%0, %1, %2"
2639   [(set_attr "length" "2")]
2640 )
2641
2642 (define_expand "ashrdi3"
2643   [(set (match_operand:DI              0 "s_register_operand" "")
2644         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2645                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2646   "TARGET_ARM"
2647   "
2648   if (GET_CODE (operands[2]) == CONST_INT)
2649     {
2650       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2651         {
2652           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2653           DONE;
2654         }
2655         /* Ideally we shouldn't fail here if we could know that operands[1] 
2656            ends up already living in an iwmmxt register. Otherwise it's
2657            cheaper to have the alternate code being generated than moving
2658            values to iwmmxt regs and back.  */
2659         FAIL;
2660     }
2661   else if (!TARGET_REALLY_IWMMXT)
2662     FAIL;
2663   "
2664 )
2665
2666 (define_insn "arm_ashrdi3_1bit"
2667   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2668         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2669                      (const_int 1)))
2670    (clobber (reg:CC CC_REGNUM))]
2671   "TARGET_ARM"
2672   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2673   [(set_attr "conds" "clob")
2674    (set_attr "length" "8")]
2675 )
2676
2677 (define_expand "ashrsi3"
2678   [(set (match_operand:SI              0 "s_register_operand" "")
2679         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2680                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2681   "TARGET_EITHER"
2682   "
2683   if (GET_CODE (operands[2]) == CONST_INT
2684       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2685     operands[2] = GEN_INT (31);
2686   "
2687 )
2688
2689 (define_insn "*thumb_ashrsi3"
2690   [(set (match_operand:SI              0 "register_operand" "=l,l")
2691         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2692                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2693   "TARGET_THUMB"
2694   "asr\\t%0, %1, %2"
2695   [(set_attr "length" "2")]
2696 )
2697
2698 (define_expand "lshrdi3"
2699   [(set (match_operand:DI              0 "s_register_operand" "")
2700         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2701                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2702   "TARGET_ARM"
2703   "
2704   if (GET_CODE (operands[2]) == CONST_INT)
2705     {
2706       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2707         {
2708           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2709           DONE;
2710         }
2711         /* Ideally we shouldn't fail here if we could know that operands[1] 
2712            ends up already living in an iwmmxt register. Otherwise it's
2713            cheaper to have the alternate code being generated than moving
2714            values to iwmmxt regs and back.  */
2715         FAIL;
2716     }
2717   else if (!TARGET_REALLY_IWMMXT)
2718     FAIL;
2719   "
2720 )
2721
2722 (define_insn "arm_lshrdi3_1bit"
2723   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2724         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2725                      (const_int 1)))
2726    (clobber (reg:CC CC_REGNUM))]
2727   "TARGET_ARM"
2728   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2729   [(set_attr "conds" "clob")
2730    (set_attr "length" "8")]
2731 )
2732
2733 (define_expand "lshrsi3"
2734   [(set (match_operand:SI              0 "s_register_operand" "")
2735         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2736                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2737   "TARGET_EITHER"
2738   "
2739   if (GET_CODE (operands[2]) == CONST_INT
2740       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2741     {
2742       emit_insn (gen_movsi (operands[0], const0_rtx));
2743       DONE;
2744     }
2745   "
2746 )
2747
2748 (define_insn "*thumb_lshrsi3"
2749   [(set (match_operand:SI              0 "register_operand" "=l,l")
2750         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2751                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2752   "TARGET_THUMB"
2753   "lsr\\t%0, %1, %2"
2754   [(set_attr "length" "2")]
2755 )
2756
2757 (define_expand "rotlsi3"
2758   [(set (match_operand:SI              0 "s_register_operand" "")
2759         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2760                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2761   "TARGET_ARM"
2762   "
2763   if (GET_CODE (operands[2]) == CONST_INT)
2764     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2765   else
2766     {
2767       rtx reg = gen_reg_rtx (SImode);
2768       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2769       operands[2] = reg;
2770     }
2771   "
2772 )
2773
2774 (define_expand "rotrsi3"
2775   [(set (match_operand:SI              0 "s_register_operand" "")
2776         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2777                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2778   "TARGET_EITHER"
2779   "
2780   if (TARGET_ARM)
2781     {
2782       if (GET_CODE (operands[2]) == CONST_INT
2783           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2784         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2785     }
2786   else /* TARGET_THUMB */
2787     {
2788       if (GET_CODE (operands [2]) == CONST_INT)
2789         operands [2] = force_reg (SImode, operands[2]);
2790     }
2791   "
2792 )
2793
2794 (define_insn "*thumb_rotrsi3"
2795   [(set (match_operand:SI              0 "register_operand" "=l")
2796         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2797                      (match_operand:SI 2 "register_operand" "l")))]
2798   "TARGET_THUMB"
2799   "ror\\t%0, %0, %2"
2800   [(set_attr "length" "2")]
2801 )
2802
2803 (define_insn "*arm_shiftsi3"
2804   [(set (match_operand:SI   0 "s_register_operand" "=r")
2805         (match_operator:SI  3 "shift_operator"
2806          [(match_operand:SI 1 "s_register_operand"  "r")
2807           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2808   "TARGET_ARM"
2809   "mov%?\\t%0, %1%S3"
2810   [(set_attr "predicable" "yes")
2811    (set_attr "shift" "1")
2812    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2813                       (const_string "alu_shift")
2814                       (const_string "alu_shift_reg")))]
2815 )
2816
2817 (define_insn "*shiftsi3_compare0"
2818   [(set (reg:CC_NOOV CC_REGNUM)
2819         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2820                           [(match_operand:SI 1 "s_register_operand" "r")
2821                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2822                          (const_int 0)))
2823    (set (match_operand:SI 0 "s_register_operand" "=r")
2824         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2825   "TARGET_ARM"
2826   "mov%?s\\t%0, %1%S3"
2827   [(set_attr "conds" "set")
2828    (set_attr "shift" "1")
2829    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2830                       (const_string "alu_shift")
2831                       (const_string "alu_shift_reg")))]
2832 )
2833
2834 (define_insn "*shiftsi3_compare0_scratch"
2835   [(set (reg:CC_NOOV CC_REGNUM)
2836         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2837                           [(match_operand:SI 1 "s_register_operand" "r")
2838                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2839                          (const_int 0)))
2840    (clobber (match_scratch:SI 0 "=r"))]
2841   "TARGET_ARM"
2842   "mov%?s\\t%0, %1%S3"
2843   [(set_attr "conds" "set")
2844    (set_attr "shift" "1")]
2845 )
2846
2847 (define_insn "*notsi_shiftsi"
2848   [(set (match_operand:SI 0 "s_register_operand" "=r")
2849         (not:SI (match_operator:SI 3 "shift_operator"
2850                  [(match_operand:SI 1 "s_register_operand" "r")
2851                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2852   "TARGET_ARM"
2853   "mvn%?\\t%0, %1%S3"
2854   [(set_attr "predicable" "yes")
2855    (set_attr "shift" "1")
2856    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2857                       (const_string "alu_shift")
2858                       (const_string "alu_shift_reg")))]
2859 )
2860
2861 (define_insn "*notsi_shiftsi_compare0"
2862   [(set (reg:CC_NOOV CC_REGNUM)
2863         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2864                           [(match_operand:SI 1 "s_register_operand" "r")
2865                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2866                          (const_int 0)))
2867    (set (match_operand:SI 0 "s_register_operand" "=r")
2868         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2869   "TARGET_ARM"
2870   "mvn%?s\\t%0, %1%S3"
2871   [(set_attr "conds" "set")
2872    (set_attr "shift" "1")
2873    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874                       (const_string "alu_shift")
2875                       (const_string "alu_shift_reg")))]
2876 )
2877
2878 (define_insn "*not_shiftsi_compare0_scratch"
2879   [(set (reg:CC_NOOV CC_REGNUM)
2880         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2881                           [(match_operand:SI 1 "s_register_operand" "r")
2882                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2883                          (const_int 0)))
2884    (clobber (match_scratch:SI 0 "=r"))]
2885   "TARGET_ARM"
2886   "mvn%?s\\t%0, %1%S3"
2887   [(set_attr "conds" "set")
2888    (set_attr "shift" "1")
2889    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2890                       (const_string "alu_shift")
2891                       (const_string "alu_shift_reg")))]
2892 )
2893
2894 ;; We don't really have extzv, but defining this using shifts helps
2895 ;; to reduce register pressure later on.
2896
2897 (define_expand "extzv"
2898   [(set (match_dup 4)
2899         (ashift:SI (match_operand:SI   1 "register_operand" "")
2900                    (match_operand:SI   2 "const_int_operand" "")))
2901    (set (match_operand:SI              0 "register_operand" "")
2902         (lshiftrt:SI (match_dup 4)
2903                      (match_operand:SI 3 "const_int_operand" "")))]
2904   "TARGET_THUMB"
2905   "
2906   {
2907     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2908     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2909     
2910     operands[3] = GEN_INT (rshift);
2911     
2912     if (lshift == 0)
2913       {
2914         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2915         DONE;
2916       }
2917       
2918     operands[2] = GEN_INT (lshift);
2919     operands[4] = gen_reg_rtx (SImode);
2920   }"
2921 )
2922
2923 \f
2924 ;; Unary arithmetic insns
2925
2926 (define_expand "negdi2"
2927  [(parallel
2928    [(set (match_operand:DI          0 "s_register_operand" "")
2929           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2930     (clobber (reg:CC CC_REGNUM))])]
2931   "TARGET_EITHER"
2932   "
2933   if (TARGET_THUMB)
2934     {
2935       if (GET_CODE (operands[1]) != REG)
2936         operands[1] = force_reg (SImode, operands[1]);
2937      }
2938   "
2939 )
2940
2941 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2942 ;; The second alternative is to allow the common case of a *full* overlap.
2943 (define_insn "*arm_negdi2"
2944   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2945         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2946    (clobber (reg:CC CC_REGNUM))]
2947   "TARGET_ARM"
2948   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2949   [(set_attr "conds" "clob")
2950    (set_attr "length" "8")]
2951 )
2952
2953 (define_insn "*thumb_negdi2"
2954   [(set (match_operand:DI         0 "register_operand" "=&l")
2955         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2956    (clobber (reg:CC CC_REGNUM))]
2957   "TARGET_THUMB"
2958   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2959   [(set_attr "length" "6")]
2960 )
2961
2962 (define_expand "negsi2"
2963   [(set (match_operand:SI         0 "s_register_operand" "")
2964         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2965   "TARGET_EITHER"
2966   ""
2967 )
2968
2969 (define_insn "*arm_negsi2"
2970   [(set (match_operand:SI         0 "s_register_operand" "=r")
2971         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2972   "TARGET_ARM"
2973   "rsb%?\\t%0, %1, #0"
2974   [(set_attr "predicable" "yes")]
2975 )
2976
2977 (define_insn "*thumb_negsi2"
2978   [(set (match_operand:SI         0 "register_operand" "=l")
2979         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2980   "TARGET_THUMB"
2981   "neg\\t%0, %1"
2982   [(set_attr "length" "2")]
2983 )
2984
2985 (define_expand "negsf2"
2986   [(set (match_operand:SF         0 "s_register_operand" "")
2987         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2988   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2989   ""
2990 )
2991
2992 (define_expand "negdf2"
2993   [(set (match_operand:DF         0 "s_register_operand" "")
2994         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2995   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2996   "")
2997
2998 ;; abssi2 doesn't really clobber the condition codes if a different register
2999 ;; is being set.  To keep things simple, assume during rtl manipulations that
3000 ;; it does, but tell the final scan operator the truth.  Similarly for
3001 ;; (neg (abs...))
3002
3003 (define_expand "abssi2"
3004   [(parallel
3005     [(set (match_operand:SI         0 "s_register_operand" "")
3006           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3007      (clobber (reg:CC CC_REGNUM))])]
3008   "TARGET_ARM"
3009   "")
3010
3011 (define_insn "*arm_abssi2"
3012   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3013         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3014    (clobber (reg:CC CC_REGNUM))]
3015   "TARGET_ARM"
3016   "@
3017    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3018    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3019   [(set_attr "conds" "clob,*")
3020    (set_attr "shift" "1")
3021    ;; predicable can't be set based on the variant, so left as no
3022    (set_attr "length" "8")]
3023 )
3024
3025 (define_insn "*neg_abssi2"
3026   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3027         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3028    (clobber (reg:CC CC_REGNUM))]
3029   "TARGET_ARM"
3030   "@
3031    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3032    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3033   [(set_attr "conds" "clob,*")
3034    (set_attr "shift" "1")
3035    ;; predicable can't be set based on the variant, so left as no
3036    (set_attr "length" "8")]
3037 )
3038
3039 (define_expand "abssf2"
3040   [(set (match_operand:SF         0 "s_register_operand" "")
3041         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3042   "TARGET_ARM && TARGET_HARD_FLOAT"
3043   "")
3044
3045 (define_expand "absdf2"
3046   [(set (match_operand:DF         0 "s_register_operand" "")
3047         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3048   "TARGET_ARM && TARGET_HARD_FLOAT"
3049   "")
3050
3051 (define_expand "sqrtsf2"
3052   [(set (match_operand:SF 0 "s_register_operand" "")
3053         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3054   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3055   "")
3056
3057 (define_expand "sqrtdf2"
3058   [(set (match_operand:DF 0 "s_register_operand" "")
3059         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3060   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3061   "")
3062
3063 (define_insn_and_split "one_cmpldi2"
3064   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3065         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3066   "TARGET_ARM"
3067   "#"
3068   "TARGET_ARM && reload_completed"
3069   [(set (match_dup 0) (not:SI (match_dup 1)))
3070    (set (match_dup 2) (not:SI (match_dup 3)))]
3071   "
3072   {
3073     operands[2] = gen_highpart (SImode, operands[0]);
3074     operands[0] = gen_lowpart (SImode, operands[0]);
3075     operands[3] = gen_highpart (SImode, operands[1]);
3076     operands[1] = gen_lowpart (SImode, operands[1]);
3077   }"
3078   [(set_attr "length" "8")
3079    (set_attr "predicable" "yes")]
3080 )
3081
3082 (define_expand "one_cmplsi2"
3083   [(set (match_operand:SI         0 "s_register_operand" "")
3084         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3085   "TARGET_EITHER"
3086   ""
3087 )
3088
3089 (define_insn "*arm_one_cmplsi2"
3090   [(set (match_operand:SI         0 "s_register_operand" "=r")
3091         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3092   "TARGET_ARM"
3093   "mvn%?\\t%0, %1"
3094   [(set_attr "predicable" "yes")]
3095 )
3096
3097 (define_insn "*thumb_one_cmplsi2"
3098   [(set (match_operand:SI         0 "register_operand" "=l")
3099         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3100   "TARGET_THUMB"
3101   "mvn\\t%0, %1"
3102   [(set_attr "length" "2")]
3103 )
3104
3105 (define_insn "*notsi_compare0"
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    (set (match_operand:SI 0 "s_register_operand" "=r")
3110         (not:SI (match_dup 1)))]
3111   "TARGET_ARM"
3112   "mvn%?s\\t%0, %1"
3113   [(set_attr "conds" "set")]
3114 )
3115
3116 (define_insn "*notsi_compare0_scratch"
3117   [(set (reg:CC_NOOV CC_REGNUM)
3118         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3119                          (const_int 0)))
3120    (clobber (match_scratch:SI 0 "=r"))]
3121   "TARGET_ARM"
3122   "mvn%?s\\t%0, %1"
3123   [(set_attr "conds" "set")]
3124 )
3125 \f
3126 ;; Fixed <--> Floating conversion insns
3127
3128 (define_expand "floatsisf2"
3129   [(set (match_operand:SF           0 "s_register_operand" "")
3130         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3131   "TARGET_ARM && TARGET_HARD_FLOAT"
3132   "
3133   if (TARGET_MAVERICK)
3134     {
3135       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3136       DONE;
3137     }
3138 ")
3139
3140 (define_expand "floatsidf2"
3141   [(set (match_operand:DF           0 "s_register_operand" "")
3142         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3143   "TARGET_ARM && TARGET_HARD_FLOAT"
3144   "
3145   if (TARGET_MAVERICK)
3146     {
3147       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3148       DONE;
3149     }
3150 ")
3151
3152 (define_expand "fix_truncsfsi2"
3153   [(set (match_operand:SI         0 "s_register_operand" "")
3154         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3155   "TARGET_ARM && TARGET_HARD_FLOAT"
3156   "
3157   if (TARGET_MAVERICK)
3158     {
3159       if (!cirrus_fp_register (operands[0], SImode))
3160         operands[0] = force_reg (SImode, operands[0]);
3161       if (!cirrus_fp_register (operands[1], SFmode))
3162         operands[1] = force_reg (SFmode, operands[0]);
3163       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3164       DONE;
3165     }
3166 ")
3167
3168 (define_expand "fix_truncdfsi2"
3169   [(set (match_operand:SI         0 "s_register_operand" "")
3170         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3171   "TARGET_ARM && TARGET_HARD_FLOAT"
3172   "
3173   if (TARGET_MAVERICK)
3174     {
3175       if (!cirrus_fp_register (operands[1], DFmode))
3176         operands[1] = force_reg (DFmode, operands[0]);
3177       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3178       DONE;
3179     }
3180 ")
3181
3182 ;; Truncation insns
3183
3184 (define_expand "truncdfsf2"
3185   [(set (match_operand:SF  0 "s_register_operand" "")
3186         (float_truncate:SF
3187          (match_operand:DF 1 "s_register_operand" "")))]
3188   "TARGET_ARM && TARGET_HARD_FLOAT"
3189   ""
3190 )
3191 \f
3192 ;; Zero and sign extension instructions.
3193
3194 (define_insn "zero_extendsidi2"
3195   [(set (match_operand:DI 0 "s_register_operand" "=r")
3196         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3197   "TARGET_ARM"
3198   "*
3199     if (REGNO (operands[1])
3200         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3201       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3202     return \"mov%?\\t%R0, #0\";
3203   "
3204   [(set_attr "length" "8")
3205    (set_attr "predicable" "yes")]
3206 )
3207
3208 (define_insn "zero_extendqidi2"
3209   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3210         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3211   "TARGET_ARM"
3212   "@
3213    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3214    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3215   [(set_attr "length" "8")
3216    (set_attr "predicable" "yes")
3217    (set_attr "type" "*,load_byte")
3218    (set_attr "pool_range" "*,4092")
3219    (set_attr "neg_pool_range" "*,4084")]
3220 )
3221
3222 (define_insn "extendsidi2"
3223   [(set (match_operand:DI 0 "s_register_operand" "=r")
3224         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3225   "TARGET_ARM"
3226   "*
3227     if (REGNO (operands[1])
3228         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3229       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3230     return \"mov%?\\t%R0, %Q0, asr #31\";
3231   "
3232   [(set_attr "length" "8")
3233    (set_attr "shift" "1")
3234    (set_attr "predicable" "yes")]
3235 )
3236
3237 (define_expand "zero_extendhisi2"
3238   [(set (match_dup 2)
3239         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3240                    (const_int 16)))
3241    (set (match_operand:SI 0 "s_register_operand" "")
3242         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3243   "TARGET_EITHER"
3244   "
3245   {
3246     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3247       {
3248         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3250         DONE;
3251       }
3252
3253     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3254       {
3255         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3256         DONE;
3257       }
3258
3259     if (!s_register_operand (operands[1], HImode))
3260       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3261
3262     if (arm_arch6)
3263       {
3264         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3265                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3266         DONE;
3267       }
3268
3269     operands[1] = gen_lowpart (SImode, operands[1]);
3270     operands[2] = gen_reg_rtx (SImode);
3271   }"
3272 )
3273
3274 (define_insn "*thumb_zero_extendhisi2"
3275   [(set (match_operand:SI 0 "register_operand" "=l")
3276         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3277   "TARGET_THUMB && !arm_arch6"
3278   "*
3279   rtx mem = XEXP (operands[1], 0);
3280
3281   if (GET_CODE (mem) == CONST)
3282     mem = XEXP (mem, 0);
3283     
3284   if (GET_CODE (mem) == LABEL_REF)
3285     return \"ldr\\t%0, %1\";
3286     
3287   if (GET_CODE (mem) == PLUS)
3288     {
3289       rtx a = XEXP (mem, 0);
3290       rtx b = XEXP (mem, 1);
3291
3292       /* This can happen due to bugs in reload.  */
3293       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3294         {
3295           rtx ops[2];
3296           ops[0] = operands[0];
3297           ops[1] = a;
3298       
3299           output_asm_insn (\"mov        %0, %1\", ops);
3300
3301           XEXP (mem, 0) = operands[0];
3302        }
3303
3304       else if (   GET_CODE (a) == LABEL_REF
3305                && GET_CODE (b) == CONST_INT)
3306         return \"ldr\\t%0, %1\";
3307     }
3308     
3309   return \"ldrh\\t%0, %1\";
3310   "
3311   [(set_attr "length" "4")
3312    (set_attr "type" "load_byte")
3313    (set_attr "pool_range" "60")]
3314 )
3315
3316 (define_insn "*thumb_zero_extendhisi2_v6"
3317   [(set (match_operand:SI 0 "register_operand" "=l,l")
3318         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3319   "TARGET_THUMB && arm_arch6"
3320   "*
3321   rtx mem;
3322
3323   if (which_alternative == 0)
3324     return \"uxth\\t%0, %1\";
3325
3326   mem = XEXP (operands[1], 0);
3327
3328   if (GET_CODE (mem) == CONST)
3329     mem = XEXP (mem, 0);
3330     
3331   if (GET_CODE (mem) == LABEL_REF)
3332     return \"ldr\\t%0, %1\";
3333     
3334   if (GET_CODE (mem) == PLUS)
3335     {
3336       rtx a = XEXP (mem, 0);
3337       rtx b = XEXP (mem, 1);
3338
3339       /* This can happen due to bugs in reload.  */
3340       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3341         {
3342           rtx ops[2];
3343           ops[0] = operands[0];
3344           ops[1] = a;
3345       
3346           output_asm_insn (\"mov        %0, %1\", ops);
3347
3348           XEXP (mem, 0) = operands[0];
3349        }
3350
3351       else if (   GET_CODE (a) == LABEL_REF
3352                && GET_CODE (b) == CONST_INT)
3353         return \"ldr\\t%0, %1\";
3354     }
3355     
3356   return \"ldrh\\t%0, %1\";
3357   "
3358   [(set_attr "length" "2,4")
3359    (set_attr "type" "alu_shift,load_byte")
3360    (set_attr "pool_range" "*,60")]
3361 )
3362
3363 (define_insn "*arm_zero_extendhisi2"
3364   [(set (match_operand:SI 0 "s_register_operand" "=r")
3365         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3366   "TARGET_ARM && arm_arch4 && !arm_arch6"
3367   "ldr%?h\\t%0, %1"
3368   [(set_attr "type" "load_byte")
3369    (set_attr "predicable" "yes")
3370    (set_attr "pool_range" "256")
3371    (set_attr "neg_pool_range" "244")]
3372 )
3373
3374 (define_insn "*arm_zero_extendhisi2_v6"
3375   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3376         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3377   "TARGET_ARM && arm_arch6"
3378   "@
3379    uxth%?\\t%0, %1
3380    ldr%?h\\t%0, %1"
3381   [(set_attr "type" "alu_shift,load_byte")
3382    (set_attr "predicable" "yes")
3383    (set_attr "pool_range" "*,256")
3384    (set_attr "neg_pool_range" "*,244")]
3385 )
3386
3387 (define_insn "*arm_zero_extendhisi2addsi"
3388   [(set (match_operand:SI 0 "s_register_operand" "=r")
3389         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3390                  (match_operand:SI 2 "s_register_operand" "r")))]
3391   "TARGET_ARM && arm_arch6"
3392   "uxtah%?\\t%0, %2, %1"
3393   [(set_attr "type" "alu_shift")
3394    (set_attr "predicable" "yes")]
3395 )
3396
3397 (define_expand "zero_extendqisi2"
3398   [(set (match_operand:SI 0 "s_register_operand" "")
3399         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3400   "TARGET_EITHER"
3401   "
3402   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3403     {
3404       if (TARGET_ARM)
3405         {
3406           emit_insn (gen_andsi3 (operands[0],
3407                                  gen_lowpart (SImode, operands[1]),
3408                                  GEN_INT (255)));
3409         }
3410       else /* TARGET_THUMB */
3411         {
3412           rtx temp = gen_reg_rtx (SImode);
3413           rtx ops[3];
3414           
3415           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3416           operands[1] = gen_lowpart (SImode, operands[1]);
3417
3418           ops[0] = temp;
3419           ops[1] = operands[1];
3420           ops[2] = GEN_INT (24);
3421
3422           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3423                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3424           
3425           ops[0] = operands[0];
3426           ops[1] = temp;
3427           ops[2] = GEN_INT (24);
3428
3429           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3430                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3431         }
3432       DONE;
3433     }
3434   "
3435 )
3436
3437 (define_insn "*thumb_zero_extendqisi2"
3438   [(set (match_operand:SI 0 "register_operand" "=l")
3439         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3440   "TARGET_THUMB && !arm_arch6"
3441   "ldrb\\t%0, %1"
3442   [(set_attr "length" "2")
3443    (set_attr "type" "load_byte")
3444    (set_attr "pool_range" "32")]
3445 )
3446
3447 (define_insn "*thumb_zero_extendqisi2_v6"
3448   [(set (match_operand:SI 0 "register_operand" "=l,l")
3449         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3450   "TARGET_THUMB && arm_arch6"
3451   "@
3452    uxtb\\t%0, %1
3453    ldrb\\t%0, %1"
3454   [(set_attr "length" "2,2")
3455    (set_attr "type" "alu_shift,load_byte")
3456    (set_attr "pool_range" "*,32")]
3457 )
3458
3459 (define_insn "*arm_zero_extendqisi2"
3460   [(set (match_operand:SI 0 "s_register_operand" "=r")
3461         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3462   "TARGET_ARM && !arm_arch6"
3463   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3464   [(set_attr "type" "load_byte")
3465    (set_attr "predicable" "yes")
3466    (set_attr "pool_range" "4096")
3467    (set_attr "neg_pool_range" "4084")]
3468 )
3469
3470 (define_insn "*arm_zero_extendqisi2_v6"
3471   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3472         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3473   "TARGET_ARM && arm_arch6"
3474   "@
3475    uxtb%?\\t%0, %1
3476    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3477   [(set_attr "type" "alu_shift,load_byte")
3478    (set_attr "predicable" "yes")
3479    (set_attr "pool_range" "*,4096")
3480    (set_attr "neg_pool_range" "*,4084")]
3481 )
3482
3483 (define_insn "*arm_zero_extendqisi2addsi"
3484   [(set (match_operand:SI 0 "s_register_operand" "=r")
3485         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3486                  (match_operand:SI 2 "s_register_operand" "r")))]
3487   "TARGET_ARM && arm_arch6"
3488   "uxtab%?\\t%0, %2, %1"
3489   [(set_attr "predicable" "yes")
3490    (set_attr "type" "alu_shift")]
3491 )
3492
3493 (define_split
3494   [(set (match_operand:SI 0 "s_register_operand" "")
3495         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3496    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3497   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3498   [(set (match_dup 2) (match_dup 1))
3499    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3500   ""
3501 )
3502
3503 (define_split
3504   [(set (match_operand:SI 0 "s_register_operand" "")
3505         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3506    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3507   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3508   [(set (match_dup 2) (match_dup 1))
3509    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3510   ""
3511 )
3512
3513 (define_insn "*compareqi_eq0"
3514   [(set (reg:CC_Z CC_REGNUM)
3515         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3516                          (const_int 0)))]
3517   "TARGET_ARM"
3518   "tst\\t%0, #255"
3519   [(set_attr "conds" "set")]
3520 )
3521
3522 (define_expand "extendhisi2"
3523   [(set (match_dup 2)
3524         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3525                    (const_int 16)))
3526    (set (match_operand:SI 0 "s_register_operand" "")
3527         (ashiftrt:SI (match_dup 2)
3528                      (const_int 16)))]
3529   "TARGET_EITHER"
3530   "
3531   {
3532     if (GET_CODE (operands[1]) == MEM)
3533       {
3534         if (TARGET_THUMB)
3535           {
3536             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3537             DONE;
3538           }
3539         else if (arm_arch4)
3540           {
3541             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3542                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3543             DONE;
3544           }
3545       }
3546
3547     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3548       {
3549         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3550         DONE;
3551       }
3552
3553     if (!s_register_operand (operands[1], HImode))
3554       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3555
3556     if (arm_arch6)
3557       {
3558         if (TARGET_THUMB)
3559           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3560         else
3561           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3562                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3563
3564         DONE;
3565       }
3566
3567     operands[1] = gen_lowpart (SImode, operands[1]);
3568     operands[2] = gen_reg_rtx (SImode);
3569   }"
3570 )
3571
3572 (define_insn "thumb_extendhisi2"
3573   [(set (match_operand:SI 0 "register_operand" "=l")
3574         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3575    (clobber (match_scratch:SI 2 "=&l"))]
3576   "TARGET_THUMB && !arm_arch6"
3577   "*
3578   {
3579     rtx ops[4];
3580     rtx mem = XEXP (operands[1], 0);
3581
3582     /* This code used to try to use 'V', and fix the address only if it was
3583        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3584        range of QImode offsets, and offsettable_address_p does a QImode
3585        address check.  */
3586        
3587     if (GET_CODE (mem) == CONST)
3588       mem = XEXP (mem, 0);
3589     
3590     if (GET_CODE (mem) == LABEL_REF)
3591       return \"ldr\\t%0, %1\";
3592     
3593     if (GET_CODE (mem) == PLUS)
3594       {
3595         rtx a = XEXP (mem, 0);
3596         rtx b = XEXP (mem, 1);
3597
3598         if (GET_CODE (a) == LABEL_REF
3599             && GET_CODE (b) == CONST_INT)
3600           return \"ldr\\t%0, %1\";
3601
3602         if (GET_CODE (b) == REG)
3603           return \"ldrsh\\t%0, %1\";
3604           
3605         ops[1] = a;
3606         ops[2] = b;
3607       }
3608     else
3609       {
3610         ops[1] = mem;
3611         ops[2] = const0_rtx;
3612       }
3613
3614     gcc_assert (GET_CODE (ops[1]) == REG);
3615
3616     ops[0] = operands[0];
3617     ops[3] = operands[2];
3618     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3619     return \"\";
3620   }"
3621   [(set_attr "length" "4")
3622    (set_attr "type" "load_byte")
3623    (set_attr "pool_range" "1020")]
3624 )
3625
3626 ;; We used to have an early-clobber on the scratch register here.
3627 ;; However, there's a bug somewhere in reload which means that this
3628 ;; can be partially ignored during spill allocation if the memory
3629 ;; address also needs reloading; this causes us to die later on when
3630 ;; we try to verify the operands.  Fortunately, we don't really need
3631 ;; the early-clobber: we can always use operand 0 if operand 2
3632 ;; overlaps the address.
3633 (define_insn "*thumb_extendhisi2_insn_v6"
3634   [(set (match_operand:SI 0 "register_operand" "=l,l")
3635         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3636    (clobber (match_scratch:SI 2 "=X,l"))]
3637   "TARGET_THUMB && arm_arch6"
3638   "*
3639   {
3640     rtx ops[4];
3641     rtx mem;
3642
3643     if (which_alternative == 0)
3644       return \"sxth\\t%0, %1\";
3645
3646     mem = XEXP (operands[1], 0);
3647
3648     /* This code used to try to use 'V', and fix the address only if it was
3649        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3650        range of QImode offsets, and offsettable_address_p does a QImode
3651        address check.  */
3652        
3653     if (GET_CODE (mem) == CONST)
3654       mem = XEXP (mem, 0);
3655     
3656     if (GET_CODE (mem) == LABEL_REF)
3657       return \"ldr\\t%0, %1\";
3658     
3659     if (GET_CODE (mem) == PLUS)
3660       {
3661         rtx a = XEXP (mem, 0);
3662         rtx b = XEXP (mem, 1);
3663
3664         if (GET_CODE (a) == LABEL_REF
3665             && GET_CODE (b) == CONST_INT)
3666           return \"ldr\\t%0, %1\";
3667
3668         if (GET_CODE (b) == REG)
3669           return \"ldrsh\\t%0, %1\";
3670           
3671         ops[1] = a;
3672         ops[2] = b;
3673       }
3674     else
3675       {
3676         ops[1] = mem;
3677         ops[2] = const0_rtx;
3678       }
3679       
3680     gcc_assert (GET_CODE (ops[1]) == REG);
3681
3682     ops[0] = operands[0];
3683     if (reg_mentioned_p (operands[2], ops[1]))
3684       ops[3] = ops[0];
3685     else
3686       ops[3] = operands[2];
3687     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3688     return \"\";
3689   }"
3690   [(set_attr "length" "2,4")
3691    (set_attr "type" "alu_shift,load_byte")
3692    (set_attr "pool_range" "*,1020")]
3693 )
3694
3695 (define_expand "extendhisi2_mem"
3696   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3697    (set (match_dup 3)
3698         (zero_extend:SI (match_dup 7)))
3699    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3700    (set (match_operand:SI 0 "" "")
3701         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3702   "TARGET_ARM"
3703   "
3704   {
3705     rtx mem1, mem2;
3706     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3707
3708     mem1 = change_address (operands[1], QImode, addr);
3709     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3710     operands[0] = gen_lowpart (SImode, operands[0]);
3711     operands[1] = mem1;
3712     operands[2] = gen_reg_rtx (SImode);
3713     operands[3] = gen_reg_rtx (SImode);
3714     operands[6] = gen_reg_rtx (SImode);
3715     operands[7] = mem2;
3716
3717     if (BYTES_BIG_ENDIAN)
3718       {
3719         operands[4] = operands[2];
3720         operands[5] = operands[3];
3721       }
3722     else
3723       {
3724         operands[4] = operands[3];
3725         operands[5] = operands[2];
3726       }
3727   }"
3728 )
3729
3730 (define_insn "*arm_extendhisi2"
3731   [(set (match_operand:SI 0 "s_register_operand" "=r")
3732         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3733   "TARGET_ARM && arm_arch4 && !arm_arch6"
3734   "ldr%?sh\\t%0, %1"
3735   [(set_attr "type" "load_byte")
3736    (set_attr "predicable" "yes")
3737    (set_attr "pool_range" "256")
3738    (set_attr "neg_pool_range" "244")]
3739 )
3740
3741 (define_insn "*arm_extendhisi2_v6"
3742   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3743         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3744   "TARGET_ARM && arm_arch6"
3745   "@
3746    sxth%?\\t%0, %1
3747    ldr%?sh\\t%0, %1"
3748   [(set_attr "type" "alu_shift,load_byte")
3749    (set_attr "predicable" "yes")
3750    (set_attr "pool_range" "*,256")
3751    (set_attr "neg_pool_range" "*,244")]
3752 )
3753
3754 (define_insn "*arm_extendhisi2addsi"
3755   [(set (match_operand:SI 0 "s_register_operand" "=r")
3756         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3757                  (match_operand:SI 2 "s_register_operand" "r")))]
3758   "TARGET_ARM && arm_arch6"
3759   "sxtah%?\\t%0, %2, %1"
3760 )
3761
3762 (define_expand "extendqihi2"
3763   [(set (match_dup 2)
3764         (ashift:SI (match_operand:QI 1 "general_operand" "")
3765                    (const_int 24)))
3766    (set (match_operand:HI 0 "s_register_operand" "")
3767         (ashiftrt:SI (match_dup 2)
3768                      (const_int 24)))]
3769   "TARGET_ARM"
3770   "
3771   {
3772     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3773       {
3774         emit_insn (gen_rtx_SET (VOIDmode,
3775                                 operands[0],
3776                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3777         DONE;
3778       }
3779     if (!s_register_operand (operands[1], QImode))
3780       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3781     operands[0] = gen_lowpart (SImode, operands[0]);
3782     operands[1] = gen_lowpart (SImode, operands[1]);
3783     operands[2] = gen_reg_rtx (SImode);
3784   }"
3785 )
3786
3787 (define_insn "*extendqihi_insn"
3788   [(set (match_operand:HI 0 "s_register_operand" "=r")
3789         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3790   "TARGET_ARM && arm_arch4"
3791   "ldr%?sb\\t%0, %1"
3792   [(set_attr "type" "load_byte")
3793    (set_attr "predicable" "yes")
3794    (set_attr "pool_range" "256")
3795    (set_attr "neg_pool_range" "244")]
3796 )
3797
3798 (define_expand "extendqisi2"
3799   [(set (match_dup 2)
3800         (ashift:SI (match_operand:QI 1 "general_operand" "")
3801                    (const_int 24)))
3802    (set (match_operand:SI 0 "s_register_operand" "")
3803         (ashiftrt:SI (match_dup 2)
3804                      (const_int 24)))]
3805   "TARGET_EITHER"
3806   "
3807   {
3808     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3809       {
3810         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3811                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3812         DONE;
3813       }
3814
3815     if (!s_register_operand (operands[1], QImode))
3816       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3817
3818     if (arm_arch6)
3819       {
3820         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3821                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3822         DONE;
3823       }
3824
3825     operands[1] = gen_lowpart (SImode, operands[1]);
3826     operands[2] = gen_reg_rtx (SImode);
3827   }"
3828 )
3829
3830 (define_insn "*arm_extendqisi"
3831   [(set (match_operand:SI 0 "s_register_operand" "=r")
3832         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3833   "TARGET_ARM && arm_arch4 && !arm_arch6"
3834   "ldr%?sb\\t%0, %1"
3835   [(set_attr "type" "load_byte")
3836    (set_attr "predicable" "yes")
3837    (set_attr "pool_range" "256")
3838    (set_attr "neg_pool_range" "244")]
3839 )
3840
3841 (define_insn "*arm_extendqisi_v6"
3842   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3843         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3844   "TARGET_ARM && arm_arch6"
3845   "@
3846    sxtb%?\\t%0, %1
3847    ldr%?sb\\t%0, %1"
3848   [(set_attr "type" "alu_shift,load_byte")
3849    (set_attr "predicable" "yes")
3850    (set_attr "pool_range" "*,256")
3851    (set_attr "neg_pool_range" "*,244")]
3852 )
3853
3854 (define_insn "*arm_extendqisi2addsi"
3855   [(set (match_operand:SI 0 "s_register_operand" "=r")
3856         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3857                  (match_operand:SI 2 "s_register_operand" "r")))]
3858   "TARGET_ARM && arm_arch6"
3859   "sxtab%?\\t%0, %2, %1"
3860   [(set_attr "type" "alu_shift")
3861    (set_attr "predicable" "yes")]
3862 )
3863
3864 (define_insn "*thumb_extendqisi2"
3865   [(set (match_operand:SI 0 "register_operand" "=l,l")
3866         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3867   "TARGET_THUMB && !arm_arch6"
3868   "*
3869   {
3870     rtx ops[3];
3871     rtx mem = XEXP (operands[1], 0);
3872     
3873     if (GET_CODE (mem) == CONST)
3874       mem = XEXP (mem, 0);
3875     
3876     if (GET_CODE (mem) == LABEL_REF)
3877       return \"ldr\\t%0, %1\";
3878
3879     if (GET_CODE (mem) == PLUS
3880         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3881       return \"ldr\\t%0, %1\";
3882       
3883     if (which_alternative == 0)
3884       return \"ldrsb\\t%0, %1\";
3885       
3886     ops[0] = operands[0];
3887     
3888     if (GET_CODE (mem) == PLUS)
3889       {
3890         rtx a = XEXP (mem, 0);
3891         rtx b = XEXP (mem, 1);
3892         
3893         ops[1] = a;
3894         ops[2] = b;
3895
3896         if (GET_CODE (a) == REG)
3897           {
3898             if (GET_CODE (b) == REG)
3899               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3900             else if (REGNO (a) == REGNO (ops[0]))
3901               {
3902                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3903                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3904                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3905               }
3906             else
3907               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3908           }
3909         else
3910           {
3911             gcc_assert (GET_CODE (b) == REG);
3912             if (REGNO (b) == REGNO (ops[0]))
3913               {
3914                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3915                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3916                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3917               }
3918             else
3919               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3920           }
3921       }
3922     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3923       {
3924         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3925         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3926         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3927       }
3928     else
3929       {
3930         ops[1] = mem;
3931         ops[2] = const0_rtx;
3932         
3933         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3934       }
3935     return \"\";
3936   }"
3937   [(set_attr "length" "2,6")
3938    (set_attr "type" "load_byte,load_byte")
3939    (set_attr "pool_range" "32,32")]
3940 )
3941
3942 (define_insn "*thumb_extendqisi2_v6"
3943   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3944         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3945   "TARGET_THUMB && arm_arch6"
3946   "*
3947   {
3948     rtx ops[3];
3949     rtx mem;
3950
3951     if (which_alternative == 0)
3952       return \"sxtb\\t%0, %1\";
3953
3954     mem = XEXP (operands[1], 0);
3955     
3956     if (GET_CODE (mem) == CONST)
3957       mem = XEXP (mem, 0);
3958     
3959     if (GET_CODE (mem) == LABEL_REF)
3960       return \"ldr\\t%0, %1\";
3961
3962     if (GET_CODE (mem) == PLUS
3963         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3964       return \"ldr\\t%0, %1\";
3965       
3966     if (which_alternative == 0)
3967       return \"ldrsb\\t%0, %1\";
3968       
3969     ops[0] = operands[0];
3970     
3971     if (GET_CODE (mem) == PLUS)
3972       {
3973         rtx a = XEXP (mem, 0);
3974         rtx b = XEXP (mem, 1);
3975         
3976         ops[1] = a;
3977         ops[2] = b;
3978
3979         if (GET_CODE (a) == REG)
3980           {
3981             if (GET_CODE (b) == REG)
3982               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3983             else if (REGNO (a) == REGNO (ops[0]))
3984               {
3985                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3986                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3987               }
3988             else
3989               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3990           }
3991         else
3992           {
3993             gcc_assert (GET_CODE (b) == REG);
3994             if (REGNO (b) == REGNO (ops[0]))
3995               {
3996                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3997                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3998               }
3999             else
4000               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4001           }
4002       }
4003     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4004       {
4005         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4006         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4007       }
4008     else
4009       {
4010         ops[1] = mem;
4011         ops[2] = const0_rtx;
4012         
4013         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4014       }
4015     return \"\";
4016   }"
4017   [(set_attr "length" "2,2,4")
4018    (set_attr "type" "alu_shift,load_byte,load_byte")
4019    (set_attr "pool_range" "*,32,32")]
4020 )
4021
4022 (define_expand "extendsfdf2"
4023   [(set (match_operand:DF                  0 "s_register_operand" "")
4024         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4025   "TARGET_ARM && TARGET_HARD_FLOAT"
4026   ""
4027 )
4028 \f
4029 ;; Move insns (including loads and stores)
4030
4031 ;; XXX Just some ideas about movti.
4032 ;; I don't think these are a good idea on the arm, there just aren't enough
4033 ;; registers
4034 ;;(define_expand "loadti"
4035 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4036 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4037 ;;  "" "")
4038
4039 ;;(define_expand "storeti"
4040 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4041 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4042 ;;  "" "")
4043
4044 ;;(define_expand "movti"
4045 ;;  [(set (match_operand:TI 0 "general_operand" "")
4046 ;;      (match_operand:TI 1 "general_operand" ""))]
4047 ;;  ""
4048 ;;  "
4049 ;;{
4050 ;;  rtx insn;
4051 ;;
4052 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4053 ;;    operands[1] = copy_to_reg (operands[1]);
4054 ;;  if (GET_CODE (operands[0]) == MEM)
4055 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4056 ;;  else if (GET_CODE (operands[1]) == MEM)
4057 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4058 ;;  else
4059 ;;    FAIL;
4060 ;;
4061 ;;  emit_insn (insn);
4062 ;;  DONE;
4063 ;;}")
4064
4065 ;; Recognize garbage generated above.
4066
4067 ;;(define_insn ""
4068 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4069 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4070 ;;  ""
4071 ;;  "*
4072 ;;  {
4073 ;;    register mem = (which_alternative < 3);
4074 ;;    register const char *template;
4075 ;;
4076 ;;    operands[mem] = XEXP (operands[mem], 0);
4077 ;;    switch (which_alternative)
4078 ;;      {
4079 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4080 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4081 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4082 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4083 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4084 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4085 ;;      }
4086 ;;    output_asm_insn (template, operands);
4087 ;;    return \"\";
4088 ;;  }")
4089
4090 (define_expand "movdi"
4091   [(set (match_operand:DI 0 "general_operand" "")
4092         (match_operand:DI 1 "general_operand" ""))]
4093   "TARGET_EITHER"
4094   "
4095   if (!no_new_pseudos)
4096     {
4097       if (GET_CODE (operands[0]) != REG)
4098         operands[1] = force_reg (DImode, operands[1]);
4099     }
4100   "
4101 )
4102
4103 (define_insn "*arm_movdi"
4104   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4105         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4106   "TARGET_ARM
4107    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4108    && !TARGET_IWMMXT
4109    && (   register_operand (operands[0], DImode)
4110        || register_operand (operands[1], DImode))"
4111   "*
4112   switch (which_alternative)
4113     {
4114     case 0:
4115     case 1:
4116     case 2:
4117       return \"#\";
4118     default:
4119       return output_move_double (operands);
4120     }
4121   "
4122   [(set_attr "length" "8,12,16,8,8")
4123    (set_attr "type" "*,*,*,load2,store2")
4124    (set_attr "pool_range" "*,*,*,1020,*")
4125    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4126 )
4127
4128 (define_split
4129   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4130         (match_operand:ANY64 1 "const_double_operand" ""))]
4131   "TARGET_ARM
4132    && reload_completed
4133    && (arm_const_double_inline_cost (operands[1])
4134        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4135   [(const_int 0)]
4136   "
4137   arm_split_constant (SET, SImode, curr_insn,
4138                       INTVAL (gen_lowpart (SImode, operands[1])),
4139                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4140   arm_split_constant (SET, SImode, curr_insn,
4141                       INTVAL (gen_highpart_mode (SImode,
4142                                                  GET_MODE (operands[0]),
4143                                                  operands[1])),
4144                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4145   DONE;
4146   "
4147 )
4148
4149 ; If optimizing for size, or if we have load delay slots, then 
4150 ; we want to split the constant into two separate operations. 
4151 ; In both cases this may split a trivial part into a single data op
4152 ; leaving a single complex constant to load.  We can also get longer
4153 ; offsets in a LDR which means we get better chances of sharing the pool
4154 ; entries.  Finally, we can normally do a better job of scheduling
4155 ; LDR instructions than we can with LDM.
4156 ; This pattern will only match if the one above did not.
4157 (define_split
4158   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4159         (match_operand:ANY64 1 "const_double_operand" ""))]
4160   "TARGET_ARM && reload_completed
4161    && arm_const_double_by_parts (operands[1])"
4162   [(set (match_dup 0) (match_dup 1))
4163    (set (match_dup 2) (match_dup 3))]
4164   "
4165   operands[2] = gen_highpart (SImode, operands[0]);
4166   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4167                                    operands[1]);
4168   operands[0] = gen_lowpart (SImode, operands[0]);
4169   operands[1] = gen_lowpart (SImode, operands[1]);
4170   "
4171 )
4172
4173 (define_split
4174   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4175         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4176   "TARGET_EITHER && reload_completed"
4177   [(set (match_dup 0) (match_dup 1))
4178    (set (match_dup 2) (match_dup 3))]
4179   "
4180   operands[2] = gen_highpart (SImode, operands[0]);
4181   operands[3] = gen_highpart (SImode, operands[1]);
4182   operands[0] = gen_lowpart (SImode, operands[0]);
4183   operands[1] = gen_lowpart (SImode, operands[1]);
4184
4185   /* Handle a partial overlap.  */
4186   if (rtx_equal_p (operands[0], operands[3]))
4187     {
4188       rtx tmp0 = operands[0];
4189       rtx tmp1 = operands[1];
4190
4191       operands[0] = operands[2];
4192       operands[1] = operands[3];
4193       operands[2] = tmp0;
4194       operands[3] = tmp1;
4195     }
4196   "
4197 )
4198
4199 ;; We can't actually do base+index doubleword loads if the index and
4200 ;; destination overlap.  Split here so that we at least have chance to
4201 ;; schedule.
4202 (define_split
4203   [(set (match_operand:DI 0 "s_register_operand" "")
4204         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4205                          (match_operand:SI 2 "s_register_operand" ""))))]
4206   "TARGET_LDRD
4207   && reg_overlap_mentioned_p (operands[0], operands[1])
4208   && reg_overlap_mentioned_p (operands[0], operands[2])"
4209   [(set (match_dup 4)
4210         (plus:SI (match_dup 1)
4211                  (match_dup 2)))
4212    (set (match_dup 0)
4213         (mem:DI (match_dup 4)))]
4214   "
4215   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4216   "
4217 )
4218
4219 ;;; ??? This should have alternatives for constants.
4220 ;;; ??? This was originally identical to the movdf_insn pattern.
4221 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4222 ;;; thumb_reorg with a memory reference.
4223 (define_insn "*thumb_movdi_insn"
4224   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4225         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4226   "TARGET_THUMB
4227    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4228    && (   register_operand (operands[0], DImode)
4229        || register_operand (operands[1], DImode))"
4230   "*
4231   {
4232   switch (which_alternative)
4233     {
4234     default:
4235     case 0:
4236       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4237         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4238       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4239     case 1:
4240       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4241     case 2:
4242       operands[1] = GEN_INT (- INTVAL (operands[1]));
4243       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4244     case 3:
4245       return \"ldmia\\t%1, {%0, %H0}\";
4246     case 4:
4247       return \"stmia\\t%0, {%1, %H1}\";
4248     case 5:
4249       return thumb_load_double_from_address (operands);
4250     case 6:
4251       operands[2] = gen_rtx_MEM (SImode,
4252                              plus_constant (XEXP (operands[0], 0), 4));
4253       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4254       return \"\";
4255     case 7:
4256       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4257         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4258       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4259     }
4260   }"
4261   [(set_attr "length" "4,4,6,2,2,6,4,4")
4262    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4263    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4264 )
4265
4266 (define_expand "movsi"
4267   [(set (match_operand:SI 0 "general_operand" "")
4268         (match_operand:SI 1 "general_operand" ""))]
4269   "TARGET_EITHER"
4270   "
4271   if (TARGET_ARM)
4272     {
4273       /* Everything except mem = const or mem = mem can be done easily.  */
4274       if (GET_CODE (operands[0]) == MEM)
4275         operands[1] = force_reg (SImode, operands[1]);
4276       if (arm_general_register_operand (operands[0], SImode)
4277           && GET_CODE (operands[1]) == CONST_INT
4278           && !(const_ok_for_arm (INTVAL (operands[1]))
4279                || const_ok_for_arm (~INTVAL (operands[1]))))
4280         {
4281            arm_split_constant (SET, SImode, NULL_RTX,
4282                                INTVAL (operands[1]), operands[0], NULL_RTX,
4283                                optimize && !no_new_pseudos);
4284           DONE;
4285         }
4286     }
4287   else /* TARGET_THUMB....  */
4288     {
4289       if (!no_new_pseudos)
4290         {
4291           if (GET_CODE (operands[0]) != REG)
4292             operands[1] = force_reg (SImode, operands[1]);
4293         }
4294     }
4295
4296   /* Recognize the case where operand[1] is a reference to thread-local
4297      data and load its address to a register.  */
4298   if (arm_tls_referenced_p (operands[1]))
4299     {
4300       rtx tmp = operands[1];
4301       rtx addend = NULL;
4302
4303       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4304         {
4305           addend = XEXP (XEXP (tmp, 0), 1);
4306           tmp = XEXP (XEXP (tmp, 0), 0);
4307         }
4308
4309       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4310       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4311
4312       tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4313       if (addend)
4314         {
4315           tmp = gen_rtx_PLUS (SImode, tmp, addend);
4316           tmp = force_operand (tmp, operands[0]);
4317         }
4318       operands[1] = tmp;
4319     }
4320   else if (flag_pic
4321            && (CONSTANT_P (operands[1])
4322                || symbol_mentioned_p (operands[1])
4323                || label_mentioned_p (operands[1])))
4324       operands[1] = legitimize_pic_address (operands[1], SImode,
4325                                             (no_new_pseudos ? operands[0] : 0));
4326   "
4327 )
4328
4329 (define_insn "*arm_movsi_insn"
4330   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4331         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4332   "TARGET_ARM && ! TARGET_IWMMXT
4333    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4334    && (   register_operand (operands[0], SImode)
4335        || register_operand (operands[1], SImode))"
4336   "@
4337    mov%?\\t%0, %1
4338    mvn%?\\t%0, #%B1
4339    ldr%?\\t%0, %1
4340    str%?\\t%1, %0"
4341   [(set_attr "type" "*,*,load1,store1")
4342    (set_attr "predicable" "yes")
4343    (set_attr "pool_range" "*,*,4096,*")
4344    (set_attr "neg_pool_range" "*,*,4084,*")]
4345 )
4346
4347 (define_split
4348   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4349         (match_operand:SI 1 "const_int_operand" ""))]
4350   "TARGET_ARM
4351   && (!(const_ok_for_arm (INTVAL (operands[1]))
4352         || const_ok_for_arm (~INTVAL (operands[1]))))"
4353   [(clobber (const_int 0))]
4354   "
4355   arm_split_constant (SET, SImode, NULL_RTX, 
4356                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4357   DONE;
4358   "
4359 )
4360
4361 (define_insn "*thumb_movsi_insn"
4362   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4363         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4364   "TARGET_THUMB
4365    && (   register_operand (operands[0], SImode) 
4366        || register_operand (operands[1], SImode))"
4367   "@
4368    mov  %0, %1
4369    mov  %0, %1
4370    #
4371    #
4372    ldmia\\t%1, {%0}
4373    stmia\\t%0, {%1}
4374    ldr\\t%0, %1
4375    str\\t%1, %0
4376    mov\\t%0, %1"
4377   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4378    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4379    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4380 )
4381
4382 (define_split 
4383   [(set (match_operand:SI 0 "register_operand" "")
4384         (match_operand:SI 1 "const_int_operand" ""))]
4385   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4386   [(set (match_dup 0) (match_dup 1))
4387    (set (match_dup 0) (neg:SI (match_dup 0)))]
4388   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4389 )
4390
4391 (define_split 
4392   [(set (match_operand:SI 0 "register_operand" "")
4393         (match_operand:SI 1 "const_int_operand" ""))]
4394   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4395   [(set (match_dup 0) (match_dup 1))
4396    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4397   "
4398   {
4399     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4400     unsigned HOST_WIDE_INT mask = 0xff;
4401     int i;
4402     
4403     for (i = 0; i < 25; i++)
4404       if ((val & (mask << i)) == val)
4405         break;
4406
4407     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4408     if (i == 0)
4409       FAIL;
4410
4411     operands[1] = GEN_INT (val >> i);
4412     operands[2] = GEN_INT (i);
4413   }"
4414 )
4415
4416 ;; When generating pic, we need to load the symbol offset into a register.
4417 ;; So that the optimizer does not confuse this with a normal symbol load
4418 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4419 ;; since that is the only type of relocation we can use.
4420
4421 ;; The rather odd constraints on the following are to force reload to leave
4422 ;; the insn alone, and to force the minipool generation pass to then move
4423 ;; the GOT symbol to memory.
4424
4425 (define_insn "pic_load_addr_arm"
4426   [(set (match_operand:SI 0 "s_register_operand" "=r")
4427         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4428   "TARGET_ARM && flag_pic"
4429   "ldr%?\\t%0, %1"
4430   [(set_attr "type" "load1")
4431    (set (attr "pool_range")     (const_int 4096))
4432    (set (attr "neg_pool_range") (const_int 4084))]
4433 )
4434
4435 (define_insn "pic_load_addr_thumb"
4436   [(set (match_operand:SI 0 "s_register_operand" "=l")
4437         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4438   "TARGET_THUMB && flag_pic"
4439   "ldr\\t%0, %1"
4440   [(set_attr "type" "load1")
4441    (set (attr "pool_range") (const_int 1024))]
4442 )
4443
4444 ;; This variant is used for AOF assembly, since it needs to mention the
4445 ;; pic register in the rtl.
4446 (define_expand "pic_load_addr_based"
4447   [(set (match_operand:SI 0 "s_register_operand" "")
4448         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4449   "TARGET_ARM && flag_pic"
4450   "operands[2] = cfun->machine->pic_reg;"
4451 )
4452
4453 (define_insn "*pic_load_addr_based_insn"
4454   [(set (match_operand:SI 0 "s_register_operand" "=r")
4455         (unspec:SI [(match_operand 1 "" "")
4456                     (match_operand 2 "s_register_operand" "r")]
4457                    UNSPEC_PIC_SYM))]
4458   "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
4459   "*
4460 #ifdef AOF_ASSEMBLER
4461   operands[1] = aof_pic_entry (operands[1]);
4462 #endif
4463   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4464   return \"\";
4465   "
4466   [(set_attr "type" "load1")
4467    (set (attr "pool_range")
4468         (if_then_else (eq_attr "is_thumb" "yes")
4469                       (const_int 1024)
4470                       (const_int 4096)))
4471    (set (attr "neg_pool_range")
4472         (if_then_else (eq_attr "is_thumb" "yes")
4473                       (const_int 0)
4474                       (const_int 4084)))]
4475 )
4476
4477 (define_insn "pic_add_dot_plus_four"
4478   [(set (match_operand:SI 0 "register_operand" "=r")
4479         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4480                              (const (plus:SI (pc) (const_int 4))))]
4481                    UNSPEC_PIC_BASE))
4482    (use (match_operand 2 "" ""))]
4483   "TARGET_THUMB"
4484   "*
4485   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4486                                      INTVAL (operands[2]));
4487   return \"add\\t%0, %|pc\";
4488   "
4489   [(set_attr "length" "2")]
4490 )
4491
4492 (define_insn "pic_add_dot_plus_eight"
4493   [(set (match_operand:SI 0 "register_operand" "=r")
4494         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4495                              (const (plus:SI (pc) (const_int 8))))]
4496                    UNSPEC_PIC_BASE))
4497    (use (match_operand 2 "" ""))]
4498   "TARGET_ARM"
4499   "*
4500     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4501                                        INTVAL (operands[2]));
4502     return \"add%?\\t%0, %|pc, %1\";
4503   "
4504   [(set_attr "predicable" "yes")]
4505 )
4506
4507 (define_insn "tls_load_dot_plus_eight"
4508   [(set (match_operand:SI 0 "register_operand" "+r")
4509         (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4510                                      (const (plus:SI (pc) (const_int 8))))]
4511                            UNSPEC_PIC_BASE)))
4512    (use (match_operand 2 "" ""))]
4513   "TARGET_ARM"
4514   "*
4515     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4516                                        INTVAL (operands[2]));
4517     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4518   "
4519   [(set_attr "predicable" "yes")]
4520 )
4521
4522 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4523 ;; followed by a load.  These sequences can be crunched down to
4524 ;; tls_load_dot_plus_eight by a peephole.
4525
4526 (define_peephole2
4527   [(parallel [(set (match_operand:SI 0 "register_operand" "")
4528                    (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4529                                         (const (plus:SI (pc) (const_int 8))))]
4530                               UNSPEC_PIC_BASE))
4531               (use (label_ref (match_operand 1 "" "")))])
4532    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4533   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4534   [(parallel [(set (match_dup 2)
4535                    (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4536                                                 (const (plus:SI (pc) (const_int 8))))]
4537                                       UNSPEC_PIC_BASE)))
4538               (use (label_ref (match_dup 1)))])]
4539   ""
4540 )
4541
4542 (define_expand "builtin_setjmp_receiver"
4543   [(label_ref (match_operand 0 "" ""))]
4544   "flag_pic"
4545   "
4546 {
4547   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4548      register.  */
4549   if (arm_pic_register != INVALID_REGNUM)
4550     arm_load_pic_register (1UL << 3);
4551   DONE;
4552 }")
4553
4554 ;; If copying one reg to another we can set the condition codes according to
4555 ;; its value.  Such a move is common after a return from subroutine and the
4556 ;; result is being tested against zero.
4557
4558 (define_insn "*movsi_compare0"
4559   [(set (reg:CC CC_REGNUM)
4560         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4561                     (const_int 0)))
4562    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4563         (match_dup 1))]
4564   "TARGET_ARM"
4565   "@
4566    cmp%?\\t%0, #0
4567    sub%?s\\t%0, %1, #0"
4568   [(set_attr "conds" "set")]
4569 )
4570
4571 ;; Subroutine to store a half word from a register into memory.
4572 ;; Operand 0 is the source register (HImode)
4573 ;; Operand 1 is the destination address in a register (SImode)
4574
4575 ;; In both this routine and the next, we must be careful not to spill
4576 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4577 ;; can generate unrecognizable rtl.
4578
4579 (define_expand "storehi"
4580   [;; store the low byte
4581    (set (match_operand 1 "" "") (match_dup 3))
4582    ;; extract the high byte
4583    (set (match_dup 2)
4584         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4585    ;; store the high byte
4586    (set (match_dup 4) (match_dup 5))]
4587   "TARGET_ARM"
4588   "
4589   {
4590     rtx op1 = operands[1];
4591     rtx addr = XEXP (op1, 0);
4592     enum rtx_code code = GET_CODE (addr);
4593
4594     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4595         || code == MINUS)
4596       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4597
4598     operands[4] = adjust_address (op1, QImode, 1);
4599     operands[1] = adjust_address (operands[1], QImode, 0);
4600     operands[3] = gen_lowpart (QImode, operands[0]);
4601     operands[0] = gen_lowpart (SImode, operands[0]);
4602     operands[2] = gen_reg_rtx (SImode);
4603     operands[5] = gen_lowpart (QImode, operands[2]);
4604   }"
4605 )
4606
4607 (define_expand "storehi_bigend"
4608   [(set (match_dup 4) (match_dup 3))
4609    (set (match_dup 2)
4610         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4611    (set (match_operand 1 "" "") (match_dup 5))]
4612   "TARGET_ARM"
4613   "
4614   {
4615     rtx op1 = operands[1];
4616     rtx addr = XEXP (op1, 0);
4617     enum rtx_code code = GET_CODE (addr);
4618
4619     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4620         || code == MINUS)
4621       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4622
4623     operands[4] = adjust_address (op1, QImode, 1);
4624     operands[1] = adjust_address (operands[1], QImode, 0);
4625     operands[3] = gen_lowpart (QImode, operands[0]);
4626     operands[0] = gen_lowpart (SImode, operands[0]);
4627     operands[2] = gen_reg_rtx (SImode);
4628     operands[5] = gen_lowpart (QImode, operands[2]);
4629   }"
4630 )
4631
4632 ;; Subroutine to store a half word integer constant into memory.
4633 (define_expand "storeinthi"
4634   [(set (match_operand 0 "" "")
4635         (match_operand 1 "" ""))
4636    (set (match_dup 3) (match_dup 2))]
4637   "TARGET_ARM"
4638   "
4639   {
4640     HOST_WIDE_INT value = INTVAL (operands[1]);
4641     rtx addr = XEXP (operands[0], 0);
4642     rtx op0 = operands[0];
4643     enum rtx_code code = GET_CODE (addr);
4644
4645     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4646         || code == MINUS)
4647       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4648
4649     operands[1] = gen_reg_rtx (SImode);
4650     if (BYTES_BIG_ENDIAN)
4651       {
4652         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4653         if ((value & 255) == ((value >> 8) & 255))
4654           operands[2] = operands[1];
4655         else
4656           {
4657             operands[2] = gen_reg_rtx (SImode);
4658             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4659           }
4660       }
4661     else
4662       {
4663         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4664         if ((value & 255) == ((value >> 8) & 255))
4665           operands[2] = operands[1];
4666         else
4667           {
4668             operands[2] = gen_reg_rtx (SImode);
4669             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4670           }
4671       }
4672
4673     operands[3] = adjust_address (op0, QImode, 1);
4674     operands[0] = adjust_address (operands[0], QImode, 0);
4675     operands[2] = gen_lowpart (QImode, operands[2]);
4676     operands[1] = gen_lowpart (QImode, operands[1]);
4677   }"
4678 )
4679
4680 (define_expand "storehi_single_op"
4681   [(set (match_operand:HI 0 "memory_operand" "")
4682         (match_operand:HI 1 "general_operand" ""))]
4683   "TARGET_ARM && arm_arch4"
4684   "
4685   if (!s_register_operand (operands[1], HImode))
4686     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4687   "
4688 )
4689
4690 (define_expand "movhi"
4691   [(set (match_operand:HI 0 "general_operand" "")
4692         (match_operand:HI 1 "general_operand" ""))]
4693   "TARGET_EITHER"
4694   "
4695   if (TARGET_ARM)
4696     {
4697       if (!no_new_pseudos)
4698         {
4699           if (GET_CODE (operands[0]) == MEM)
4700             {
4701               if (arm_arch4)
4702                 {
4703                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4704                   DONE;
4705                 }
4706               if (GET_CODE (operands[1]) == CONST_INT)
4707                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4708               else
4709                 {
4710                   if (GET_CODE (operands[1]) == MEM)
4711                     operands[1] = force_reg (HImode, operands[1]);
4712                   if (BYTES_BIG_ENDIAN)
4713                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4714                   else
4715                    emit_insn (gen_storehi (operands[1], operands[0]));
4716                 }
4717               DONE;
4718             }
4719           /* Sign extend a constant, and keep it in an SImode reg.  */
4720           else if (GET_CODE (operands[1]) == CONST_INT)
4721             {
4722               rtx reg = gen_reg_rtx (SImode);
4723               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4724
4725               /* If the constant is already valid, leave it alone.  */
4726               if (!const_ok_for_arm (val))
4727                 {
4728                   /* If setting all the top bits will make the constant 
4729                      loadable in a single instruction, then set them.  
4730                      Otherwise, sign extend the number.  */
4731
4732                   if (const_ok_for_arm (~(val | ~0xffff)))
4733                     val |= ~0xffff;
4734                   else if (val & 0x8000)
4735                     val |= ~0xffff;
4736                 }
4737
4738               emit_insn (gen_movsi (reg, GEN_INT (val)));
4739               operands[1] = gen_lowpart (HImode, reg);
4740             }
4741           else if (arm_arch4 && optimize && !no_new_pseudos
4742                    && GET_CODE (operands[1]) == MEM)
4743             {
4744               rtx reg = gen_reg_rtx (SImode);
4745
4746               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4747               operands[1] = gen_lowpart (HImode, reg);
4748             }
4749           else if (!arm_arch4)
4750             {
4751               if (GET_CODE (operands[1]) == MEM)
4752                 {
4753                   rtx base;
4754                   rtx offset = const0_rtx;
4755                   rtx reg = gen_reg_rtx (SImode);
4756
4757                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4758                        || (GET_CODE (base) == PLUS
4759                            && (GET_CODE (offset = XEXP (base, 1))
4760                                == CONST_INT)
4761                            && ((INTVAL(offset) & 1) != 1)
4762                            && GET_CODE (base = XEXP (base, 0)) == REG))
4763                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4764                     {
4765                       rtx new;
4766
4767                       new = widen_memory_access (operands[1], SImode,
4768                                                  ((INTVAL (offset) & ~3)
4769                                                   - INTVAL (offset)));
4770                       emit_insn (gen_movsi (reg, new));
4771                       if (((INTVAL (offset) & 2) != 0)
4772                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4773                         {
4774                           rtx reg2 = gen_reg_rtx (SImode);
4775
4776                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4777                           reg = reg2;
4778                         }
4779                     }
4780                   else
4781                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4782
4783                   operands[1] = gen_lowpart (HImode, reg);
4784                }
4785            }
4786         }
4787       /* Handle loading a large integer during reload.  */
4788       else if (GET_CODE (operands[1]) == CONST_INT
4789                && !const_ok_for_arm (INTVAL (operands[1]))
4790                && !const_ok_for_arm (~INTVAL (operands[1])))
4791         {
4792           /* Writing a constant to memory needs a scratch, which should
4793              be handled with SECONDARY_RELOADs.  */
4794           gcc_assert (GET_CODE (operands[0]) == REG);
4795
4796           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4797           emit_insn (gen_movsi (operands[0], operands[1]));
4798           DONE;
4799        }
4800     }
4801   else /* TARGET_THUMB */
4802     {
4803       if (!no_new_pseudos)
4804         {
4805           if (GET_CODE (operands[1]) == CONST_INT)
4806             {
4807               rtx reg = gen_reg_rtx (SImode);
4808
4809               emit_insn (gen_movsi (reg, operands[1]));
4810               operands[1] = gen_lowpart (HImode, reg);
4811             }
4812
4813           /* ??? We shouldn't really get invalid addresses here, but this can
4814              happen if we are passed a SP (never OK for HImode/QImode) or 
4815              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4816              HImode/QImode) relative address.  */
4817           /* ??? This should perhaps be fixed elsewhere, for instance, in
4818              fixup_stack_1, by checking for other kinds of invalid addresses,
4819              e.g. a bare reference to a virtual register.  This may confuse the
4820              alpha though, which must handle this case differently.  */
4821           if (GET_CODE (operands[0]) == MEM
4822               && !memory_address_p (GET_MODE (operands[0]),
4823                                     XEXP (operands[0], 0)))
4824             operands[0]
4825               = replace_equiv_address (operands[0],
4826                                        copy_to_reg (XEXP (operands[0], 0)));
4827    
4828           if (GET_CODE (operands[1]) == MEM
4829               && !memory_address_p (GET_MODE (operands[1]),
4830                                     XEXP (operands[1], 0)))
4831             operands[1]
4832               = replace_equiv_address (operands[1],
4833                                        copy_to_reg (XEXP (operands[1], 0)));
4834
4835           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4836             {
4837               rtx reg = gen_reg_rtx (SImode);
4838
4839               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4840               operands[1] = gen_lowpart (HImode, reg);
4841             }
4842
4843           if (GET_CODE (operands[0]) == MEM)
4844             operands[1] = force_reg (HImode, operands[1]);
4845         }
4846       else if (GET_CODE (operands[1]) == CONST_INT
4847                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4848         {
4849           /* Handle loading a large integer during reload.  */
4850
4851           /* Writing a constant to memory needs a scratch, which should
4852              be handled with SECONDARY_RELOADs.  */
4853           gcc_assert (GET_CODE (operands[0]) == REG);
4854
4855           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4856           emit_insn (gen_movsi (operands[0], operands[1]));
4857           DONE;
4858         }
4859     }
4860   "
4861 )
4862
4863 (define_insn "*thumb_movhi_insn"
4864   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4865         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4866   "TARGET_THUMB
4867    && (   register_operand (operands[0], HImode)
4868        || register_operand (operands[1], HImode))"
4869   "*
4870   switch (which_alternative)
4871     {
4872     case 0: return \"add        %0, %1, #0\";
4873     case 2: return \"strh       %1, %0\";
4874     case 3: return \"mov        %0, %1\";
4875     case 4: return \"mov        %0, %1\";
4876     case 5: return \"mov        %0, %1\";
4877     default: gcc_unreachable ();
4878     case 1:
4879       /* The stack pointer can end up being taken as an index register.
4880           Catch this case here and deal with it.  */
4881       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4882           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4883           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4884         {
4885           rtx ops[2];
4886           ops[0] = operands[0];
4887           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4888       
4889           output_asm_insn (\"mov        %0, %1\", ops);
4890
4891           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4892     
4893         }
4894       return \"ldrh     %0, %1\";
4895     }"
4896   [(set_attr "length" "2,4,2,2,2,2")
4897    (set_attr "type" "*,load1,store1,*,*,*")]
4898 )
4899
4900
4901 (define_expand "movhi_bytes"
4902   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4903    (set (match_dup 3)
4904         (zero_extend:SI (match_dup 6)))
4905    (set (match_operand:SI 0 "" "")
4906          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4907   "TARGET_ARM"
4908   "
4909   {
4910     rtx mem1, mem2;
4911     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4912
4913     mem1 = change_address (operands[1], QImode, addr);
4914     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4915     operands[0] = gen_lowpart (SImode, operands[0]);
4916     operands[1] = mem1;
4917     operands[2] = gen_reg_rtx (SImode);
4918     operands[3] = gen_reg_rtx (SImode);
4919     operands[6] = mem2;
4920
4921     if (BYTES_BIG_ENDIAN)
4922       {
4923         operands[4] = operands[2];
4924         operands[5] = operands[3];
4925       }
4926     else
4927       {
4928         operands[4] = operands[3];
4929         operands[5] = operands[2];
4930       }
4931   }"
4932 )
4933
4934 (define_expand "movhi_bigend"
4935   [(set (match_dup 2)
4936         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4937                    (const_int 16)))
4938    (set (match_dup 3)
4939         (ashiftrt:SI (match_dup 2) (const_int 16)))
4940    (set (match_operand:HI 0 "s_register_operand" "")
4941         (match_dup 4))]
4942   "TARGET_ARM"
4943   "
4944   operands[2] = gen_reg_rtx (SImode);
4945   operands[3] = gen_reg_rtx (SImode);
4946   operands[4] = gen_lowpart (HImode, operands[3]);
4947   "
4948 )
4949
4950 ;; Pattern to recognize insn generated default case above
4951 (define_insn "*movhi_insn_arch4"
4952   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4953         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4954   "TARGET_ARM
4955    && arm_arch4
4956    && (GET_CODE (operands[1]) != CONST_INT
4957        || const_ok_for_arm (INTVAL (operands[1]))
4958        || const_ok_for_arm (~INTVAL (operands[1])))"
4959   "@
4960    mov%?\\t%0, %1\\t%@ movhi
4961    mvn%?\\t%0, #%B1\\t%@ movhi
4962    str%?h\\t%1, %0\\t%@ movhi
4963    ldr%?h\\t%0, %1\\t%@ movhi"
4964   [(set_attr "type" "*,*,store1,load1")
4965    (set_attr "predicable" "yes")
4966    (set_attr "pool_range" "*,*,*,256")
4967    (set_attr "neg_pool_range" "*,*,*,244")]
4968 )
4969
4970 (define_insn "*movhi_bytes"
4971   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4972         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4973   "TARGET_ARM"
4974   "@
4975    mov%?\\t%0, %1\\t%@ movhi
4976    mvn%?\\t%0, #%B1\\t%@ movhi"
4977   [(set_attr "predicable" "yes")]
4978 )
4979
4980 (define_expand "thumb_movhi_clobber"
4981   [(set (match_operand:HI     0 "memory_operand"   "")
4982         (match_operand:HI     1 "register_operand" ""))
4983    (clobber (match_operand:DI 2 "register_operand" ""))]
4984   "TARGET_THUMB"
4985   "
4986   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
4987       && REGNO (operands[1]) <= LAST_LO_REGNUM)
4988     {
4989       emit_insn (gen_movhi (operands[0], operands[1]));
4990       DONE;
4991     }
4992   /* XXX Fixme, need to handle other cases here as well.  */
4993   gcc_unreachable ();
4994   "
4995 )
4996         
4997 ;; We use a DImode scratch because we may occasionally need an additional
4998 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4999 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5000 (define_expand "reload_outhi"
5001   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5002               (match_operand:HI 1 "s_register_operand"        "r")
5003               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5004   "TARGET_EITHER"
5005   "if (TARGET_ARM)
5006      arm_reload_out_hi (operands);
5007    else
5008      thumb_reload_out_hi (operands);
5009   DONE;
5010   "
5011 )
5012
5013 (define_expand "reload_inhi"
5014   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5015               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5016               (match_operand:DI 2 "s_register_operand" "=&r")])]
5017   "TARGET_EITHER"
5018   "
5019   if (TARGET_ARM)
5020     arm_reload_in_hi (operands);
5021   else
5022     thumb_reload_out_hi (operands);
5023   DONE;
5024 ")
5025
5026 (define_expand "movqi"
5027   [(set (match_operand:QI 0 "general_operand" "")
5028         (match_operand:QI 1 "general_operand" ""))]
5029   "TARGET_EITHER"
5030   "
5031   /* Everything except mem = const or mem = mem can be done easily */
5032
5033   if (!no_new_pseudos)
5034     {
5035       if (GET_CODE (operands[1]) == CONST_INT)
5036         {
5037           rtx reg = gen_reg_rtx (SImode);
5038
5039           emit_insn (gen_movsi (reg, operands[1]));
5040           operands[1] = gen_lowpart (QImode, reg);
5041         }
5042
5043       if (TARGET_THUMB)
5044         {
5045           /* ??? We shouldn't really get invalid addresses here, but this can
5046              happen if we are passed a SP (never OK for HImode/QImode) or
5047              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5048              HImode/QImode) relative address.  */
5049           /* ??? This should perhaps be fixed elsewhere, for instance, in
5050              fixup_stack_1, by checking for other kinds of invalid addresses,
5051              e.g. a bare reference to a virtual register.  This may confuse the
5052              alpha though, which must handle this case differently.  */
5053           if (GET_CODE (operands[0]) == MEM
5054               && !memory_address_p (GET_MODE (operands[0]),
5055                                      XEXP (operands[0], 0)))
5056             operands[0]
5057               = replace_equiv_address (operands[0],
5058                                        copy_to_reg (XEXP (operands[0], 0)));
5059           if (GET_CODE (operands[1]) == MEM
5060               && !memory_address_p (GET_MODE (operands[1]),
5061                                     XEXP (operands[1], 0)))
5062              operands[1]
5063                = replace_equiv_address (operands[1],
5064                                         copy_to_reg (XEXP (operands[1], 0)));
5065         }
5066
5067       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5068         {
5069           rtx reg = gen_reg_rtx (SImode);
5070
5071           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5072           operands[1] = gen_lowpart (QImode, reg);
5073         }
5074
5075       if (GET_CODE (operands[0]) == MEM)
5076         operands[1] = force_reg (QImode, operands[1]);
5077     }
5078   else if (TARGET_THUMB
5079            && GET_CODE (operands[1]) == CONST_INT
5080            && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5081     {
5082       /* Handle loading a large integer during reload.  */
5083
5084       /* Writing a constant to memory needs a scratch, which should
5085          be handled with SECONDARY_RELOADs.  */
5086       gcc_assert (GET_CODE (operands[0]) == REG);
5087
5088       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5089       emit_insn (gen_movsi (operands[0], operands[1]));
5090       DONE;
5091     }
5092   "
5093 )
5094
5095
5096 (define_insn "*arm_movqi_insn"
5097   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5098         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5099   "TARGET_ARM
5100    && (   register_operand (operands[0], QImode)
5101        || register_operand (operands[1], QImode))"
5102   "@
5103    mov%?\\t%0, %1
5104    mvn%?\\t%0, #%B1
5105    ldr%?b\\t%0, %1
5106    str%?b\\t%1, %0"
5107   [(set_attr "type" "*,*,load1,store1")
5108    (set_attr "predicable" "yes")]
5109 )
5110
5111 (define_insn "*thumb_movqi_insn"
5112   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5113         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5114   "TARGET_THUMB
5115    && (   register_operand (operands[0], QImode)
5116        || register_operand (operands[1], QImode))"
5117   "@
5118    add\\t%0, %1, #0
5119    ldrb\\t%0, %1
5120    strb\\t%1, %0
5121    mov\\t%0, %1
5122    mov\\t%0, %1
5123    mov\\t%0, %1"
5124   [(set_attr "length" "2")
5125    (set_attr "type" "*,load1,store1,*,*,*")
5126    (set_attr "pool_range" "*,32,*,*,*,*")]
5127 )
5128
5129 (define_expand "movsf"
5130   [(set (match_operand:SF 0 "general_operand" "")
5131         (match_operand:SF 1 "general_operand" ""))]
5132   "TARGET_EITHER"
5133   "
5134   if (TARGET_ARM)
5135     {
5136       if (GET_CODE (operands[0]) == MEM)
5137         operands[1] = force_reg (SFmode, operands[1]);
5138     }
5139   else /* TARGET_THUMB */
5140     {
5141       if (!no_new_pseudos)
5142         {
5143            if (GET_CODE (operands[0]) != REG)
5144              operands[1] = force_reg (SFmode, operands[1]);
5145         }
5146     }
5147   "
5148 )
5149
5150 ;; Transform a floating-point move of a constant into a core register into
5151 ;; an SImode operation.
5152 (define_split
5153   [(set (match_operand:SF 0 "arm_general_register_operand" "")
5154         (match_operand:SF 1 "immediate_operand" ""))]
5155   "TARGET_ARM
5156    && reload_completed
5157    && GET_CODE (operands[1]) == CONST_DOUBLE"
5158   [(set (match_dup 2) (match_dup 3))]
5159   "
5160   operands[2] = gen_lowpart (SImode, operands[0]);
5161   operands[3] = gen_lowpart (SImode, operands[1]);
5162   if (operands[2] == 0 || operands[3] == 0)
5163     FAIL;
5164   "
5165 )
5166
5167 (define_insn "*arm_movsf_soft_insn"
5168   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5169         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5170   "TARGET_ARM
5171    && TARGET_SOFT_FLOAT
5172    && (GET_CODE (operands[0]) != MEM
5173        || register_operand (operands[1], SFmode))"
5174   "@
5175    mov%?\\t%0, %1
5176    ldr%?\\t%0, %1\\t%@ float
5177    str%?\\t%1, %0\\t%@ float"
5178   [(set_attr "length" "4,4,4")
5179    (set_attr "predicable" "yes")
5180    (set_attr "type" "*,load1,store1")
5181    (set_attr "pool_range" "*,4096,*")
5182    (set_attr "neg_pool_range" "*,4084,*")]
5183 )
5184
5185 ;;; ??? This should have alternatives for constants.
5186 (define_insn "*thumb_movsf_insn"
5187   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5188         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5189   "TARGET_THUMB
5190    && (   register_operand (operands[0], SFmode) 
5191        || register_operand (operands[1], SFmode))"
5192   "@
5193    add\\t%0, %1, #0
5194    ldmia\\t%1, {%0}
5195    stmia\\t%0, {%1}
5196    ldr\\t%0, %1
5197    str\\t%1, %0
5198    mov\\t%0, %1
5199    mov\\t%0, %1"
5200   [(set_attr "length" "2")
5201    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5202    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5203 )
5204
5205 (define_expand "movdf"
5206   [(set (match_operand:DF 0 "general_operand" "")
5207         (match_operand:DF 1 "general_operand" ""))]
5208   "TARGET_EITHER"
5209   "
5210   if (TARGET_ARM)
5211     {
5212       if (GET_CODE (operands[0]) == MEM)
5213         operands[1] = force_reg (DFmode, operands[1]);
5214     }
5215   else /* TARGET_THUMB */
5216     {
5217       if (!no_new_pseudos)
5218         {
5219           if (GET_CODE (operands[0]) != REG)
5220             operands[1] = force_reg (DFmode, operands[1]);
5221         }
5222     }
5223   "
5224 )
5225
5226 ;; Reloading a df mode value stored in integer regs to memory can require a
5227 ;; scratch reg.
5228 (define_expand "reload_outdf"
5229   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5230    (match_operand:DF 1 "s_register_operand" "r")
5231    (match_operand:SI 2 "s_register_operand" "=&r")]
5232   "TARGET_ARM"
5233   "
5234   {
5235     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5236
5237     if (code == REG)
5238       operands[2] = XEXP (operands[0], 0);
5239     else if (code == POST_INC || code == PRE_DEC)
5240       {
5241         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5242         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5243         emit_insn (gen_movdi (operands[0], operands[1]));
5244         DONE;
5245       }
5246     else if (code == PRE_INC)
5247       {
5248         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5249
5250         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5251         operands[2] = reg;
5252       }
5253     else if (code == POST_DEC)
5254       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5255     else
5256       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5257                              XEXP (XEXP (operands[0], 0), 1)));
5258
5259     emit_insn (gen_rtx_SET (VOIDmode,
5260                             replace_equiv_address (operands[0], operands[2]),
5261                             operands[1]));
5262
5263     if (code == POST_DEC)
5264       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5265
5266     DONE;
5267   }"
5268 )
5269
5270 (define_insn "*movdf_soft_insn"
5271   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5272         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5273   "TARGET_ARM && TARGET_SOFT_FLOAT
5274    && (   register_operand (operands[0], DFmode)
5275        || register_operand (operands[1], DFmode))"
5276   "*
5277   switch (which_alternative)
5278     {
5279     case 0:
5280     case 1:
5281     case 2:
5282       return \"#\";
5283     default:
5284       return output_move_double (operands);
5285     }
5286   "
5287   [(set_attr "length" "8,12,16,8,8")
5288    (set_attr "type" "*,*,*,load2,store2")
5289    (set_attr "pool_range" "1020")
5290    (set_attr "neg_pool_range" "1008")]
5291 )
5292
5293 ;;; ??? This should have alternatives for constants.
5294 ;;; ??? This was originally identical to the movdi_insn pattern.
5295 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5296 ;;; thumb_reorg with a memory reference.
5297 (define_insn "*thumb_movdf_insn"
5298   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5299         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5300   "TARGET_THUMB
5301    && (   register_operand (operands[0], DFmode)
5302        || register_operand (operands[1], DFmode))"
5303   "*
5304   switch (which_alternative)
5305     {
5306     default:
5307     case 0:
5308       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5309         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5310       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5311     case 1:
5312       return \"ldmia\\t%1, {%0, %H0}\";
5313     case 2:
5314       return \"stmia\\t%0, {%1, %H1}\";
5315     case 3:
5316       return thumb_load_double_from_address (operands);
5317     case 4:
5318       operands[2] = gen_rtx_MEM (SImode,
5319                                  plus_constant (XEXP (operands[0], 0), 4));
5320       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5321       return \"\";
5322     case 5:
5323       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5324         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5325       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5326     }
5327   "
5328   [(set_attr "length" "4,2,2,6,4,4")
5329    (set_attr "type" "*,load2,store2,load2,store2,*")
5330    (set_attr "pool_range" "*,*,*,1020,*,*")]
5331 )
5332
5333 (define_expand "movxf"
5334   [(set (match_operand:XF 0 "general_operand" "")
5335         (match_operand:XF 1 "general_operand" ""))]
5336   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5337   "
5338   if (GET_CODE (operands[0]) == MEM)
5339     operands[1] = force_reg (XFmode, operands[1]);
5340   "
5341 )
5342
5343 ;; Vector Moves
5344 (define_expand "movv2si"
5345   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5346         (match_operand:V2SI 1 "general_operand" ""))]
5347   "TARGET_REALLY_IWMMXT"
5348 {
5349 })
5350
5351 (define_expand "movv4hi"
5352   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5353         (match_operand:V4HI 1 "general_operand" ""))]
5354   "TARGET_REALLY_IWMMXT"
5355 {
5356 })
5357
5358 (define_expand "movv8qi"
5359   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5360         (match_operand:V8QI 1 "general_operand" ""))]
5361   "TARGET_REALLY_IWMMXT"
5362 {
5363 })
5364 \f
5365
5366 ;; load- and store-multiple insns
5367 ;; The arm can load/store any set of registers, provided that they are in
5368 ;; ascending order; but that is beyond GCC so stick with what it knows.
5369
5370 (define_expand "load_multiple"
5371   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5372                           (match_operand:SI 1 "" ""))
5373                      (use (match_operand:SI 2 "" ""))])]
5374   "TARGET_ARM"
5375 {
5376   HOST_WIDE_INT offset = 0;
5377
5378   /* Support only fixed point registers.  */
5379   if (GET_CODE (operands[2]) != CONST_INT
5380       || INTVAL (operands[2]) > 14
5381       || INTVAL (operands[2]) < 2
5382       || GET_CODE (operands[1]) != MEM
5383       || GET_CODE (operands[0]) != REG
5384       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5385       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5386     FAIL;
5387
5388   operands[3]
5389     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5390                              force_reg (SImode, XEXP (operands[1], 0)),
5391                              TRUE, FALSE, operands[1], &offset);
5392 })
5393
5394 ;; Load multiple with write-back
5395
5396 (define_insn "*ldmsi_postinc4"
5397   [(match_parallel 0 "load_multiple_operation"
5398     [(set (match_operand:SI 1 "s_register_operand" "=r")
5399           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5400                    (const_int 16)))
5401      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5402           (mem:SI (match_dup 2)))
5403      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5404           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5405      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5406           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5407      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5408           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5409   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5410   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5411   [(set_attr "type" "load4")
5412    (set_attr "predicable" "yes")]
5413 )
5414
5415 (define_insn "*ldmsi_postinc4_thumb"
5416   [(match_parallel 0 "load_multiple_operation"
5417     [(set (match_operand:SI 1 "s_register_operand" "=l")
5418           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5419                    (const_int 16)))
5420      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5421           (mem:SI (match_dup 2)))
5422      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5423           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5424      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5425           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5426      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5427           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5428   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5429   "ldmia\\t%1!, {%3, %4, %5, %6}"
5430   [(set_attr "type" "load4")]
5431 )
5432
5433 (define_insn "*ldmsi_postinc3"
5434   [(match_parallel 0 "load_multiple_operation"
5435     [(set (match_operand:SI 1 "s_register_operand" "=r")
5436           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5437                    (const_int 12)))
5438      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5439           (mem:SI (match_dup 2)))
5440      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5441           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5442      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5443           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5444   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5445   "ldm%?ia\\t%1!, {%3, %4, %5}"
5446   [(set_attr "type" "load3")
5447    (set_attr "predicable" "yes")]
5448 )
5449
5450 (define_insn "*ldmsi_postinc2"
5451   [(match_parallel 0 "load_multiple_operation"
5452     [(set (match_operand:SI 1 "s_register_operand" "=r")
5453           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5454                    (const_int 8)))
5455      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5456           (mem:SI (match_dup 2)))
5457      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5458           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5459   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5460   "ldm%?ia\\t%1!, {%3, %4}"
5461   [(set_attr "type" "load2")
5462    (set_attr "predicable" "yes")]
5463 )
5464
5465 ;; Ordinary load multiple
5466
5467 (define_insn "*ldmsi4"
5468   [(match_parallel 0 "load_multiple_operation"
5469     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5470           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5471      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5472           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5473      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5474           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5475      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5476           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5477   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5478   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5479   [(set_attr "type" "load4")
5480    (set_attr "predicable" "yes")]
5481 )
5482
5483 (define_insn "*ldmsi3"
5484   [(match_parallel 0 "load_multiple_operation"
5485     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5486           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5487      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5488           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5489      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5490           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5491   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5492   "ldm%?ia\\t%1, {%2, %3, %4}"
5493   [(set_attr "type" "load3")
5494    (set_attr "predicable" "yes")]
5495 )
5496
5497 (define_insn "*ldmsi2"
5498   [(match_parallel 0 "load_multiple_operation"
5499     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5500           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5501      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5502           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5503   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5504   "ldm%?ia\\t%1, {%2, %3}"
5505   [(set_attr "type" "load2")
5506    (set_attr "predicable" "yes")]
5507 )
5508
5509 (define_expand "store_multiple"
5510   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5511                           (match_operand:SI 1 "" ""))
5512                      (use (match_operand:SI 2 "" ""))])]
5513   "TARGET_ARM"
5514 {
5515   HOST_WIDE_INT offset = 0;
5516
5517   /* Support only fixed point registers.  */
5518   if (GET_CODE (operands[2]) != CONST_INT
5519       || INTVAL (operands[2]) > 14
5520       || INTVAL (operands[2]) < 2
5521       || GET_CODE (operands[1]) != REG
5522       || GET_CODE (operands[0]) != MEM
5523       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5524       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5525     FAIL;
5526
5527   operands[3]
5528     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5529                               force_reg (SImode, XEXP (operands[0], 0)),
5530                               TRUE, FALSE, operands[0], &offset);
5531 })
5532
5533 ;; Store multiple with write-back
5534
5535 (define_insn "*stmsi_postinc4"
5536   [(match_parallel 0 "store_multiple_operation"
5537     [(set (match_operand:SI 1 "s_register_operand" "=r")
5538           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5539                    (const_int 16)))
5540      (set (mem:SI (match_dup 2))
5541           (match_operand:SI 3 "arm_hard_register_operand" ""))
5542      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5543           (match_operand:SI 4 "arm_hard_register_operand" ""))
5544      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5545           (match_operand:SI 5 "arm_hard_register_operand" ""))
5546      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5547           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5548   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5549   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5550   [(set_attr "predicable" "yes")
5551    (set_attr "type" "store4")]
5552 )
5553
5554 (define_insn "*stmsi_postinc4_thumb"
5555   [(match_parallel 0 "store_multiple_operation"
5556     [(set (match_operand:SI 1 "s_register_operand" "=l")
5557           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5558                    (const_int 16)))
5559      (set (mem:SI (match_dup 2))
5560           (match_operand:SI 3 "arm_hard_register_operand" ""))
5561      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5562           (match_operand:SI 4 "arm_hard_register_operand" ""))
5563      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5564           (match_operand:SI 5 "arm_hard_register_operand" ""))
5565      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5566           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5567   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5568   "stmia\\t%1!, {%3, %4, %5, %6}"
5569   [(set_attr "type" "store4")]
5570 )
5571
5572 (define_insn "*stmsi_postinc3"
5573   [(match_parallel 0 "store_multiple_operation"
5574     [(set (match_operand:SI 1 "s_register_operand" "=r")
5575           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5576                    (const_int 12)))
5577      (set (mem:SI (match_dup 2))
5578           (match_operand:SI 3 "arm_hard_register_operand" ""))
5579      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5580           (match_operand:SI 4 "arm_hard_register_operand" ""))
5581      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5582           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5583   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5584   "stm%?ia\\t%1!, {%3, %4, %5}"
5585   [(set_attr "predicable" "yes")
5586    (set_attr "type" "store3")]
5587 )
5588
5589 (define_insn "*stmsi_postinc2"
5590   [(match_parallel 0 "store_multiple_operation"
5591     [(set (match_operand:SI 1 "s_register_operand" "=r")
5592           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5593                    (const_int 8)))
5594      (set (mem:SI (match_dup 2))
5595           (match_operand:SI 3 "arm_hard_register_operand" ""))
5596      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5597           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5598   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5599   "stm%?ia\\t%1!, {%3, %4}"
5600   [(set_attr "predicable" "yes")
5601    (set_attr "type" "store2")]
5602 )
5603
5604 ;; Ordinary store multiple
5605
5606 (define_insn "*stmsi4"
5607   [(match_parallel 0 "store_multiple_operation"
5608     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5609           (match_operand:SI 2 "arm_hard_register_operand" ""))
5610      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5611           (match_operand:SI 3 "arm_hard_register_operand" ""))
5612      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5613           (match_operand:SI 4 "arm_hard_register_operand" ""))
5614      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5615           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5616   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5617   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5618   [(set_attr "predicable" "yes")
5619    (set_attr "type" "store4")]
5620 )
5621
5622 (define_insn "*stmsi3"
5623   [(match_parallel 0 "store_multiple_operation"
5624     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5625           (match_operand:SI 2 "arm_hard_register_operand" ""))
5626      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5627           (match_operand:SI 3 "arm_hard_register_operand" ""))
5628      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5629           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5630   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5631   "stm%?ia\\t%1, {%2, %3, %4}"
5632   [(set_attr "predicable" "yes")
5633    (set_attr "type" "store3")]
5634 )
5635
5636 (define_insn "*stmsi2"
5637   [(match_parallel 0 "store_multiple_operation"
5638     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5639           (match_operand:SI 2 "arm_hard_register_operand" ""))
5640      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5641           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5642   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5643   "stm%?ia\\t%1, {%2, %3}"
5644   [(set_attr "predicable" "yes")
5645    (set_attr "type" "store2")]
5646 )
5647
5648 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5649 ;; We could let this apply for blocks of less than this, but it clobbers so
5650 ;; many registers that there is then probably a better way.
5651
5652 (define_expand "movmemqi"
5653   [(match_operand:BLK 0 "general_operand" "")
5654    (match_operand:BLK 1 "general_operand" "")
5655    (match_operand:SI 2 "const_int_operand" "")
5656    (match_operand:SI 3 "const_int_operand" "")]
5657   "TARGET_EITHER"
5658   "
5659   if (TARGET_ARM)
5660     {
5661       if (arm_gen_movmemqi (operands))
5662         DONE;
5663       FAIL;
5664     }
5665   else /* TARGET_THUMB */
5666     {
5667       if (   INTVAL (operands[3]) != 4
5668           || INTVAL (operands[2]) > 48)
5669         FAIL;
5670
5671       thumb_expand_movmemqi (operands);
5672       DONE;
5673     }
5674   "
5675 )
5676
5677 ;; Thumb block-move insns
5678
5679 (define_insn "movmem12b"
5680   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5681         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5682    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5683         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5684    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5685         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5686    (set (match_operand:SI 0 "register_operand" "=l")
5687         (plus:SI (match_dup 2) (const_int 12)))
5688    (set (match_operand:SI 1 "register_operand" "=l")
5689         (plus:SI (match_dup 3) (const_int 12)))
5690    (clobber (match_scratch:SI 4 "=&l"))
5691    (clobber (match_scratch:SI 5 "=&l"))
5692    (clobber (match_scratch:SI 6 "=&l"))]
5693   "TARGET_THUMB"
5694   "* return thumb_output_move_mem_multiple (3, operands);"
5695   [(set_attr "length" "4")
5696    ; This isn't entirely accurate...  It loads as well, but in terms of
5697    ; scheduling the following insn it is better to consider it as a store
5698    (set_attr "type" "store3")]
5699 )
5700
5701 (define_insn "movmem8b"
5702   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5703         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5704    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5705         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5706    (set (match_operand:SI 0 "register_operand" "=l")
5707         (plus:SI (match_dup 2) (const_int 8)))
5708    (set (match_operand:SI 1 "register_operand" "=l")
5709         (plus:SI (match_dup 3) (const_int 8)))
5710    (clobber (match_scratch:SI 4 "=&l"))
5711    (clobber (match_scratch:SI 5 "=&l"))]
5712   "TARGET_THUMB"
5713   "* return thumb_output_move_mem_multiple (2, operands);"
5714   [(set_attr "length" "4")
5715    ; This isn't entirely accurate...  It loads as well, but in terms of
5716    ; scheduling the following insn it is better to consider it as a store
5717    (set_attr "type" "store2")]
5718 )
5719
5720 \f
5721
5722 ;; Compare & branch insns
5723 ;; The range calculations are based as follows:
5724 ;; For forward branches, the address calculation returns the address of
5725 ;; the next instruction.  This is 2 beyond the branch instruction.
5726 ;; For backward branches, the address calculation returns the address of
5727 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5728 ;; instruction for the shortest sequence, and 4 before the branch instruction
5729 ;; if we have to jump around an unconditional branch.
5730 ;; To the basic branch range the PC offset must be added (this is +4).
5731 ;; So for forward branches we have 
5732 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5733 ;; And for backward branches we have 
5734 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5735 ;;
5736 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5737 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5738
5739 (define_expand "cbranchsi4"
5740   [(set (pc) (if_then_else
5741               (match_operator 0 "arm_comparison_operator"
5742                [(match_operand:SI 1 "s_register_operand" "")
5743                 (match_operand:SI 2 "nonmemory_operand" "")])
5744               (label_ref (match_operand 3 "" ""))
5745               (pc)))]
5746   "TARGET_THUMB"
5747   "
5748   if (thumb_cmpneg_operand (operands[2], SImode))
5749     {
5750       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5751                                               operands[3], operands[0]));
5752       DONE;
5753     }
5754   if (!thumb_cmp_operand (operands[2], SImode))
5755     operands[2] = force_reg (SImode, operands[2]);
5756   ")
5757
5758 (define_insn "*cbranchsi4_insn"
5759   [(set (pc) (if_then_else
5760               (match_operator 0 "arm_comparison_operator"
5761                [(match_operand:SI 1 "s_register_operand" "l,*h")
5762                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5763               (label_ref (match_operand 3 "" ""))
5764               (pc)))]
5765   "TARGET_THUMB"
5766   "*
5767   output_asm_insn (\"cmp\\t%1, %2\", operands);
5768
5769   switch (get_attr_length (insn))
5770     {
5771     case 4:  return \"b%d0\\t%l3\";
5772     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5773     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5774     }
5775   "
5776   [(set (attr "far_jump")
5777         (if_then_else
5778             (eq_attr "length" "8")
5779             (const_string "yes")
5780             (const_string "no")))
5781    (set (attr "length") 
5782         (if_then_else
5783             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5784                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5785             (const_int 4)
5786             (if_then_else
5787                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5788                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5789                 (const_int 6)
5790                 (const_int 8))))]
5791 )
5792
5793 (define_insn "cbranchsi4_scratch"
5794   [(set (pc) (if_then_else
5795               (match_operator 4 "arm_comparison_operator"
5796                [(match_operand:SI 1 "s_register_operand" "l,0")
5797                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5798               (label_ref (match_operand 3 "" ""))
5799               (pc)))
5800    (clobber (match_scratch:SI 0 "=l,l"))]
5801   "TARGET_THUMB"
5802   "*
5803   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5804
5805   switch (get_attr_length (insn))
5806     {
5807     case 4:  return \"b%d4\\t%l3\";
5808     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5809     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5810     }
5811   "
5812   [(set (attr "far_jump")
5813         (if_then_else
5814             (eq_attr "length" "8")
5815             (const_string "yes")
5816             (const_string "no")))
5817    (set (attr "length") 
5818         (if_then_else
5819             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5820                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5821             (const_int 4)
5822             (if_then_else
5823                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5824                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5825                 (const_int 6)
5826                 (const_int 8))))]
5827 )
5828 (define_insn "*movsi_cbranchsi4"
5829   [(set (pc)
5830         (if_then_else
5831          (match_operator 3 "arm_comparison_operator"
5832           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5833            (const_int 0)])
5834          (label_ref (match_operand 2 "" ""))
5835          (pc)))
5836    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5837         (match_dup 1))]
5838   "TARGET_THUMB"
5839   "*{
5840   if (which_alternative == 0)
5841     output_asm_insn (\"cmp\t%0, #0\", operands);
5842   else if (which_alternative == 1)
5843     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5844   else
5845     {
5846       output_asm_insn (\"cmp\t%1, #0\", operands);
5847       if (which_alternative == 2)
5848         output_asm_insn (\"mov\t%0, %1\", operands);
5849       else
5850         output_asm_insn (\"str\t%1, %0\", operands);
5851     }
5852   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5853     {
5854     case 4:  return \"b%d3\\t%l2\";
5855     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5856     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5857     }
5858   }"
5859   [(set (attr "far_jump")
5860         (if_then_else
5861             (ior (and (gt (symbol_ref ("which_alternative"))
5862                           (const_int 1))
5863                       (eq_attr "length" "8"))
5864                  (eq_attr "length" "10"))
5865             (const_string "yes")
5866             (const_string "no")))
5867    (set (attr "length")
5868      (if_then_else
5869        (le (symbol_ref ("which_alternative"))
5870                        (const_int 1))
5871        (if_then_else
5872          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5873               (le (minus (match_dup 2) (pc)) (const_int 256)))
5874          (const_int 4)
5875          (if_then_else
5876            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5877                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5878            (const_int 6)
5879            (const_int 8)))
5880        (if_then_else
5881          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5882               (le (minus (match_dup 2) (pc)) (const_int 256)))
5883          (const_int 6)
5884          (if_then_else
5885            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5886                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5887            (const_int 8)
5888            (const_int 10)))))]
5889 )
5890
5891 (define_insn "*negated_cbranchsi4"
5892   [(set (pc)
5893         (if_then_else
5894          (match_operator 0 "equality_operator"
5895           [(match_operand:SI 1 "s_register_operand" "l")
5896            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5897          (label_ref (match_operand 3 "" ""))
5898          (pc)))]
5899   "TARGET_THUMB"
5900   "*
5901   output_asm_insn (\"cmn\\t%1, %2\", operands);
5902   switch (get_attr_length (insn))
5903     {
5904     case 4:  return \"b%d0\\t%l3\";
5905     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5906     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5907     }
5908   "
5909   [(set (attr "far_jump")
5910         (if_then_else
5911             (eq_attr "length" "8")
5912             (const_string "yes")
5913             (const_string "no")))
5914    (set (attr "length") 
5915         (if_then_else
5916             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5917                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5918             (const_int 4)
5919             (if_then_else
5920                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5921                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5922                 (const_int 6)
5923                 (const_int 8))))]
5924 )
5925
5926 (define_insn "*tbit_cbranch"
5927   [(set (pc)
5928         (if_then_else
5929          (match_operator 0 "equality_operator"
5930           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5931                             (const_int 1)
5932                             (match_operand:SI 2 "const_int_operand" "i"))
5933            (const_int 0)])
5934          (label_ref (match_operand 3 "" ""))
5935          (pc)))
5936    (clobber (match_scratch:SI 4 "=l"))]
5937   "TARGET_THUMB"
5938   "*
5939   {
5940   rtx op[3];
5941   op[0] = operands[4];
5942   op[1] = operands[1];
5943   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5944
5945   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5946   switch (get_attr_length (insn))
5947     {
5948     case 4:  return \"b%d0\\t%l3\";
5949     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5950     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5951     }
5952   }"
5953   [(set (attr "far_jump")
5954         (if_then_else
5955             (eq_attr "length" "8")
5956             (const_string "yes")
5957             (const_string "no")))
5958    (set (attr "length") 
5959         (if_then_else
5960             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5961                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5962             (const_int 4)
5963             (if_then_else
5964                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5965                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5966                 (const_int 6)
5967                 (const_int 8))))]
5968 )
5969   
5970 (define_insn "*tstsi3_cbranch"
5971   [(set (pc)
5972         (if_then_else
5973          (match_operator 3 "equality_operator"
5974           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5975                    (match_operand:SI 1 "s_register_operand" "l"))
5976            (const_int 0)])
5977          (label_ref (match_operand 2 "" ""))
5978          (pc)))]
5979   "TARGET_THUMB"
5980   "*
5981   {
5982   output_asm_insn (\"tst\\t%0, %1\", operands);
5983   switch (get_attr_length (insn))
5984     {
5985     case 4:  return \"b%d3\\t%l2\";
5986     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5987     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5988     }
5989   }"
5990   [(set (attr "far_jump")
5991         (if_then_else
5992             (eq_attr "length" "8")
5993             (const_string "yes")
5994             (const_string "no")))
5995    (set (attr "length") 
5996         (if_then_else
5997             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5998                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5999             (const_int 4)
6000             (if_then_else
6001                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6002                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6003                 (const_int 6)
6004                 (const_int 8))))]
6005 )
6006   
6007 (define_insn "*andsi3_cbranch"
6008   [(set (pc)
6009         (if_then_else
6010          (match_operator 5 "equality_operator"
6011           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6012                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6013            (const_int 0)])
6014          (label_ref (match_operand 4 "" ""))
6015          (pc)))
6016    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6017         (and:SI (match_dup 2) (match_dup 3)))
6018    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6019   "TARGET_THUMB"
6020   "*
6021   {
6022   if (which_alternative == 0)
6023     output_asm_insn (\"and\\t%0, %3\", operands);
6024   else if (which_alternative == 1)
6025     {
6026       output_asm_insn (\"and\\t%1, %3\", operands);
6027       output_asm_insn (\"mov\\t%0, %1\", operands);
6028     }
6029   else
6030     {
6031       output_asm_insn (\"and\\t%1, %3\", operands);
6032       output_asm_insn (\"str\\t%1, %0\", operands);
6033     }
6034
6035   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6036     {
6037     case 4:  return \"b%d5\\t%l4\";
6038     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6039     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6040     }
6041   }"
6042   [(set (attr "far_jump")
6043         (if_then_else
6044             (ior (and (eq (symbol_ref ("which_alternative"))
6045                           (const_int 0))
6046                       (eq_attr "length" "8"))
6047                  (eq_attr "length" "10"))
6048             (const_string "yes")
6049             (const_string "no")))
6050    (set (attr "length")
6051      (if_then_else
6052        (eq (symbol_ref ("which_alternative"))
6053                        (const_int 0))
6054        (if_then_else
6055          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6056               (le (minus (match_dup 4) (pc)) (const_int 256)))
6057          (const_int 4)
6058          (if_then_else
6059            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6060                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6061            (const_int 6)
6062            (const_int 8)))
6063        (if_then_else
6064          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6065               (le (minus (match_dup 4) (pc)) (const_int 256)))
6066          (const_int 6)
6067          (if_then_else
6068            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6069                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6070            (const_int 8)
6071            (const_int 10)))))]
6072 )
6073
6074 (define_insn "*orrsi3_cbranch_scratch"
6075   [(set (pc)
6076         (if_then_else
6077          (match_operator 4 "equality_operator"
6078           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6079                    (match_operand:SI 2 "s_register_operand" "l"))
6080            (const_int 0)])
6081          (label_ref (match_operand 3 "" ""))
6082          (pc)))
6083    (clobber (match_scratch:SI 0 "=l"))]
6084   "TARGET_THUMB"
6085   "*
6086   {
6087   output_asm_insn (\"orr\\t%0, %2\", operands);
6088   switch (get_attr_length (insn))
6089     {
6090     case 4:  return \"b%d4\\t%l3\";
6091     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6092     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6093     }
6094   }"
6095   [(set (attr "far_jump")
6096         (if_then_else
6097             (eq_attr "length" "8")
6098             (const_string "yes")
6099             (const_string "no")))
6100    (set (attr "length") 
6101         (if_then_else
6102             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6103                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6104             (const_int 4)
6105             (if_then_else
6106                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6107                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6108                 (const_int 6)
6109                 (const_int 8))))]
6110 )
6111   
6112 (define_insn "*orrsi3_cbranch"
6113   [(set (pc)
6114         (if_then_else
6115          (match_operator 5 "equality_operator"
6116           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6117                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6118            (const_int 0)])
6119          (label_ref (match_operand 4 "" ""))
6120          (pc)))
6121    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6122         (ior:SI (match_dup 2) (match_dup 3)))
6123    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6124   "TARGET_THUMB"
6125   "*
6126   {
6127   if (which_alternative == 0)
6128     output_asm_insn (\"orr\\t%0, %3\", operands);
6129   else if (which_alternative == 1)
6130     {
6131       output_asm_insn (\"orr\\t%1, %3\", operands);
6132       output_asm_insn (\"mov\\t%0, %1\", operands);
6133     }
6134   else
6135     {
6136       output_asm_insn (\"orr\\t%1, %3\", operands);
6137       output_asm_insn (\"str\\t%1, %0\", operands);
6138     }
6139
6140   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6141     {
6142     case 4:  return \"b%d5\\t%l4\";
6143     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6144     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6145     }
6146   }"
6147   [(set (attr "far_jump")
6148         (if_then_else
6149             (ior (and (eq (symbol_ref ("which_alternative"))
6150                           (const_int 0))
6151                       (eq_attr "length" "8"))
6152                  (eq_attr "length" "10"))
6153             (const_string "yes")
6154             (const_string "no")))
6155    (set (attr "length")
6156      (if_then_else
6157        (eq (symbol_ref ("which_alternative"))
6158                        (const_int 0))
6159        (if_then_else
6160          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6161               (le (minus (match_dup 4) (pc)) (const_int 256)))
6162          (const_int 4)
6163          (if_then_else
6164            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6165                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6166            (const_int 6)
6167            (const_int 8)))
6168        (if_then_else
6169          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6170               (le (minus (match_dup 4) (pc)) (const_int 256)))
6171          (const_int 6)
6172          (if_then_else
6173            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6174                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6175            (const_int 8)
6176            (const_int 10)))))]
6177 )
6178
6179 (define_insn "*xorsi3_cbranch_scratch"
6180   [(set (pc)
6181         (if_then_else
6182          (match_operator 4 "equality_operator"
6183           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6184                    (match_operand:SI 2 "s_register_operand" "l"))
6185            (const_int 0)])
6186          (label_ref (match_operand 3 "" ""))
6187          (pc)))
6188    (clobber (match_scratch:SI 0 "=l"))]
6189   "TARGET_THUMB"
6190   "*
6191   {
6192   output_asm_insn (\"eor\\t%0, %2\", operands);
6193   switch (get_attr_length (insn))
6194     {
6195     case 4:  return \"b%d4\\t%l3\";
6196     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6197     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6198     }
6199   }"
6200   [(set (attr "far_jump")
6201         (if_then_else
6202             (eq_attr "length" "8")
6203             (const_string "yes")
6204             (const_string "no")))
6205    (set (attr "length") 
6206         (if_then_else
6207             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6208                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6209             (const_int 4)
6210             (if_then_else
6211                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6212                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6213                 (const_int 6)
6214                 (const_int 8))))]
6215 )
6216   
6217 (define_insn "*xorsi3_cbranch"
6218   [(set (pc)
6219         (if_then_else
6220          (match_operator 5 "equality_operator"
6221           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6222                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6223            (const_int 0)])
6224          (label_ref (match_operand 4 "" ""))
6225          (pc)))
6226    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6227         (xor:SI (match_dup 2) (match_dup 3)))
6228    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6229   "TARGET_THUMB"
6230   "*
6231   {
6232   if (which_alternative == 0)
6233     output_asm_insn (\"eor\\t%0, %3\", operands);
6234   else if (which_alternative == 1)
6235     {
6236       output_asm_insn (\"eor\\t%1, %3\", operands);
6237       output_asm_insn (\"mov\\t%0, %1\", operands);
6238     }
6239   else
6240     {
6241       output_asm_insn (\"eor\\t%1, %3\", operands);
6242       output_asm_insn (\"str\\t%1, %0\", operands);
6243     }
6244
6245   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6246     {
6247     case 4:  return \"b%d5\\t%l4\";
6248     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6249     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6250     }
6251   }"
6252   [(set (attr "far_jump")
6253         (if_then_else
6254             (ior (and (eq (symbol_ref ("which_alternative"))
6255                           (const_int 0))
6256                       (eq_attr "length" "8"))
6257                  (eq_attr "length" "10"))
6258             (const_string "yes")
6259             (const_string "no")))
6260    (set (attr "length")
6261      (if_then_else
6262        (eq (symbol_ref ("which_alternative"))
6263                        (const_int 0))
6264        (if_then_else
6265          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6266               (le (minus (match_dup 4) (pc)) (const_int 256)))
6267          (const_int 4)
6268          (if_then_else
6269            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6270                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6271            (const_int 6)
6272            (const_int 8)))
6273        (if_then_else
6274          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6275               (le (minus (match_dup 4) (pc)) (const_int 256)))
6276          (const_int 6)
6277          (if_then_else
6278            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6279                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6280            (const_int 8)
6281            (const_int 10)))))]
6282 )
6283
6284 (define_insn "*bicsi3_cbranch_scratch"
6285   [(set (pc)
6286         (if_then_else
6287          (match_operator 4 "equality_operator"
6288           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6289                    (match_operand:SI 1 "s_register_operand" "0"))
6290            (const_int 0)])
6291          (label_ref (match_operand 3 "" ""))
6292          (pc)))
6293    (clobber (match_scratch:SI 0 "=l"))]
6294   "TARGET_THUMB"
6295   "*
6296   {
6297   output_asm_insn (\"bic\\t%0, %2\", operands);
6298   switch (get_attr_length (insn))
6299     {
6300     case 4:  return \"b%d4\\t%l3\";
6301     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6302     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6303     }
6304   }"
6305   [(set (attr "far_jump")
6306         (if_then_else
6307             (eq_attr "length" "8")
6308             (const_string "yes")
6309             (const_string "no")))
6310    (set (attr "length") 
6311         (if_then_else
6312             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6313                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6314             (const_int 4)
6315             (if_then_else
6316                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6317                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6318                 (const_int 6)
6319                 (const_int 8))))]
6320 )
6321   
6322 (define_insn "*bicsi3_cbranch"
6323   [(set (pc)
6324         (if_then_else
6325          (match_operator 5 "equality_operator"
6326           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6327                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6328            (const_int 0)])
6329          (label_ref (match_operand 4 "" ""))
6330          (pc)))
6331    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6332         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6333    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6334   "TARGET_THUMB"
6335   "*
6336   {
6337   if (which_alternative == 0)
6338     output_asm_insn (\"bic\\t%0, %3\", operands);
6339   else if (which_alternative <= 2)
6340     {
6341       output_asm_insn (\"bic\\t%1, %3\", operands);
6342       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6343          conditions again, since we're only testing for equality.  */
6344       output_asm_insn (\"mov\\t%0, %1\", operands);
6345     }
6346   else
6347     {
6348       output_asm_insn (\"bic\\t%1, %3\", operands);
6349       output_asm_insn (\"str\\t%1, %0\", operands);
6350     }
6351
6352   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6353     {
6354     case 4:  return \"b%d5\\t%l4\";
6355     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6356     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6357     }
6358   }"
6359   [(set (attr "far_jump")
6360         (if_then_else
6361             (ior (and (eq (symbol_ref ("which_alternative"))
6362                           (const_int 0))
6363                       (eq_attr "length" "8"))
6364                  (eq_attr "length" "10"))
6365             (const_string "yes")
6366             (const_string "no")))
6367    (set (attr "length")
6368      (if_then_else
6369        (eq (symbol_ref ("which_alternative"))
6370                        (const_int 0))
6371        (if_then_else
6372          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6373               (le (minus (match_dup 4) (pc)) (const_int 256)))
6374          (const_int 4)
6375          (if_then_else
6376            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6377                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6378            (const_int 6)
6379            (const_int 8)))
6380        (if_then_else
6381          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6382               (le (minus (match_dup 4) (pc)) (const_int 256)))
6383          (const_int 6)
6384          (if_then_else
6385            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6386                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6387            (const_int 8)
6388            (const_int 10)))))]
6389 )
6390
6391 (define_insn "*cbranchne_decr1"
6392   [(set (pc)
6393         (if_then_else (match_operator 3 "equality_operator"
6394                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6395                         (const_int 0)])
6396                       (label_ref (match_operand 4 "" ""))
6397                       (pc)))
6398    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6399         (plus:SI (match_dup 2) (const_int -1)))
6400    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6401   "TARGET_THUMB"
6402   "*
6403    {
6404      rtx cond[2];
6405      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6406                                 ? GEU : LTU),
6407                                VOIDmode, operands[2], const1_rtx);
6408      cond[1] = operands[4];
6409
6410      if (which_alternative == 0)
6411        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6412      else if (which_alternative == 1)
6413        {
6414          /* We must provide an alternative for a hi reg because reload 
6415             cannot handle output reloads on a jump instruction, but we
6416             can't subtract into that.  Fortunately a mov from lo to hi
6417             does not clobber the condition codes.  */
6418          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6419          output_asm_insn (\"mov\\t%0, %1\", operands);
6420        }
6421      else
6422        {
6423          /* Similarly, but the target is memory.  */
6424          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6425          output_asm_insn (\"str\\t%1, %0\", operands);
6426        }
6427
6428      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6429        {
6430          case 4:
6431            output_asm_insn (\"b%d0\\t%l1\", cond);
6432            return \"\";
6433          case 6:
6434            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6435            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6436          default:
6437            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6438            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6439        }
6440    }
6441   "
6442   [(set (attr "far_jump")
6443         (if_then_else
6444             (ior (and (eq (symbol_ref ("which_alternative"))
6445                           (const_int 0))
6446                       (eq_attr "length" "8"))
6447                  (eq_attr "length" "10"))
6448             (const_string "yes")
6449             (const_string "no")))
6450    (set_attr_alternative "length"
6451       [
6452        ;; Alternative 0
6453        (if_then_else
6454          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6455               (le (minus (match_dup 4) (pc)) (const_int 256)))
6456          (const_int 4)
6457          (if_then_else
6458            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6459                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6460            (const_int 6)
6461            (const_int 8)))
6462        ;; Alternative 1
6463        (if_then_else
6464          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6465               (le (minus (match_dup 4) (pc)) (const_int 256)))
6466          (const_int 6)
6467          (if_then_else
6468            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6469                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6470            (const_int 8)
6471            (const_int 10)))
6472        ;; Alternative 2
6473        (if_then_else
6474          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6475               (le (minus (match_dup 4) (pc)) (const_int 256)))
6476          (const_int 6)
6477          (if_then_else
6478            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6479                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6480            (const_int 8)
6481            (const_int 10)))
6482        ;; Alternative 3
6483        (if_then_else
6484          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6485               (le (minus (match_dup 4) (pc)) (const_int 256)))
6486          (const_int 6)
6487          (if_then_else
6488            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6489                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6490            (const_int 8)
6491            (const_int 10)))])]
6492 )
6493
6494 (define_insn "*addsi3_cbranch"
6495   [(set (pc)
6496         (if_then_else
6497          (match_operator 4 "comparison_operator"
6498           [(plus:SI
6499             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6500             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6501            (const_int 0)])
6502          (label_ref (match_operand 5 "" ""))
6503          (pc)))
6504    (set
6505     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6506     (plus:SI (match_dup 2) (match_dup 3)))
6507    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6508   "TARGET_THUMB
6509    && (GET_CODE (operands[4]) == EQ
6510        || GET_CODE (operands[4]) == NE
6511        || GET_CODE (operands[4]) == GE
6512        || GET_CODE (operands[4]) == LT)"
6513   "*
6514    {
6515      rtx cond[3];
6516
6517      
6518      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6519      cond[1] = operands[2];
6520      cond[2] = operands[3];
6521
6522      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6523        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6524      else
6525        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6526
6527      if (which_alternative >= 3
6528          && which_alternative < 4)
6529        output_asm_insn (\"mov\\t%0, %1\", operands);
6530      else if (which_alternative >= 4)
6531        output_asm_insn (\"str\\t%1, %0\", operands);
6532
6533      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6534        {
6535          case 4:
6536            return \"b%d4\\t%l5\";
6537          case 6:
6538            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6539          default:
6540            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6541        }
6542    }
6543   "
6544   [(set (attr "far_jump")
6545         (if_then_else
6546             (ior (and (lt (symbol_ref ("which_alternative"))
6547                           (const_int 3))
6548                       (eq_attr "length" "8"))
6549                  (eq_attr "length" "10"))
6550             (const_string "yes")
6551             (const_string "no")))
6552    (set (attr "length")
6553      (if_then_else
6554        (lt (symbol_ref ("which_alternative"))
6555                        (const_int 3))
6556        (if_then_else
6557          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6558               (le (minus (match_dup 5) (pc)) (const_int 256)))
6559          (const_int 4)
6560          (if_then_else
6561            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6562                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6563            (const_int 6)
6564            (const_int 8)))
6565        (if_then_else
6566          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6567               (le (minus (match_dup 5) (pc)) (const_int 256)))
6568          (const_int 6)
6569          (if_then_else
6570            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6571                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6572            (const_int 8)
6573            (const_int 10)))))]
6574 )
6575
6576 (define_insn "*addsi3_cbranch_scratch"
6577   [(set (pc)
6578         (if_then_else
6579          (match_operator 3 "comparison_operator"
6580           [(plus:SI
6581             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6582             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6583            (const_int 0)])
6584          (label_ref (match_operand 4 "" ""))
6585          (pc)))
6586    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6587   "TARGET_THUMB
6588    && (GET_CODE (operands[3]) == EQ
6589        || GET_CODE (operands[3]) == NE
6590        || GET_CODE (operands[3]) == GE
6591        || GET_CODE (operands[3]) == LT)"
6592   "*
6593    {
6594      switch (which_alternative)
6595        {
6596        case 0:
6597          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6598          break;
6599        case 1:
6600          output_asm_insn (\"cmn\t%1, %2\", operands);
6601          break;
6602        case 2:
6603          if (INTVAL (operands[2]) < 0)
6604            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6605          else
6606            output_asm_insn (\"add\t%0, %1, %2\", operands);
6607          break;
6608        case 3:
6609          if (INTVAL (operands[2]) < 0)
6610            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6611          else
6612            output_asm_insn (\"add\t%0, %0, %2\", operands);
6613          break;
6614        }
6615
6616      switch (get_attr_length (insn))
6617        {
6618          case 4:
6619            return \"b%d3\\t%l4\";
6620          case 6:
6621            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6622          default:
6623            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6624        }
6625    }
6626   "
6627   [(set (attr "far_jump")
6628         (if_then_else
6629             (eq_attr "length" "8")
6630             (const_string "yes")
6631             (const_string "no")))
6632    (set (attr "length")
6633        (if_then_else
6634          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6635               (le (minus (match_dup 4) (pc)) (const_int 256)))
6636          (const_int 4)
6637          (if_then_else
6638            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6639                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6640            (const_int 6)
6641            (const_int 8))))]
6642 )
6643
6644 (define_insn "*subsi3_cbranch"
6645   [(set (pc)
6646         (if_then_else
6647          (match_operator 4 "comparison_operator"
6648           [(minus:SI
6649             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6650             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6651            (const_int 0)])
6652          (label_ref (match_operand 5 "" ""))
6653          (pc)))
6654    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6655         (minus:SI (match_dup 2) (match_dup 3)))
6656    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6657   "TARGET_THUMB
6658    && (GET_CODE (operands[4]) == EQ
6659        || GET_CODE (operands[4]) == NE
6660        || GET_CODE (operands[4]) == GE
6661        || GET_CODE (operands[4]) == LT)"
6662   "*
6663    {
6664      if (which_alternative == 0)
6665        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6666      else if (which_alternative == 1)
6667        {
6668          /* We must provide an alternative for a hi reg because reload 
6669             cannot handle output reloads on a jump instruction, but we
6670             can't subtract into that.  Fortunately a mov from lo to hi
6671             does not clobber the condition codes.  */
6672          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6673          output_asm_insn (\"mov\\t%0, %1\", operands);
6674        }
6675      else
6676        {
6677          /* Similarly, but the target is memory.  */
6678          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6679          output_asm_insn (\"str\\t%1, %0\", operands);
6680        }
6681
6682      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6683        {
6684          case 4:
6685            return \"b%d4\\t%l5\";
6686          case 6:
6687            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6688          default:
6689            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6690        }
6691    }
6692   "
6693   [(set (attr "far_jump")
6694         (if_then_else
6695             (ior (and (eq (symbol_ref ("which_alternative"))
6696                           (const_int 0))
6697                       (eq_attr "length" "8"))
6698                  (eq_attr "length" "10"))
6699             (const_string "yes")
6700             (const_string "no")))
6701    (set (attr "length")
6702      (if_then_else
6703        (eq (symbol_ref ("which_alternative"))
6704                        (const_int 0))
6705        (if_then_else
6706          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6707               (le (minus (match_dup 5) (pc)) (const_int 256)))
6708          (const_int 4)
6709          (if_then_else
6710            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6711                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6712            (const_int 6)
6713            (const_int 8)))
6714        (if_then_else
6715          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6716               (le (minus (match_dup 5) (pc)) (const_int 256)))
6717          (const_int 6)
6718          (if_then_else
6719            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6720                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6721            (const_int 8)
6722            (const_int 10)))))]
6723 )
6724
6725 (define_insn "*subsi3_cbranch_scratch"
6726   [(set (pc)
6727         (if_then_else
6728          (match_operator 0 "arm_comparison_operator"
6729           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6730                      (match_operand:SI 2 "nonmemory_operand" "l"))
6731            (const_int 0)])
6732          (label_ref (match_operand 3 "" ""))
6733          (pc)))]
6734   "TARGET_THUMB
6735    && (GET_CODE (operands[0]) == EQ
6736        || GET_CODE (operands[0]) == NE
6737        || GET_CODE (operands[0]) == GE
6738        || GET_CODE (operands[0]) == LT)"
6739   "*
6740   output_asm_insn (\"cmp\\t%1, %2\", operands);
6741   switch (get_attr_length (insn))
6742     {
6743     case 4:  return \"b%d0\\t%l3\";
6744     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6745     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6746     }
6747   "
6748   [(set (attr "far_jump")
6749         (if_then_else
6750             (eq_attr "length" "8")
6751             (const_string "yes")
6752             (const_string "no")))
6753    (set (attr "length") 
6754         (if_then_else
6755             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6756                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6757             (const_int 4)
6758             (if_then_else
6759                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6760                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6761                 (const_int 6)
6762                 (const_int 8))))]
6763 )
6764
6765 ;; Comparison and test insns
6766
6767 (define_expand "cmpsi"
6768   [(match_operand:SI 0 "s_register_operand" "")
6769    (match_operand:SI 1 "arm_add_operand" "")]
6770   "TARGET_ARM"
6771   "{
6772     arm_compare_op0 = operands[0];
6773     arm_compare_op1 = operands[1];
6774     DONE;
6775   }"
6776 )
6777
6778 (define_expand "cmpsf"
6779   [(match_operand:SF 0 "s_register_operand" "")
6780    (match_operand:SF 1 "arm_float_compare_operand" "")]
6781   "TARGET_ARM && TARGET_HARD_FLOAT"
6782   "
6783   arm_compare_op0 = operands[0];
6784   arm_compare_op1 = operands[1];
6785   DONE;
6786   "
6787 )
6788
6789 (define_expand "cmpdf"
6790   [(match_operand:DF 0 "s_register_operand" "")
6791    (match_operand:DF 1 "arm_float_compare_operand" "")]
6792   "TARGET_ARM && TARGET_HARD_FLOAT"
6793   "
6794   arm_compare_op0 = operands[0];
6795   arm_compare_op1 = operands[1];
6796   DONE;
6797   "
6798 )
6799
6800 (define_insn "*arm_cmpsi_insn"
6801   [(set (reg:CC CC_REGNUM)
6802         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6803                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6804   "TARGET_ARM"
6805   "@
6806    cmp%?\\t%0, %1
6807    cmn%?\\t%0, #%n1"
6808   [(set_attr "conds" "set")]
6809 )
6810
6811 (define_insn "*cmpsi_shiftsi"
6812   [(set (reg:CC CC_REGNUM)
6813         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6814                     (match_operator:SI  3 "shift_operator"
6815                      [(match_operand:SI 1 "s_register_operand" "r")
6816                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6817   "TARGET_ARM"
6818   "cmp%?\\t%0, %1%S3"
6819   [(set_attr "conds" "set")
6820    (set_attr "shift" "1")
6821    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6822                       (const_string "alu_shift")
6823                       (const_string "alu_shift_reg")))]
6824 )
6825
6826 (define_insn "*cmpsi_shiftsi_swp"
6827   [(set (reg:CC_SWP CC_REGNUM)
6828         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6829                          [(match_operand:SI 1 "s_register_operand" "r")
6830                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6831                         (match_operand:SI 0 "s_register_operand" "r")))]
6832   "TARGET_ARM"
6833   "cmp%?\\t%0, %1%S3"
6834   [(set_attr "conds" "set")
6835    (set_attr "shift" "1")
6836    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6837                       (const_string "alu_shift")
6838                       (const_string "alu_shift_reg")))]
6839 )
6840
6841 (define_insn "*cmpsi_negshiftsi_si"
6842   [(set (reg:CC_Z CC_REGNUM)
6843         (compare:CC_Z
6844          (neg:SI (match_operator:SI 1 "shift_operator"
6845                     [(match_operand:SI 2 "s_register_operand" "r")
6846                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6847          (match_operand:SI 0 "s_register_operand" "r")))]
6848   "TARGET_ARM"
6849   "cmn%?\\t%0, %2%S1"
6850   [(set_attr "conds" "set")
6851    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6852                                     (const_string "alu_shift")
6853                                     (const_string "alu_shift_reg")))]
6854 )
6855
6856 ;; Cirrus SF compare instruction
6857 (define_insn "*cirrus_cmpsf"
6858   [(set (reg:CCFP CC_REGNUM)
6859         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6860                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6861   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6862   "cfcmps%?\\tr15, %V0, %V1"
6863   [(set_attr "type"   "mav_farith")
6864    (set_attr "cirrus" "compare")]
6865 )
6866
6867 ;; Cirrus DF compare instruction
6868 (define_insn "*cirrus_cmpdf"
6869   [(set (reg:CCFP CC_REGNUM)
6870         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6871                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6872   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6873   "cfcmpd%?\\tr15, %V0, %V1"
6874   [(set_attr "type"   "mav_farith")
6875    (set_attr "cirrus" "compare")]
6876 )
6877
6878 ;; Cirrus DI compare instruction
6879 (define_expand "cmpdi"
6880   [(match_operand:DI 0 "cirrus_fp_register" "")
6881    (match_operand:DI 1 "cirrus_fp_register" "")]
6882   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6883   "{
6884      arm_compare_op0 = operands[0];
6885      arm_compare_op1 = operands[1];
6886      DONE;
6887    }")
6888
6889 (define_insn "*cirrus_cmpdi"
6890   [(set (reg:CC CC_REGNUM)
6891         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6892                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6893   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6894   "cfcmp64%?\\tr15, %V0, %V1"
6895   [(set_attr "type"   "mav_farith")
6896    (set_attr "cirrus" "compare")]
6897 )
6898
6899 ; This insn allows redundant compares to be removed by cse, nothing should
6900 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6901 ; is deleted later on. The match_dup will match the mode here, so that
6902 ; mode changes of the condition codes aren't lost by this even though we don't
6903 ; specify what they are.
6904
6905 (define_insn "*deleted_compare"
6906   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6907   "TARGET_ARM"
6908   "\\t%@ deleted compare"
6909   [(set_attr "conds" "set")
6910    (set_attr "length" "0")]
6911 )
6912
6913 \f
6914 ;; Conditional branch insns
6915
6916 (define_expand "beq"
6917   [(set (pc)
6918         (if_then_else (eq (match_dup 1) (const_int 0))
6919                       (label_ref (match_operand 0 "" ""))
6920                       (pc)))]
6921   "TARGET_ARM"
6922   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6923 )
6924
6925 (define_expand "bne"
6926   [(set (pc)
6927         (if_then_else (ne (match_dup 1) (const_int 0))
6928                       (label_ref (match_operand 0 "" ""))
6929                       (pc)))]
6930   "TARGET_ARM"
6931   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6932 )
6933
6934 (define_expand "bgt"
6935   [(set (pc)
6936         (if_then_else (gt (match_dup 1) (const_int 0))
6937                       (label_ref (match_operand 0 "" ""))
6938                       (pc)))]
6939   "TARGET_ARM"
6940   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6941 )
6942
6943 (define_expand "ble"
6944   [(set (pc)
6945         (if_then_else (le (match_dup 1) (const_int 0))
6946                       (label_ref (match_operand 0 "" ""))
6947                       (pc)))]
6948   "TARGET_ARM"
6949   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6950 )
6951
6952 (define_expand "bge"
6953   [(set (pc)
6954         (if_then_else (ge (match_dup 1) (const_int 0))
6955                       (label_ref (match_operand 0 "" ""))
6956                       (pc)))]
6957   "TARGET_ARM"
6958   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6959 )
6960
6961 (define_expand "blt"
6962   [(set (pc)
6963         (if_then_else (lt (match_dup 1) (const_int 0))
6964                       (label_ref (match_operand 0 "" ""))
6965                       (pc)))]
6966   "TARGET_ARM"
6967   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6968 )
6969
6970 (define_expand "bgtu"
6971   [(set (pc)
6972         (if_then_else (gtu (match_dup 1) (const_int 0))
6973                       (label_ref (match_operand 0 "" ""))
6974                       (pc)))]
6975   "TARGET_ARM"
6976   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6977 )
6978
6979 (define_expand "bleu"
6980   [(set (pc)
6981         (if_then_else (leu (match_dup 1) (const_int 0))
6982                       (label_ref (match_operand 0 "" ""))
6983                       (pc)))]
6984   "TARGET_ARM"
6985   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6986 )
6987
6988 (define_expand "bgeu"
6989   [(set (pc)
6990         (if_then_else (geu (match_dup 1) (const_int 0))
6991                       (label_ref (match_operand 0 "" ""))
6992                       (pc)))]
6993   "TARGET_ARM"
6994   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6995 )
6996
6997 (define_expand "bltu"
6998   [(set (pc)
6999         (if_then_else (ltu (match_dup 1) (const_int 0))
7000                       (label_ref (match_operand 0 "" ""))
7001                       (pc)))]
7002   "TARGET_ARM"
7003   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7004 )
7005
7006 (define_expand "bunordered"
7007   [(set (pc)
7008         (if_then_else (unordered (match_dup 1) (const_int 0))
7009                       (label_ref (match_operand 0 "" ""))
7010                       (pc)))]
7011   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7012   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7013                                       arm_compare_op1);"
7014 )
7015
7016 (define_expand "bordered"
7017   [(set (pc)
7018         (if_then_else (ordered (match_dup 1) (const_int 0))
7019                       (label_ref (match_operand 0 "" ""))
7020                       (pc)))]
7021   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7022   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7023                                       arm_compare_op1);"
7024 )
7025
7026 (define_expand "bungt"
7027   [(set (pc)
7028         (if_then_else (ungt (match_dup 1) (const_int 0))
7029                       (label_ref (match_operand 0 "" ""))
7030                       (pc)))]
7031   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7032   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7033 )
7034
7035 (define_expand "bunlt"
7036   [(set (pc)
7037         (if_then_else (unlt (match_dup 1) (const_int 0))
7038                       (label_ref (match_operand 0 "" ""))
7039                       (pc)))]
7040   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7041   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7042 )
7043
7044 (define_expand "bunge"
7045   [(set (pc)
7046         (if_then_else (unge (match_dup 1) (const_int 0))
7047                       (label_ref (match_operand 0 "" ""))
7048                       (pc)))]
7049   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7050   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7051 )
7052
7053 (define_expand "bunle"
7054   [(set (pc)
7055         (if_then_else (unle (match_dup 1) (const_int 0))
7056                       (label_ref (match_operand 0 "" ""))
7057                       (pc)))]
7058   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7059   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7060 )
7061
7062 ;; The following two patterns need two branch instructions, since there is
7063 ;; no single instruction that will handle all cases.
7064 (define_expand "buneq"
7065   [(set (pc)
7066         (if_then_else (uneq (match_dup 1) (const_int 0))
7067                       (label_ref (match_operand 0 "" ""))
7068                       (pc)))]
7069   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7070   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7071 )
7072
7073 (define_expand "bltgt"
7074   [(set (pc)
7075         (if_then_else (ltgt (match_dup 1) (const_int 0))
7076                       (label_ref (match_operand 0 "" ""))
7077                       (pc)))]
7078   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7079   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7080 )
7081
7082 ;;
7083 ;; Patterns to match conditional branch insns.
7084 ;;
7085
7086 ; Special pattern to match UNEQ.
7087 (define_insn "*arm_buneq"
7088   [(set (pc)
7089         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7090                       (label_ref (match_operand 0 "" ""))
7091                       (pc)))]
7092   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7093   "*
7094   gcc_assert (!arm_ccfsm_state);
7095
7096   return \"bvs\\t%l0\;beq\\t%l0\";
7097   "
7098   [(set_attr "conds" "jump_clob")
7099    (set_attr "length" "8")]
7100 )
7101
7102 ; Special pattern to match LTGT.
7103 (define_insn "*arm_bltgt"
7104   [(set (pc)
7105         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7106                       (label_ref (match_operand 0 "" ""))
7107                       (pc)))]
7108   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7109   "*
7110   gcc_assert (!arm_ccfsm_state);
7111
7112   return \"bmi\\t%l0\;bgt\\t%l0\";
7113   "
7114   [(set_attr "conds" "jump_clob")
7115    (set_attr "length" "8")]
7116 )
7117
7118 (define_insn "*arm_cond_branch"
7119   [(set (pc)
7120         (if_then_else (match_operator 1 "arm_comparison_operator"
7121                        [(match_operand 2 "cc_register" "") (const_int 0)])
7122                       (label_ref (match_operand 0 "" ""))
7123                       (pc)))]
7124   "TARGET_ARM"
7125   "*
7126   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7127     {
7128       arm_ccfsm_state += 2;
7129       return \"\";
7130     }
7131   return \"b%d1\\t%l0\";
7132   "
7133   [(set_attr "conds" "use")
7134    (set_attr "type" "branch")]
7135 )
7136
7137 ; Special pattern to match reversed UNEQ.
7138 (define_insn "*arm_buneq_reversed"
7139   [(set (pc)
7140         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7141                       (pc)
7142                       (label_ref (match_operand 0 "" ""))))]
7143   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7144   "*
7145   gcc_assert (!arm_ccfsm_state);
7146
7147   return \"bmi\\t%l0\;bgt\\t%l0\";
7148   "
7149   [(set_attr "conds" "jump_clob")
7150    (set_attr "length" "8")]
7151 )
7152
7153 ; Special pattern to match reversed LTGT.
7154 (define_insn "*arm_bltgt_reversed"
7155   [(set (pc)
7156         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7157                       (pc)
7158                       (label_ref (match_operand 0 "" ""))))]
7159   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7160   "*
7161   gcc_assert (!arm_ccfsm_state);
7162
7163   return \"bvs\\t%l0\;beq\\t%l0\";
7164   "
7165   [(set_attr "conds" "jump_clob")
7166    (set_attr "length" "8")]
7167 )
7168
7169 (define_insn "*arm_cond_branch_reversed"
7170   [(set (pc)
7171         (if_then_else (match_operator 1 "arm_comparison_operator"
7172                        [(match_operand 2 "cc_register" "") (const_int 0)])
7173                       (pc)
7174                       (label_ref (match_operand 0 "" ""))))]
7175   "TARGET_ARM"
7176   "*
7177   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7178     {
7179       arm_ccfsm_state += 2;
7180       return \"\";
7181     }
7182   return \"b%D1\\t%l0\";
7183   "
7184   [(set_attr "conds" "use")
7185    (set_attr "type" "branch")]
7186 )
7187
7188 \f
7189
7190 ; scc insns
7191
7192 (define_expand "seq"
7193   [(set (match_operand:SI 0 "s_register_operand" "")
7194         (eq:SI (match_dup 1) (const_int 0)))]
7195   "TARGET_ARM"
7196   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7197 )
7198
7199 (define_expand "sne"
7200   [(set (match_operand:SI 0 "s_register_operand" "")
7201         (ne:SI (match_dup 1) (const_int 0)))]
7202   "TARGET_ARM"
7203   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7204 )
7205
7206 (define_expand "sgt"
7207   [(set (match_operand:SI 0 "s_register_operand" "")
7208         (gt:SI (match_dup 1) (const_int 0)))]
7209   "TARGET_ARM"
7210   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7211 )
7212
7213 (define_expand "sle"
7214   [(set (match_operand:SI 0 "s_register_operand" "")
7215         (le:SI (match_dup 1) (const_int 0)))]
7216   "TARGET_ARM"
7217   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7218 )
7219
7220 (define_expand "sge"
7221   [(set (match_operand:SI 0 "s_register_operand" "")
7222         (ge:SI (match_dup 1) (const_int 0)))]
7223   "TARGET_ARM"
7224   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7225 )
7226
7227 (define_expand "slt"
7228   [(set (match_operand:SI 0 "s_register_operand" "")
7229         (lt:SI (match_dup 1) (const_int 0)))]
7230   "TARGET_ARM"
7231   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7232 )
7233
7234 (define_expand "sgtu"
7235   [(set (match_operand:SI 0 "s_register_operand" "")
7236         (gtu:SI (match_dup 1) (const_int 0)))]
7237   "TARGET_ARM"
7238   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7239 )
7240
7241 (define_expand "sleu"
7242   [(set (match_operand:SI 0 "s_register_operand" "")
7243         (leu:SI (match_dup 1) (const_int 0)))]
7244   "TARGET_ARM"
7245   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7246 )
7247
7248 (define_expand "sgeu"
7249   [(set (match_operand:SI 0 "s_register_operand" "")
7250         (geu:SI (match_dup 1) (const_int 0)))]
7251   "TARGET_ARM"
7252   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7253 )
7254
7255 (define_expand "sltu"
7256   [(set (match_operand:SI 0 "s_register_operand" "")
7257         (ltu:SI (match_dup 1) (const_int 0)))]
7258   "TARGET_ARM"
7259   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7260 )
7261
7262 (define_expand "sunordered"
7263   [(set (match_operand:SI 0 "s_register_operand" "")
7264         (unordered:SI (match_dup 1) (const_int 0)))]
7265   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7266   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7267                                       arm_compare_op1);"
7268 )
7269
7270 (define_expand "sordered"
7271   [(set (match_operand:SI 0 "s_register_operand" "")
7272         (ordered:SI (match_dup 1) (const_int 0)))]
7273   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7274   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7275                                       arm_compare_op1);"
7276 )
7277
7278 (define_expand "sungt"
7279   [(set (match_operand:SI 0 "s_register_operand" "")
7280         (ungt:SI (match_dup 1) (const_int 0)))]
7281   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7282   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7283                                       arm_compare_op1);"
7284 )
7285
7286 (define_expand "sunge"
7287   [(set (match_operand:SI 0 "s_register_operand" "")
7288         (unge:SI (match_dup 1) (const_int 0)))]
7289   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7290   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7291                                       arm_compare_op1);"
7292 )
7293
7294 (define_expand "sunlt"
7295   [(set (match_operand:SI 0 "s_register_operand" "")
7296         (unlt:SI (match_dup 1) (const_int 0)))]
7297   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7298   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7299                                       arm_compare_op1);"
7300 )
7301
7302 (define_expand "sunle"
7303   [(set (match_operand:SI 0 "s_register_operand" "")
7304         (unle:SI (match_dup 1) (const_int 0)))]
7305   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7306   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7307                                       arm_compare_op1);"
7308 )
7309
7310 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7311 ;;; simple ARM instructions. 
7312 ;
7313 ; (define_expand "suneq"
7314 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7315 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7316 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7317 ;   "gcc_unreachable ();"
7318 ; )
7319 ;
7320 ; (define_expand "sltgt"
7321 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7322 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7323 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7324 ;   "gcc_unreachable ();"
7325 ; )
7326
7327 (define_insn "*mov_scc"
7328   [(set (match_operand:SI 0 "s_register_operand" "=r")
7329         (match_operator:SI 1 "arm_comparison_operator"
7330          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7331   "TARGET_ARM"
7332   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7333   [(set_attr "conds" "use")
7334    (set_attr "length" "8")]
7335 )
7336
7337 (define_insn "*mov_negscc"
7338   [(set (match_operand:SI 0 "s_register_operand" "=r")
7339         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7340                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7341   "TARGET_ARM"
7342   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7343   [(set_attr "conds" "use")
7344    (set_attr "length" "8")]
7345 )
7346
7347 (define_insn "*mov_notscc"
7348   [(set (match_operand:SI 0 "s_register_operand" "=r")
7349         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7350                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7351   "TARGET_ARM"
7352   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7353   [(set_attr "conds" "use")
7354    (set_attr "length" "8")]
7355 )
7356
7357 \f
7358 ;; Conditional move insns
7359
7360 (define_expand "movsicc"
7361   [(set (match_operand:SI 0 "s_register_operand" "")
7362         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7363                          (match_operand:SI 2 "arm_not_operand" "")
7364                          (match_operand:SI 3 "arm_not_operand" "")))]
7365   "TARGET_ARM"
7366   "
7367   {
7368     enum rtx_code code = GET_CODE (operands[1]);
7369     rtx ccreg;
7370
7371     if (code == UNEQ || code == LTGT)
7372       FAIL;
7373
7374     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7375     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7376   }"
7377 )
7378
7379 (define_expand "movsfcc"
7380   [(set (match_operand:SF 0 "s_register_operand" "")
7381         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7382                          (match_operand:SF 2 "s_register_operand" "")
7383                          (match_operand:SF 3 "nonmemory_operand" "")))]
7384   "TARGET_ARM"
7385   "
7386   {
7387     enum rtx_code code = GET_CODE (operands[1]);
7388     rtx ccreg;
7389
7390     if (code == UNEQ || code == LTGT)
7391       FAIL;
7392
7393     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7394        Otherwise, ensure it is a valid FP add operand */
7395     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7396         || (!arm_float_add_operand (operands[3], SFmode)))
7397       operands[3] = force_reg (SFmode, operands[3]);
7398
7399     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7400     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7401   }"
7402 )
7403
7404 (define_expand "movdfcc"
7405   [(set (match_operand:DF 0 "s_register_operand" "")
7406         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7407                          (match_operand:DF 2 "s_register_operand" "")
7408                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7409   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7410   "
7411   {
7412     enum rtx_code code = GET_CODE (operands[1]);
7413     rtx ccreg;
7414
7415     if (code == UNEQ || code == LTGT)
7416       FAIL;
7417
7418     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7419     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7420   }"
7421 )
7422
7423 (define_insn "*movsicc_insn"
7424   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7425         (if_then_else:SI
7426          (match_operator 3 "arm_comparison_operator"
7427           [(match_operand 4 "cc_register" "") (const_int 0)])
7428          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7429          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7430   "TARGET_ARM"
7431   "@
7432    mov%D3\\t%0, %2
7433    mvn%D3\\t%0, #%B2
7434    mov%d3\\t%0, %1
7435    mvn%d3\\t%0, #%B1
7436    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7437    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7438    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7439    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7440   [(set_attr "length" "4,4,4,4,8,8,8,8")
7441    (set_attr "conds" "use")]
7442 )
7443
7444 (define_insn "*movsfcc_soft_insn"
7445   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7446         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7447                           [(match_operand 4 "cc_register" "") (const_int 0)])
7448                          (match_operand:SF 1 "s_register_operand" "0,r")
7449                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7450   "TARGET_ARM && TARGET_SOFT_FLOAT"
7451   "@
7452    mov%D3\\t%0, %2
7453    mov%d3\\t%0, %1"
7454   [(set_attr "conds" "use")]
7455 )
7456
7457 \f
7458 ;; Jump and linkage insns
7459
7460 (define_expand "jump"
7461   [(set (pc)
7462         (label_ref (match_operand 0 "" "")))]
7463   "TARGET_EITHER"
7464   ""
7465 )
7466
7467 (define_insn "*arm_jump"
7468   [(set (pc)
7469         (label_ref (match_operand 0 "" "")))]
7470   "TARGET_ARM"
7471   "*
7472   {
7473     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7474       {
7475         arm_ccfsm_state += 2;
7476         return \"\";
7477       }
7478     return \"b%?\\t%l0\";
7479   }
7480   "
7481   [(set_attr "predicable" "yes")]
7482 )
7483
7484 (define_insn "*thumb_jump"
7485   [(set (pc)
7486         (label_ref (match_operand 0 "" "")))]
7487   "TARGET_THUMB"
7488   "*
7489   if (get_attr_length (insn) == 2)
7490     return \"b\\t%l0\";
7491   return \"bl\\t%l0\\t%@ far jump\";
7492   "
7493   [(set (attr "far_jump")
7494         (if_then_else
7495             (eq_attr "length" "4")
7496             (const_string "yes")
7497             (const_string "no")))
7498    (set (attr "length") 
7499         (if_then_else
7500             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7501                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7502             (const_int 2)
7503             (const_int 4)))]
7504 )
7505
7506 (define_expand "call"
7507   [(parallel [(call (match_operand 0 "memory_operand" "")
7508                     (match_operand 1 "general_operand" ""))
7509               (use (match_operand 2 "" ""))
7510               (clobber (reg:SI LR_REGNUM))])]
7511   "TARGET_EITHER"
7512   "
7513   {
7514     rtx callee;
7515     
7516     /* In an untyped call, we can get NULL for operand 2.  */
7517     if (operands[2] == NULL_RTX)
7518       operands[2] = const0_rtx;
7519       
7520     /* This is to decide if we should generate indirect calls by loading the
7521        32 bit address of the callee into a register before performing the
7522        branch and link.  operand[2] encodes the long_call/short_call
7523        attribute of the function being called.  This attribute is set whenever
7524        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7525        is used, and the short_call attribute can also be set if function is
7526        declared as static or if it has already been defined in the current
7527        compilation unit.  See arm.c and arm.h for info about this.  The third
7528        parameter to arm_is_longcall_p is used to tell it which pattern
7529        invoked it.  */
7530     callee  = XEXP (operands[0], 0);
7531     
7532     if ((GET_CODE (callee) == SYMBOL_REF
7533          && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7534         || (GET_CODE (callee) != SYMBOL_REF
7535             && GET_CODE (callee) != REG))
7536       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7537   }"
7538 )
7539
7540 (define_insn "*call_reg_armv5"
7541   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7542          (match_operand 1 "" ""))
7543    (use (match_operand 2 "" ""))
7544    (clobber (reg:SI LR_REGNUM))]
7545   "TARGET_ARM && arm_arch5"
7546   "blx%?\\t%0"
7547   [(set_attr "type" "call")]
7548 )
7549
7550 (define_insn "*call_reg_arm"
7551   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7552          (match_operand 1 "" ""))
7553    (use (match_operand 2 "" ""))
7554    (clobber (reg:SI LR_REGNUM))]
7555   "TARGET_ARM && !arm_arch5"
7556   "*
7557   return output_call (operands);
7558   "
7559   ;; length is worst case, normally it is only two
7560   [(set_attr "length" "12")
7561    (set_attr "type" "call")]
7562 )
7563
7564 (define_insn "*call_mem"
7565   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
7566          (match_operand 1 "" ""))
7567    (use (match_operand 2 "" ""))
7568    (clobber (reg:SI LR_REGNUM))]
7569   "TARGET_ARM"
7570   "*
7571   return output_call_mem (operands);
7572   "
7573   [(set_attr "length" "12")
7574    (set_attr "type" "call")]
7575 )
7576
7577 (define_insn "*call_reg_thumb_v5"
7578   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7579          (match_operand 1 "" ""))
7580    (use (match_operand 2 "" ""))
7581    (clobber (reg:SI LR_REGNUM))]
7582   "TARGET_THUMB && arm_arch5"
7583   "blx\\t%0"
7584   [(set_attr "length" "2")
7585    (set_attr "type" "call")]
7586 )
7587
7588 (define_insn "*call_reg_thumb"
7589   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7590          (match_operand 1 "" ""))
7591    (use (match_operand 2 "" ""))
7592    (clobber (reg:SI LR_REGNUM))]
7593   "TARGET_THUMB && !arm_arch5"
7594   "*
7595   {
7596     if (!TARGET_CALLER_INTERWORKING)
7597       return thumb_call_via_reg (operands[0]);
7598     else if (operands[1] == const0_rtx)
7599       return \"bl\\t%__interwork_call_via_%0\";
7600     else if (frame_pointer_needed)
7601       return \"bl\\t%__interwork_r7_call_via_%0\";
7602     else
7603       return \"bl\\t%__interwork_r11_call_via_%0\";
7604   }"
7605   [(set_attr "type" "call")]
7606 )
7607
7608 (define_expand "call_value"
7609   [(parallel [(set (match_operand       0 "" "")
7610                    (call (match_operand 1 "memory_operand" "")
7611                          (match_operand 2 "general_operand" "")))
7612               (use (match_operand 3 "" ""))
7613               (clobber (reg:SI LR_REGNUM))])]
7614   "TARGET_EITHER"
7615   "
7616   {
7617     rtx callee = XEXP (operands[1], 0);
7618     
7619     /* In an untyped call, we can get NULL for operand 2.  */
7620     if (operands[3] == 0)
7621       operands[3] = const0_rtx;
7622       
7623     /* See the comment in define_expand \"call\".  */
7624     if ((GET_CODE (callee) == SYMBOL_REF
7625          && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7626         || (GET_CODE (callee) != SYMBOL_REF
7627             && GET_CODE (callee) != REG))
7628       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7629   }"
7630 )
7631
7632 (define_insn "*call_value_reg_armv5"
7633   [(set (match_operand 0 "" "")
7634         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7635               (match_operand 2 "" "")))
7636    (use (match_operand 3 "" ""))
7637    (clobber (reg:SI LR_REGNUM))]
7638   "TARGET_ARM && arm_arch5"
7639   "blx%?\\t%1"
7640   [(set_attr "type" "call")]
7641 )
7642
7643 (define_insn "*call_value_reg_arm"
7644   [(set (match_operand 0 "" "")
7645         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7646               (match_operand 2 "" "")))
7647    (use (match_operand 3 "" ""))
7648    (clobber (reg:SI LR_REGNUM))]
7649   "TARGET_ARM && !arm_arch5"
7650   "*
7651   return output_call (&operands[1]);
7652   "
7653   [(set_attr "length" "12")
7654    (set_attr "type" "call")]
7655 )
7656
7657 (define_insn "*call_value_mem"
7658   [(set (match_operand 0 "" "")
7659         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
7660               (match_operand 2 "" "")))
7661    (use (match_operand 3 "" ""))
7662    (clobber (reg:SI LR_REGNUM))]
7663   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7664   "*
7665   return output_call_mem (&operands[1]);
7666   "
7667   [(set_attr "length" "12")
7668    (set_attr "type" "call")]
7669 )
7670
7671 (define_insn "*call_value_reg_thumb_v5"
7672   [(set (match_operand 0 "" "")
7673         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7674               (match_operand 2 "" "")))
7675    (use (match_operand 3 "" ""))
7676    (clobber (reg:SI LR_REGNUM))]
7677   "TARGET_THUMB && arm_arch5"
7678   "blx\\t%1"
7679   [(set_attr "length" "2")
7680    (set_attr "type" "call")]
7681 )
7682
7683 (define_insn "*call_value_reg_thumb"
7684   [(set (match_operand 0 "" "")
7685         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7686               (match_operand 2 "" "")))
7687    (use (match_operand 3 "" ""))
7688    (clobber (reg:SI LR_REGNUM))]
7689   "TARGET_THUMB && !arm_arch5"
7690   "*
7691   {
7692     if (!TARGET_CALLER_INTERWORKING)
7693       return thumb_call_via_reg (operands[1]);
7694     else if (operands[2] == const0_rtx)
7695       return \"bl\\t%__interwork_call_via_%1\";
7696     else if (frame_pointer_needed)
7697       return \"bl\\t%__interwork_r7_call_via_%1\";
7698     else
7699       return \"bl\\t%__interwork_r11_call_via_%1\";
7700   }"
7701   [(set_attr "type" "call")]
7702 )
7703
7704 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7705 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7706
7707 (define_insn "*call_symbol"
7708   [(call (mem:SI (match_operand:SI 0 "" ""))
7709          (match_operand 1 "" ""))
7710    (use (match_operand 2 "" ""))
7711    (clobber (reg:SI LR_REGNUM))]
7712   "TARGET_ARM
7713    && (GET_CODE (operands[0]) == SYMBOL_REF)
7714    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7715   "*
7716   {
7717     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7718   }"
7719   [(set_attr "type" "call")]
7720 )
7721
7722 (define_insn "*call_value_symbol"
7723   [(set (match_operand 0 "" "")
7724         (call (mem:SI (match_operand:SI 1 "" ""))
7725         (match_operand:SI 2 "" "")))
7726    (use (match_operand 3 "" ""))
7727    (clobber (reg:SI LR_REGNUM))]
7728   "TARGET_ARM
7729    && (GET_CODE (operands[1]) == SYMBOL_REF)
7730    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7731   "*
7732   {
7733     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7734   }"
7735   [(set_attr "type" "call")]
7736 )
7737
7738 (define_insn "*call_insn"
7739   [(call (mem:SI (match_operand:SI 0 "" ""))
7740          (match_operand:SI 1 "" ""))
7741    (use (match_operand 2 "" ""))
7742    (clobber (reg:SI LR_REGNUM))]
7743   "TARGET_THUMB
7744    && GET_CODE (operands[0]) == SYMBOL_REF
7745    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7746   "bl\\t%a0"
7747   [(set_attr "length" "4")
7748    (set_attr "type" "call")]
7749 )
7750
7751 (define_insn "*call_value_insn"
7752   [(set (match_operand 0 "" "")
7753         (call (mem:SI (match_operand 1 "" ""))
7754               (match_operand 2 "" "")))
7755    (use (match_operand 3 "" ""))
7756    (clobber (reg:SI LR_REGNUM))]
7757   "TARGET_THUMB
7758    && GET_CODE (operands[1]) == SYMBOL_REF
7759    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7760   "bl\\t%a1"
7761   [(set_attr "length" "4")
7762    (set_attr "type" "call")]
7763 )
7764
7765 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7766 (define_expand "sibcall"
7767   [(parallel [(call (match_operand 0 "memory_operand" "")
7768                     (match_operand 1 "general_operand" ""))
7769               (return)
7770               (use (match_operand 2 "" ""))])]
7771   "TARGET_ARM"
7772   "
7773   {
7774     if (operands[2] == NULL_RTX)
7775       operands[2] = const0_rtx;
7776   }"
7777 )
7778
7779 (define_expand "sibcall_value"
7780   [(parallel [(set (match_operand 0 "" "")
7781                    (call (match_operand 1 "memory_operand" "")
7782                          (match_operand 2 "general_operand" "")))
7783               (return)
7784               (use (match_operand 3 "" ""))])]
7785   "TARGET_ARM"
7786   "
7787   {
7788     if (operands[3] == NULL_RTX)
7789       operands[3] = const0_rtx;
7790   }"
7791 )
7792
7793 (define_insn "*sibcall_insn"
7794  [(call (mem:SI (match_operand:SI 0 "" "X"))
7795         (match_operand 1 "" ""))
7796   (return)
7797   (use (match_operand 2 "" ""))]
7798   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7799   "*
7800   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7801   "
7802   [(set_attr "type" "call")]
7803 )
7804
7805 (define_insn "*sibcall_value_insn"
7806  [(set (match_operand 0 "" "")
7807        (call (mem:SI (match_operand:SI 1 "" "X"))
7808              (match_operand 2 "" "")))
7809   (return)
7810   (use (match_operand 3 "" ""))]
7811   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7812   "*
7813   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7814   "
7815   [(set_attr "type" "call")]
7816 )
7817
7818 ;; Often the return insn will be the same as loading from memory, so set attr
7819 (define_insn "return"
7820   [(return)]
7821   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7822   "*
7823   {
7824     if (arm_ccfsm_state == 2)
7825       {
7826         arm_ccfsm_state += 2;
7827         return \"\";
7828       }
7829     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7830   }"
7831   [(set_attr "type" "load1")
7832    (set_attr "length" "12")
7833    (set_attr "predicable" "yes")]
7834 )
7835
7836 (define_insn "*cond_return"
7837   [(set (pc)
7838         (if_then_else (match_operator 0 "arm_comparison_operator"
7839                        [(match_operand 1 "cc_register" "") (const_int 0)])
7840                       (return)
7841                       (pc)))]
7842   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7843   "*
7844   {
7845     if (arm_ccfsm_state == 2)
7846       {
7847         arm_ccfsm_state += 2;
7848         return \"\";
7849       }
7850     return output_return_instruction (operands[0], TRUE, FALSE);
7851   }"
7852   [(set_attr "conds" "use")
7853    (set_attr "length" "12")
7854    (set_attr "type" "load1")]
7855 )
7856
7857 (define_insn "*cond_return_inverted"
7858   [(set (pc)
7859         (if_then_else (match_operator 0 "arm_comparison_operator"
7860                        [(match_operand 1 "cc_register" "") (const_int 0)])
7861                       (pc)
7862                       (return)))]
7863   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7864   "*
7865   {
7866     if (arm_ccfsm_state == 2)
7867       {
7868         arm_ccfsm_state += 2;
7869         return \"\";
7870       }
7871     return output_return_instruction (operands[0], TRUE, TRUE);
7872   }"
7873   [(set_attr "conds" "use")
7874    (set_attr "length" "12")
7875    (set_attr "type" "load1")]
7876 )
7877
7878 ;; Generate a sequence of instructions to determine if the processor is
7879 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7880 ;; mask.
7881
7882 (define_expand "return_addr_mask"
7883   [(set (match_dup 1)
7884       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7885                        (const_int 0)))
7886    (set (match_operand:SI 0 "s_register_operand" "")
7887       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7888                        (const_int -1)
7889                        (const_int 67108860)))] ; 0x03fffffc
7890   "TARGET_ARM"
7891   "
7892   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7893   ")
7894
7895 (define_insn "*check_arch2"
7896   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7897       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7898                        (const_int 0)))]
7899   "TARGET_ARM"
7900   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7901   [(set_attr "length" "8")
7902    (set_attr "conds" "set")]
7903 )
7904
7905 ;; Call subroutine returning any type.
7906
7907 (define_expand "untyped_call"
7908   [(parallel [(call (match_operand 0 "" "")
7909                     (const_int 0))
7910               (match_operand 1 "" "")
7911               (match_operand 2 "" "")])]
7912   "TARGET_EITHER"
7913   "
7914   {
7915     int i;
7916     rtx par = gen_rtx_PARALLEL (VOIDmode,
7917                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7918     rtx addr = gen_reg_rtx (Pmode);
7919     rtx mem;
7920     int size = 0;
7921
7922     emit_move_insn (addr, XEXP (operands[1], 0));
7923     mem = change_address (operands[1], BLKmode, addr);
7924
7925     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7926       {
7927         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7928
7929         /* Default code only uses r0 as a return value, but we could
7930            be using anything up to 4 registers.  */
7931         if (REGNO (src) == R0_REGNUM)
7932           src = gen_rtx_REG (TImode, R0_REGNUM);
7933
7934         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7935                                                  GEN_INT (size));
7936         size += GET_MODE_SIZE (GET_MODE (src));
7937       }
7938
7939     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7940                                     const0_rtx));
7941
7942     size = 0;
7943
7944     for (i = 0; i < XVECLEN (par, 0); i++)
7945       {
7946         HOST_WIDE_INT offset = 0;
7947         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7948
7949         if (size != 0)
7950           emit_move_insn (addr, plus_constant (addr, size));
7951
7952         mem = change_address (mem, GET_MODE (reg), NULL);
7953         if (REGNO (reg) == R0_REGNUM)
7954           {
7955             /* On thumb we have to use a write-back instruction.  */
7956             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7957                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7958             size = TARGET_ARM ? 16 : 0;
7959           }
7960         else
7961           {
7962             emit_move_insn (mem, reg);
7963             size = GET_MODE_SIZE (GET_MODE (reg));
7964           }
7965       }
7966
7967     /* The optimizer does not know that the call sets the function value
7968        registers we stored in the result block.  We avoid problems by
7969        claiming that all hard registers are used and clobbered at this
7970        point.  */
7971     emit_insn (gen_blockage ());
7972
7973     DONE;
7974   }"
7975 )
7976
7977 (define_expand "untyped_return"
7978   [(match_operand:BLK 0 "memory_operand" "")
7979    (match_operand 1 "" "")]
7980   "TARGET_EITHER"
7981   "
7982   {
7983     int i;
7984     rtx addr = gen_reg_rtx (Pmode);
7985     rtx mem;
7986     int size = 0;
7987
7988     emit_move_insn (addr, XEXP (operands[0], 0));
7989     mem = change_address (operands[0], BLKmode, addr);
7990
7991     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7992       {
7993         HOST_WIDE_INT offset = 0;
7994         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7995
7996         if (size != 0)
7997           emit_move_insn (addr, plus_constant (addr, size));
7998
7999         mem = change_address (mem, GET_MODE (reg), NULL);
8000         if (REGNO (reg) == R0_REGNUM)
8001           {
8002             /* On thumb we have to use a write-back instruction.  */
8003             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8004                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8005             size = TARGET_ARM ? 16 : 0;
8006           }
8007         else
8008           {
8009             emit_move_insn (reg, mem);
8010             size = GET_MODE_SIZE (GET_MODE (reg));
8011           }
8012       }
8013
8014     /* Emit USE insns before the return.  */
8015     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8016       emit_insn (gen_rtx_USE (VOIDmode,
8017                               SET_DEST (XVECEXP (operands[1], 0, i))));
8018
8019     /* Construct the return.  */
8020     expand_naked_return ();
8021
8022     DONE;
8023   }"
8024 )
8025
8026 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8027 ;; all of memory.  This blocks insns from being moved across this point.
8028
8029 (define_insn "blockage"
8030   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8031   "TARGET_EITHER"
8032   ""
8033   [(set_attr "length" "0")
8034    (set_attr "type" "block")]
8035 )
8036
8037 (define_expand "casesi"
8038   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8039    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8040    (match_operand:SI 2 "const_int_operand" "")  ; total range
8041    (match_operand:SI 3 "" "")                   ; table label
8042    (match_operand:SI 4 "" "")]                  ; Out of range label
8043   "TARGET_ARM"
8044   "
8045   {
8046     rtx reg;
8047     if (operands[1] != const0_rtx)
8048       {
8049         reg = gen_reg_rtx (SImode);
8050
8051         emit_insn (gen_addsi3 (reg, operands[0],
8052                                GEN_INT (-INTVAL (operands[1]))));
8053         operands[0] = reg;
8054       }
8055
8056     if (!const_ok_for_arm (INTVAL (operands[2])))
8057       operands[2] = force_reg (SImode, operands[2]);
8058
8059     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8060                                          operands[4]));
8061     DONE;
8062   }"
8063 )
8064
8065 ;; The USE in this pattern is needed to tell flow analysis that this is
8066 ;; a CASESI insn.  It has no other purpose.
8067 (define_insn "casesi_internal"
8068   [(parallel [(set (pc)
8069                (if_then_else
8070                 (leu (match_operand:SI 0 "s_register_operand" "r")
8071                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8072                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8073                                  (label_ref (match_operand 2 "" ""))))
8074                 (label_ref (match_operand 3 "" ""))))
8075               (clobber (reg:CC CC_REGNUM))
8076               (use (label_ref (match_dup 2)))])]
8077   "TARGET_ARM"
8078   "*
8079     if (flag_pic)
8080       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8081     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8082   "
8083   [(set_attr "conds" "clob")
8084    (set_attr "length" "12")]
8085 )
8086
8087 (define_expand "indirect_jump"
8088   [(set (pc)
8089         (match_operand:SI 0 "s_register_operand" ""))]
8090   "TARGET_EITHER"
8091   ""
8092 )
8093
8094 ;; NB Never uses BX.
8095 (define_insn "*arm_indirect_jump"
8096   [(set (pc)
8097         (match_operand:SI 0 "s_register_operand" "r"))]
8098   "TARGET_ARM"
8099   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8100   [(set_attr "predicable" "yes")]
8101 )
8102
8103 (define_insn "*load_indirect_jump"
8104   [(set (pc)
8105         (match_operand:SI 0 "memory_operand" "m"))]
8106   "TARGET_ARM"
8107   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8108   [(set_attr "type" "load1")
8109    (set_attr "pool_range" "4096")
8110    (set_attr "neg_pool_range" "4084")
8111    (set_attr "predicable" "yes")]
8112 )
8113
8114 ;; NB Never uses BX.
8115 (define_insn "*thumb_indirect_jump"
8116   [(set (pc)
8117         (match_operand:SI 0 "register_operand" "l*r"))]
8118   "TARGET_THUMB"
8119   "mov\\tpc, %0"
8120   [(set_attr "conds" "clob")
8121    (set_attr "length" "2")]
8122 )
8123
8124 \f
8125 ;; Misc insns
8126
8127 (define_insn "nop"
8128   [(const_int 0)]
8129   "TARGET_EITHER"
8130   "*
8131   if (TARGET_ARM)
8132     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8133   return  \"mov\\tr8, r8\";
8134   "
8135   [(set (attr "length")
8136         (if_then_else (eq_attr "is_thumb" "yes")
8137                       (const_int 2)
8138                       (const_int 4)))]
8139 )
8140
8141 \f
8142 ;; Patterns to allow combination of arithmetic, cond code and shifts
8143
8144 (define_insn "*arith_shiftsi"
8145   [(set (match_operand:SI 0 "s_register_operand" "=r")
8146         (match_operator:SI 1 "shiftable_operator"
8147           [(match_operator:SI 3 "shift_operator"
8148              [(match_operand:SI 4 "s_register_operand" "r")
8149               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8150            (match_operand:SI 2 "s_register_operand" "r")]))]
8151   "TARGET_ARM"
8152   "%i1%?\\t%0, %2, %4%S3"
8153   [(set_attr "predicable" "yes")
8154    (set_attr "shift" "4")
8155    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8156                       (const_string "alu_shift")
8157                       (const_string "alu_shift_reg")))]
8158 )
8159
8160 (define_split
8161   [(set (match_operand:SI 0 "s_register_operand" "")
8162         (match_operator:SI 1 "shiftable_operator"
8163          [(match_operator:SI 2 "shiftable_operator"
8164            [(match_operator:SI 3 "shift_operator"
8165              [(match_operand:SI 4 "s_register_operand" "")
8166               (match_operand:SI 5 "reg_or_int_operand" "")])
8167             (match_operand:SI 6 "s_register_operand" "")])
8168           (match_operand:SI 7 "arm_rhs_operand" "")]))
8169    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8170   "TARGET_ARM"
8171   [(set (match_dup 8)
8172         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8173                          (match_dup 6)]))
8174    (set (match_dup 0)
8175         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8176   "")
8177
8178 (define_insn "*arith_shiftsi_compare0"
8179   [(set (reg:CC_NOOV CC_REGNUM)
8180         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8181                           [(match_operator:SI 3 "shift_operator"
8182                             [(match_operand:SI 4 "s_register_operand" "r")
8183                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8184                            (match_operand:SI 2 "s_register_operand" "r")])
8185                          (const_int 0)))
8186    (set (match_operand:SI 0 "s_register_operand" "=r")
8187         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8188                          (match_dup 2)]))]
8189   "TARGET_ARM"
8190   "%i1%?s\\t%0, %2, %4%S3"
8191   [(set_attr "conds" "set")
8192    (set_attr "shift" "4")
8193    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8194                       (const_string "alu_shift")
8195                       (const_string "alu_shift_reg")))]
8196 )
8197
8198 (define_insn "*arith_shiftsi_compare0_scratch"
8199   [(set (reg:CC_NOOV CC_REGNUM)
8200         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8201                           [(match_operator:SI 3 "shift_operator"
8202                             [(match_operand:SI 4 "s_register_operand" "r")
8203                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8204                            (match_operand:SI 2 "s_register_operand" "r")])
8205                          (const_int 0)))
8206    (clobber (match_scratch:SI 0 "=r"))]
8207   "TARGET_ARM"
8208   "%i1%?s\\t%0, %2, %4%S3"
8209   [(set_attr "conds" "set")
8210    (set_attr "shift" "4")
8211    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8212                       (const_string "alu_shift")
8213                       (const_string "alu_shift_reg")))]
8214 )
8215
8216 (define_insn "*sub_shiftsi"
8217   [(set (match_operand:SI 0 "s_register_operand" "=r")
8218         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8219                   (match_operator:SI 2 "shift_operator"
8220                    [(match_operand:SI 3 "s_register_operand" "r")
8221                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8222   "TARGET_ARM"
8223   "sub%?\\t%0, %1, %3%S2"
8224   [(set_attr "predicable" "yes")
8225    (set_attr "shift" "3")
8226    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8227                       (const_string "alu_shift")
8228                       (const_string "alu_shift_reg")))]
8229 )
8230
8231 (define_insn "*sub_shiftsi_compare0"
8232   [(set (reg:CC_NOOV CC_REGNUM)
8233         (compare:CC_NOOV
8234          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8235                    (match_operator:SI 2 "shift_operator"
8236                     [(match_operand:SI 3 "s_register_operand" "r")
8237                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8238          (const_int 0)))
8239    (set (match_operand:SI 0 "s_register_operand" "=r")
8240         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8241                                                  (match_dup 4)])))]
8242   "TARGET_ARM"
8243   "sub%?s\\t%0, %1, %3%S2"
8244   [(set_attr "conds" "set")
8245    (set_attr "shift" "3")
8246    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8247                       (const_string "alu_shift")
8248                       (const_string "alu_shift_reg")))]
8249 )
8250
8251 (define_insn "*sub_shiftsi_compare0_scratch"
8252   [(set (reg:CC_NOOV CC_REGNUM)
8253         (compare:CC_NOOV
8254          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8255                    (match_operator:SI 2 "shift_operator"
8256                     [(match_operand:SI 3 "s_register_operand" "r")
8257                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8258          (const_int 0)))
8259    (clobber (match_scratch:SI 0 "=r"))]
8260   "TARGET_ARM"
8261   "sub%?s\\t%0, %1, %3%S2"
8262   [(set_attr "conds" "set")
8263    (set_attr "shift" "3")
8264    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8265                       (const_string "alu_shift")
8266                       (const_string "alu_shift_reg")))]
8267 )
8268
8269 \f
8270
8271 (define_insn "*and_scc"
8272   [(set (match_operand:SI 0 "s_register_operand" "=r")
8273         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8274                  [(match_operand 3 "cc_register" "") (const_int 0)])
8275                 (match_operand:SI 2 "s_register_operand" "r")))]
8276   "TARGET_ARM"
8277   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8278   [(set_attr "conds" "use")
8279    (set_attr "length" "8")]
8280 )
8281
8282 (define_insn "*ior_scc"
8283   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8284         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8285                  [(match_operand 3 "cc_register" "") (const_int 0)])
8286                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8287   "TARGET_ARM"
8288   "@
8289    orr%d2\\t%0, %1, #1
8290    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8291   [(set_attr "conds" "use")
8292    (set_attr "length" "4,8")]
8293 )
8294
8295 (define_insn "*compare_scc"
8296   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8297         (match_operator:SI 1 "arm_comparison_operator"
8298          [(match_operand:SI 2 "s_register_operand" "r,r")
8299           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8300    (clobber (reg:CC CC_REGNUM))]
8301   "TARGET_ARM"
8302   "*
8303     if (operands[3] == const0_rtx)
8304       {
8305         if (GET_CODE (operands[1]) == LT)
8306           return \"mov\\t%0, %2, lsr #31\";
8307
8308         if (GET_CODE (operands[1]) == GE)
8309           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8310
8311         if (GET_CODE (operands[1]) == EQ)
8312           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8313       }
8314
8315     if (GET_CODE (operands[1]) == NE)
8316       {
8317         if (which_alternative == 1)
8318           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8319         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8320       }
8321     if (which_alternative == 1)
8322       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8323     else
8324       output_asm_insn (\"cmp\\t%2, %3\", operands);
8325     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8326   "
8327   [(set_attr "conds" "clob")
8328    (set_attr "length" "12")]
8329 )
8330
8331 (define_insn "*cond_move"
8332   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8333         (if_then_else:SI (match_operator 3 "equality_operator"
8334                           [(match_operator 4 "arm_comparison_operator"
8335                             [(match_operand 5 "cc_register" "") (const_int 0)])
8336                            (const_int 0)])
8337                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8338                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8339   "TARGET_ARM"
8340   "*
8341     if (GET_CODE (operands[3]) == NE)
8342       {
8343         if (which_alternative != 1)
8344           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8345         if (which_alternative != 0)
8346           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8347         return \"\";
8348       }
8349     if (which_alternative != 0)
8350       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8351     if (which_alternative != 1)
8352       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8353     return \"\";
8354   "
8355   [(set_attr "conds" "use")
8356    (set_attr "length" "4,4,8")]
8357 )
8358
8359 (define_insn "*cond_arith"
8360   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8361         (match_operator:SI 5 "shiftable_operator" 
8362          [(match_operator:SI 4 "arm_comparison_operator"
8363            [(match_operand:SI 2 "s_register_operand" "r,r")
8364             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8365           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8366    (clobber (reg:CC CC_REGNUM))]
8367   "TARGET_ARM"
8368   "*
8369     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8370       return \"%i5\\t%0, %1, %2, lsr #31\";
8371
8372     output_asm_insn (\"cmp\\t%2, %3\", operands);
8373     if (GET_CODE (operands[5]) == AND)
8374       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8375     else if (GET_CODE (operands[5]) == MINUS)
8376       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8377     else if (which_alternative != 0)
8378       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8379     return \"%i5%d4\\t%0, %1, #1\";
8380   "
8381   [(set_attr "conds" "clob")
8382    (set_attr "length" "12")]
8383 )
8384
8385 (define_insn "*cond_sub"
8386   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8387         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8388                   (match_operator:SI 4 "arm_comparison_operator"
8389                    [(match_operand:SI 2 "s_register_operand" "r,r")
8390                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8391    (clobber (reg:CC CC_REGNUM))]
8392   "TARGET_ARM"
8393   "*
8394     output_asm_insn (\"cmp\\t%2, %3\", operands);
8395     if (which_alternative != 0)
8396       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8397     return \"sub%d4\\t%0, %1, #1\";
8398   "
8399   [(set_attr "conds" "clob")
8400    (set_attr "length" "8,12")]
8401 )
8402
8403 (define_insn "*cmp_ite0"
8404   [(set (match_operand 6 "dominant_cc_register" "")
8405         (compare
8406          (if_then_else:SI
8407           (match_operator 4 "arm_comparison_operator"
8408            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8409             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8410           (match_operator:SI 5 "arm_comparison_operator"
8411            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8412             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8413           (const_int 0))
8414          (const_int 0)))]
8415   "TARGET_ARM"
8416   "*
8417   {
8418     static const char * const opcodes[4][2] =
8419     {
8420       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8421        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8422       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8423        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8424       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8425        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8426       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8427        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8428     };
8429     int swap =
8430       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8431
8432     return opcodes[which_alternative][swap];
8433   }"
8434   [(set_attr "conds" "set")
8435    (set_attr "length" "8")]
8436 )
8437
8438 (define_insn "*cmp_ite1"
8439   [(set (match_operand 6 "dominant_cc_register" "")
8440         (compare
8441          (if_then_else:SI
8442           (match_operator 4 "arm_comparison_operator"
8443            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8444             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8445           (match_operator:SI 5 "arm_comparison_operator"
8446            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8447             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8448           (const_int 1))
8449          (const_int 0)))]
8450   "TARGET_ARM"
8451   "*
8452   {
8453     static const char * const opcodes[4][2] =
8454     {
8455       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8456        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8457       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8458        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8459       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8460        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8461       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8462        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8463     };
8464     int swap =
8465       comparison_dominates_p (GET_CODE (operands[5]),
8466                               reverse_condition (GET_CODE (operands[4])));
8467
8468     return opcodes[which_alternative][swap];
8469   }"
8470   [(set_attr "conds" "set")
8471    (set_attr "length" "8")]
8472 )
8473
8474 (define_insn "*cmp_and"
8475   [(set (match_operand 6 "dominant_cc_register" "")
8476         (compare
8477          (and:SI
8478           (match_operator 4 "arm_comparison_operator"
8479            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8480             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8481           (match_operator:SI 5 "arm_comparison_operator"
8482            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8483             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8484          (const_int 0)))]
8485   "TARGET_ARM"
8486   "*
8487   {
8488     static const char *const opcodes[4][2] =
8489     {
8490       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8491        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8492       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8493        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8494       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8495        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8496       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8497        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8498     };
8499     int swap =
8500       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8501
8502     return opcodes[which_alternative][swap];
8503   }"
8504   [(set_attr "conds" "set")
8505    (set_attr "predicable" "no")
8506    (set_attr "length" "8")]
8507 )
8508
8509 (define_insn "*cmp_ior"
8510   [(set (match_operand 6 "dominant_cc_register" "")
8511         (compare
8512          (ior:SI
8513           (match_operator 4 "arm_comparison_operator"
8514            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8515             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8516           (match_operator:SI 5 "arm_comparison_operator"
8517            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8518             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8519          (const_int 0)))]
8520   "TARGET_ARM"
8521   "*
8522 {
8523   static const char *const opcodes[4][2] =
8524   {
8525     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8526      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8527     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8528      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8529     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8530      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8531     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8532      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8533   };
8534   int swap =
8535     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8536
8537   return opcodes[which_alternative][swap];
8538 }
8539 "
8540   [(set_attr "conds" "set")
8541    (set_attr "length" "8")]
8542 )
8543
8544 (define_insn_and_split "*ior_scc_scc"
8545   [(set (match_operand:SI 0 "s_register_operand" "=r")
8546         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8547                  [(match_operand:SI 1 "s_register_operand" "r")
8548                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8549                 (match_operator:SI 6 "arm_comparison_operator"
8550                  [(match_operand:SI 4 "s_register_operand" "r")
8551                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8552    (clobber (reg:CC CC_REGNUM))]
8553   "TARGET_ARM
8554    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8555        != CCmode)"
8556   "#"
8557   "TARGET_ARM && reload_completed"
8558   [(set (match_dup 7)
8559         (compare
8560          (ior:SI
8561           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8562           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8563          (const_int 0)))
8564    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8565   "operands[7]
8566      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8567                                                   DOM_CC_X_OR_Y),
8568                     CC_REGNUM);"
8569   [(set_attr "conds" "clob")
8570    (set_attr "length" "16")])
8571
8572 ; If the above pattern is followed by a CMP insn, then the compare is 
8573 ; redundant, since we can rework the conditional instruction that follows.
8574 (define_insn_and_split "*ior_scc_scc_cmp"
8575   [(set (match_operand 0 "dominant_cc_register" "")
8576         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8577                           [(match_operand:SI 1 "s_register_operand" "r")
8578                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8579                          (match_operator:SI 6 "arm_comparison_operator"
8580                           [(match_operand:SI 4 "s_register_operand" "r")
8581                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8582                  (const_int 0)))
8583    (set (match_operand:SI 7 "s_register_operand" "=r")
8584         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8585                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8586   "TARGET_ARM"
8587   "#"
8588   "TARGET_ARM && reload_completed"
8589   [(set (match_dup 0)
8590         (compare
8591          (ior:SI
8592           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8593           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8594          (const_int 0)))
8595    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8596   ""
8597   [(set_attr "conds" "set")
8598    (set_attr "length" "16")])
8599
8600 (define_insn_and_split "*and_scc_scc"
8601   [(set (match_operand:SI 0 "s_register_operand" "=r")
8602         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8603                  [(match_operand:SI 1 "s_register_operand" "r")
8604                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8605                 (match_operator:SI 6 "arm_comparison_operator"
8606                  [(match_operand:SI 4 "s_register_operand" "r")
8607                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8608    (clobber (reg:CC CC_REGNUM))]
8609   "TARGET_ARM
8610    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8611        != CCmode)"
8612   "#"
8613   "TARGET_ARM && reload_completed
8614    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8615        != CCmode)"
8616   [(set (match_dup 7)
8617         (compare
8618          (and:SI
8619           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8620           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8621          (const_int 0)))
8622    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8623   "operands[7]
8624      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8625                                                   DOM_CC_X_AND_Y),
8626                     CC_REGNUM);"
8627   [(set_attr "conds" "clob")
8628    (set_attr "length" "16")])
8629
8630 ; If the above pattern is followed by a CMP insn, then the compare is 
8631 ; redundant, since we can rework the conditional instruction that follows.
8632 (define_insn_and_split "*and_scc_scc_cmp"
8633   [(set (match_operand 0 "dominant_cc_register" "")
8634         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8635                           [(match_operand:SI 1 "s_register_operand" "r")
8636                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8637                          (match_operator:SI 6 "arm_comparison_operator"
8638                           [(match_operand:SI 4 "s_register_operand" "r")
8639                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8640                  (const_int 0)))
8641    (set (match_operand:SI 7 "s_register_operand" "=r")
8642         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8643                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8644   "TARGET_ARM"
8645   "#"
8646   "TARGET_ARM && reload_completed"
8647   [(set (match_dup 0)
8648         (compare
8649          (and:SI
8650           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8651           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8652          (const_int 0)))
8653    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8654   ""
8655   [(set_attr "conds" "set")
8656    (set_attr "length" "16")])
8657
8658 ;; If there is no dominance in the comparison, then we can still save an
8659 ;; instruction in the AND case, since we can know that the second compare
8660 ;; need only zero the value if false (if true, then the value is already
8661 ;; correct).
8662 (define_insn_and_split "*and_scc_scc_nodom"
8663   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8664         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8665                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8666                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8667                 (match_operator:SI 6 "arm_comparison_operator"
8668                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8669                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8670    (clobber (reg:CC CC_REGNUM))]
8671   "TARGET_ARM
8672    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8673        == CCmode)"
8674   "#"
8675   "TARGET_ARM && reload_completed"
8676   [(parallel [(set (match_dup 0)
8677                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8678               (clobber (reg:CC CC_REGNUM))])
8679    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8680    (set (match_dup 0)
8681         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8682                          (match_dup 0)
8683                          (const_int 0)))]
8684   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8685                                               operands[4], operands[5]),
8686                               CC_REGNUM);
8687    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8688                                   operands[5]);"
8689   [(set_attr "conds" "clob")
8690    (set_attr "length" "20")])
8691
8692 (define_split
8693   [(set (reg:CC_NOOV CC_REGNUM)
8694         (compare:CC_NOOV (ior:SI
8695                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8696                                   (const_int 1))
8697                           (match_operator:SI 1 "comparison_operator"
8698                            [(match_operand:SI 2 "s_register_operand" "")
8699                             (match_operand:SI 3 "arm_add_operand" "")]))
8700                          (const_int 0)))
8701    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8702   "TARGET_ARM"
8703   [(set (match_dup 4)
8704         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8705                 (match_dup 0)))
8706    (set (reg:CC_NOOV CC_REGNUM)
8707         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8708                          (const_int 0)))]
8709   "")
8710
8711 (define_split
8712   [(set (reg:CC_NOOV CC_REGNUM)
8713         (compare:CC_NOOV (ior:SI
8714                           (match_operator:SI 1 "comparison_operator"
8715                            [(match_operand:SI 2 "s_register_operand" "")
8716                             (match_operand:SI 3 "arm_add_operand" "")])
8717                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8718                                   (const_int 1)))
8719                          (const_int 0)))
8720    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8721   "TARGET_ARM"
8722   [(set (match_dup 4)
8723         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8724                 (match_dup 0)))
8725    (set (reg:CC_NOOV CC_REGNUM)
8726         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8727                          (const_int 0)))]
8728   "")
8729
8730 (define_insn "*negscc"
8731   [(set (match_operand:SI 0 "s_register_operand" "=r")
8732         (neg:SI (match_operator 3 "arm_comparison_operator"
8733                  [(match_operand:SI 1 "s_register_operand" "r")
8734                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8735    (clobber (reg:CC CC_REGNUM))]
8736   "TARGET_ARM"
8737   "*
8738   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8739     return \"mov\\t%0, %1, asr #31\";
8740
8741   if (GET_CODE (operands[3]) == NE)
8742     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8743
8744   if (GET_CODE (operands[3]) == GT)
8745     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8746
8747   output_asm_insn (\"cmp\\t%1, %2\", operands);
8748   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8749   return \"mvn%d3\\t%0, #0\";
8750   "
8751   [(set_attr "conds" "clob")
8752    (set_attr "length" "12")]
8753 )
8754
8755 (define_insn "movcond"
8756   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8757         (if_then_else:SI
8758          (match_operator 5 "arm_comparison_operator"
8759           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8760            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8761          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8762          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8763    (clobber (reg:CC CC_REGNUM))]
8764   "TARGET_ARM"
8765   "*
8766   if (GET_CODE (operands[5]) == LT
8767       && (operands[4] == const0_rtx))
8768     {
8769       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8770         {
8771           if (operands[2] == const0_rtx)
8772             return \"and\\t%0, %1, %3, asr #31\";
8773           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8774         }
8775       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8776         {
8777           if (operands[1] == const0_rtx)
8778             return \"bic\\t%0, %2, %3, asr #31\";
8779           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8780         }
8781       /* The only case that falls through to here is when both ops 1 & 2
8782          are constants.  */
8783     }
8784
8785   if (GET_CODE (operands[5]) == GE
8786       && (operands[4] == const0_rtx))
8787     {
8788       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8789         {
8790           if (operands[2] == const0_rtx)
8791             return \"bic\\t%0, %1, %3, asr #31\";
8792           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8793         }
8794       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8795         {
8796           if (operands[1] == const0_rtx)
8797             return \"and\\t%0, %2, %3, asr #31\";
8798           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8799         }
8800       /* The only case that falls through to here is when both ops 1 & 2
8801          are constants.  */
8802     }
8803   if (GET_CODE (operands[4]) == CONST_INT
8804       && !const_ok_for_arm (INTVAL (operands[4])))
8805     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8806   else
8807     output_asm_insn (\"cmp\\t%3, %4\", operands);
8808   if (which_alternative != 0)
8809     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8810   if (which_alternative != 1)
8811     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8812   return \"\";
8813   "
8814   [(set_attr "conds" "clob")
8815    (set_attr "length" "8,8,12")]
8816 )
8817
8818 (define_insn "*ifcompare_plus_move"
8819   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8820         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8821                           [(match_operand:SI 4 "s_register_operand" "r,r")
8822                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8823                          (plus:SI
8824                           (match_operand:SI 2 "s_register_operand" "r,r")
8825                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8826                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8827    (clobber (reg:CC CC_REGNUM))]
8828   "TARGET_ARM"
8829   "#"
8830   [(set_attr "conds" "clob")
8831    (set_attr "length" "8,12")]
8832 )
8833
8834 (define_insn "*if_plus_move"
8835   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8836         (if_then_else:SI
8837          (match_operator 4 "arm_comparison_operator"
8838           [(match_operand 5 "cc_register" "") (const_int 0)])
8839          (plus:SI
8840           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8841           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8842          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8843   "TARGET_ARM"
8844   "@
8845    add%d4\\t%0, %2, %3
8846    sub%d4\\t%0, %2, #%n3
8847    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8848    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8849   [(set_attr "conds" "use")
8850    (set_attr "length" "4,4,8,8")
8851    (set_attr "type" "*,*,*,*")]
8852 )
8853
8854 (define_insn "*ifcompare_move_plus"
8855   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8856         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8857                           [(match_operand:SI 4 "s_register_operand" "r,r")
8858                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8859                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8860                          (plus:SI
8861                           (match_operand:SI 2 "s_register_operand" "r,r")
8862                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8863    (clobber (reg:CC CC_REGNUM))]
8864   "TARGET_ARM"
8865   "#"
8866   [(set_attr "conds" "clob")
8867    (set_attr "length" "8,12")]
8868 )
8869
8870 (define_insn "*if_move_plus"
8871   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8872         (if_then_else:SI
8873          (match_operator 4 "arm_comparison_operator"
8874           [(match_operand 5 "cc_register" "") (const_int 0)])
8875          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8876          (plus:SI
8877           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8878           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8879   "TARGET_ARM"
8880   "@
8881    add%D4\\t%0, %2, %3
8882    sub%D4\\t%0, %2, #%n3
8883    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8884    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8885   [(set_attr "conds" "use")
8886    (set_attr "length" "4,4,8,8")
8887    (set_attr "type" "*,*,*,*")]
8888 )
8889
8890 (define_insn "*ifcompare_arith_arith"
8891   [(set (match_operand:SI 0 "s_register_operand" "=r")
8892         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8893                           [(match_operand:SI 5 "s_register_operand" "r")
8894                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8895                          (match_operator:SI 8 "shiftable_operator"
8896                           [(match_operand:SI 1 "s_register_operand" "r")
8897                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8898                          (match_operator:SI 7 "shiftable_operator"
8899                           [(match_operand:SI 3 "s_register_operand" "r")
8900                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8901    (clobber (reg:CC CC_REGNUM))]
8902   "TARGET_ARM"
8903   "#"
8904   [(set_attr "conds" "clob")
8905    (set_attr "length" "12")]
8906 )
8907
8908 (define_insn "*if_arith_arith"
8909   [(set (match_operand:SI 0 "s_register_operand" "=r")
8910         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8911                           [(match_operand 8 "cc_register" "") (const_int 0)])
8912                          (match_operator:SI 6 "shiftable_operator"
8913                           [(match_operand:SI 1 "s_register_operand" "r")
8914                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8915                          (match_operator:SI 7 "shiftable_operator"
8916                           [(match_operand:SI 3 "s_register_operand" "r")
8917                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8918   "TARGET_ARM"
8919   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8920   [(set_attr "conds" "use")
8921    (set_attr "length" "8")]
8922 )
8923
8924 (define_insn "*ifcompare_arith_move"
8925   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8926         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8927                           [(match_operand:SI 2 "s_register_operand" "r,r")
8928                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8929                          (match_operator:SI 7 "shiftable_operator"
8930                           [(match_operand:SI 4 "s_register_operand" "r,r")
8931                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8932                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8933    (clobber (reg:CC CC_REGNUM))]
8934   "TARGET_ARM"
8935   "*
8936   /* If we have an operation where (op x 0) is the identity operation and
8937      the conditional operator is LT or GE and we are comparing against zero and
8938      everything is in registers then we can do this in two instructions.  */
8939   if (operands[3] == const0_rtx
8940       && GET_CODE (operands[7]) != AND
8941       && GET_CODE (operands[5]) == REG
8942       && GET_CODE (operands[1]) == REG 
8943       && REGNO (operands[1]) == REGNO (operands[4])
8944       && REGNO (operands[4]) != REGNO (operands[0]))
8945     {
8946       if (GET_CODE (operands[6]) == LT)
8947         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8948       else if (GET_CODE (operands[6]) == GE)
8949         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8950     }
8951   if (GET_CODE (operands[3]) == CONST_INT
8952       && !const_ok_for_arm (INTVAL (operands[3])))
8953     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8954   else
8955     output_asm_insn (\"cmp\\t%2, %3\", operands);
8956   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8957   if (which_alternative != 0)
8958     return \"mov%D6\\t%0, %1\";
8959   return \"\";
8960   "
8961   [(set_attr "conds" "clob")
8962    (set_attr "length" "8,12")]
8963 )
8964
8965 (define_insn "*if_arith_move"
8966   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8967         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8968                           [(match_operand 6 "cc_register" "") (const_int 0)])
8969                          (match_operator:SI 5 "shiftable_operator"
8970                           [(match_operand:SI 2 "s_register_operand" "r,r")
8971                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8972                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8973   "TARGET_ARM"
8974   "@
8975    %I5%d4\\t%0, %2, %3
8976    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8977   [(set_attr "conds" "use")
8978    (set_attr "length" "4,8")
8979    (set_attr "type" "*,*")]
8980 )
8981
8982 (define_insn "*ifcompare_move_arith"
8983   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8984         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8985                           [(match_operand:SI 4 "s_register_operand" "r,r")
8986                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8987                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8988                          (match_operator:SI 7 "shiftable_operator"
8989                           [(match_operand:SI 2 "s_register_operand" "r,r")
8990                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8991    (clobber (reg:CC CC_REGNUM))]
8992   "TARGET_ARM"
8993   "*
8994   /* If we have an operation where (op x 0) is the identity operation and
8995      the conditional operator is LT or GE and we are comparing against zero and
8996      everything is in registers then we can do this in two instructions */
8997   if (operands[5] == const0_rtx
8998       && GET_CODE (operands[7]) != AND
8999       && GET_CODE (operands[3]) == REG
9000       && GET_CODE (operands[1]) == REG 
9001       && REGNO (operands[1]) == REGNO (operands[2])
9002       && REGNO (operands[2]) != REGNO (operands[0]))
9003     {
9004       if (GET_CODE (operands[6]) == GE)
9005         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9006       else if (GET_CODE (operands[6]) == LT)
9007         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9008     }
9009
9010   if (GET_CODE (operands[5]) == CONST_INT
9011       && !const_ok_for_arm (INTVAL (operands[5])))
9012     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9013   else
9014     output_asm_insn (\"cmp\\t%4, %5\", operands);
9015
9016   if (which_alternative != 0)
9017     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9018   return \"%I7%D6\\t%0, %2, %3\";
9019   "
9020   [(set_attr "conds" "clob")
9021    (set_attr "length" "8,12")]
9022 )
9023
9024 (define_insn "*if_move_arith"
9025   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9026         (if_then_else:SI
9027          (match_operator 4 "arm_comparison_operator"
9028           [(match_operand 6 "cc_register" "") (const_int 0)])
9029          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9030          (match_operator:SI 5 "shiftable_operator"
9031           [(match_operand:SI 2 "s_register_operand" "r,r")
9032            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9033   "TARGET_ARM"
9034   "@
9035    %I5%D4\\t%0, %2, %3
9036    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9037   [(set_attr "conds" "use")
9038    (set_attr "length" "4,8")
9039    (set_attr "type" "*,*")]
9040 )
9041
9042 (define_insn "*ifcompare_move_not"
9043   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9044         (if_then_else:SI
9045          (match_operator 5 "arm_comparison_operator"
9046           [(match_operand:SI 3 "s_register_operand" "r,r")
9047            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9048          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9049          (not:SI
9050           (match_operand:SI 2 "s_register_operand" "r,r"))))
9051    (clobber (reg:CC CC_REGNUM))]
9052   "TARGET_ARM"
9053   "#"
9054   [(set_attr "conds" "clob")
9055    (set_attr "length" "8,12")]
9056 )
9057
9058 (define_insn "*if_move_not"
9059   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9060         (if_then_else:SI
9061          (match_operator 4 "arm_comparison_operator"
9062           [(match_operand 3 "cc_register" "") (const_int 0)])
9063          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9064          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9065   "TARGET_ARM"
9066   "@
9067    mvn%D4\\t%0, %2
9068    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9069    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9070   [(set_attr "conds" "use")
9071    (set_attr "length" "4,8,8")]
9072 )
9073
9074 (define_insn "*ifcompare_not_move"
9075   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9076         (if_then_else:SI 
9077          (match_operator 5 "arm_comparison_operator"
9078           [(match_operand:SI 3 "s_register_operand" "r,r")
9079            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9080          (not:SI
9081           (match_operand:SI 2 "s_register_operand" "r,r"))
9082          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9083    (clobber (reg:CC CC_REGNUM))]
9084   "TARGET_ARM"
9085   "#"
9086   [(set_attr "conds" "clob")
9087    (set_attr "length" "8,12")]
9088 )
9089
9090 (define_insn "*if_not_move"
9091   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9092         (if_then_else:SI
9093          (match_operator 4 "arm_comparison_operator"
9094           [(match_operand 3 "cc_register" "") (const_int 0)])
9095          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9096          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9097   "TARGET_ARM"
9098   "@
9099    mvn%d4\\t%0, %2
9100    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9101    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9102   [(set_attr "conds" "use")
9103    (set_attr "length" "4,8,8")]
9104 )
9105
9106 (define_insn "*ifcompare_shift_move"
9107   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9108         (if_then_else:SI
9109          (match_operator 6 "arm_comparison_operator"
9110           [(match_operand:SI 4 "s_register_operand" "r,r")
9111            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9112          (match_operator:SI 7 "shift_operator"
9113           [(match_operand:SI 2 "s_register_operand" "r,r")
9114            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9115          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9116    (clobber (reg:CC CC_REGNUM))]
9117   "TARGET_ARM"
9118   "#"
9119   [(set_attr "conds" "clob")
9120    (set_attr "length" "8,12")]
9121 )
9122
9123 (define_insn "*if_shift_move"
9124   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9125         (if_then_else:SI
9126          (match_operator 5 "arm_comparison_operator"
9127           [(match_operand 6 "cc_register" "") (const_int 0)])
9128          (match_operator:SI 4 "shift_operator"
9129           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9130            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9131          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9132   "TARGET_ARM"
9133   "@
9134    mov%d5\\t%0, %2%S4
9135    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9136    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9137   [(set_attr "conds" "use")
9138    (set_attr "shift" "2")
9139    (set_attr "length" "4,8,8")
9140    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9141                       (const_string "alu_shift")
9142                       (const_string "alu_shift_reg")))]
9143 )
9144
9145 (define_insn "*ifcompare_move_shift"
9146   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9147         (if_then_else:SI
9148          (match_operator 6 "arm_comparison_operator"
9149           [(match_operand:SI 4 "s_register_operand" "r,r")
9150            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9151          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9152          (match_operator:SI 7 "shift_operator"
9153           [(match_operand:SI 2 "s_register_operand" "r,r")
9154            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9155    (clobber (reg:CC CC_REGNUM))]
9156   "TARGET_ARM"
9157   "#"
9158   [(set_attr "conds" "clob")
9159    (set_attr "length" "8,12")]
9160 )
9161
9162 (define_insn "*if_move_shift"
9163   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9164         (if_then_else:SI
9165          (match_operator 5 "arm_comparison_operator"
9166           [(match_operand 6 "cc_register" "") (const_int 0)])
9167          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9168          (match_operator:SI 4 "shift_operator"
9169           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9170            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9171   "TARGET_ARM"
9172   "@
9173    mov%D5\\t%0, %2%S4
9174    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9175    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9176   [(set_attr "conds" "use")
9177    (set_attr "shift" "2")
9178    (set_attr "length" "4,8,8")
9179    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9180                       (const_string "alu_shift")
9181                       (const_string "alu_shift_reg")))]
9182 )
9183
9184 (define_insn "*ifcompare_shift_shift"
9185   [(set (match_operand:SI 0 "s_register_operand" "=r")
9186         (if_then_else:SI
9187          (match_operator 7 "arm_comparison_operator"
9188           [(match_operand:SI 5 "s_register_operand" "r")
9189            (match_operand:SI 6 "arm_add_operand" "rIL")])
9190          (match_operator:SI 8 "shift_operator"
9191           [(match_operand:SI 1 "s_register_operand" "r")
9192            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9193          (match_operator:SI 9 "shift_operator"
9194           [(match_operand:SI 3 "s_register_operand" "r")
9195            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9196    (clobber (reg:CC CC_REGNUM))]
9197   "TARGET_ARM"
9198   "#"
9199   [(set_attr "conds" "clob")
9200    (set_attr "length" "12")]
9201 )
9202
9203 (define_insn "*if_shift_shift"
9204   [(set (match_operand:SI 0 "s_register_operand" "=r")
9205         (if_then_else:SI
9206          (match_operator 5 "arm_comparison_operator"
9207           [(match_operand 8 "cc_register" "") (const_int 0)])
9208          (match_operator:SI 6 "shift_operator"
9209           [(match_operand:SI 1 "s_register_operand" "r")
9210            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9211          (match_operator:SI 7 "shift_operator"
9212           [(match_operand:SI 3 "s_register_operand" "r")
9213            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9214   "TARGET_ARM"
9215   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9216   [(set_attr "conds" "use")
9217    (set_attr "shift" "1")
9218    (set_attr "length" "8")
9219    (set (attr "type") (if_then_else
9220                         (and (match_operand 2 "const_int_operand" "")
9221                              (match_operand 4 "const_int_operand" ""))
9222                       (const_string "alu_shift")
9223                       (const_string "alu_shift_reg")))]
9224 )
9225
9226 (define_insn "*ifcompare_not_arith"
9227   [(set (match_operand:SI 0 "s_register_operand" "=r")
9228         (if_then_else:SI
9229          (match_operator 6 "arm_comparison_operator"
9230           [(match_operand:SI 4 "s_register_operand" "r")
9231            (match_operand:SI 5 "arm_add_operand" "rIL")])
9232          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9233          (match_operator:SI 7 "shiftable_operator"
9234           [(match_operand:SI 2 "s_register_operand" "r")
9235            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9236    (clobber (reg:CC CC_REGNUM))]
9237   "TARGET_ARM"
9238   "#"
9239   [(set_attr "conds" "clob")
9240    (set_attr "length" "12")]
9241 )
9242
9243 (define_insn "*if_not_arith"
9244   [(set (match_operand:SI 0 "s_register_operand" "=r")
9245         (if_then_else:SI
9246          (match_operator 5 "arm_comparison_operator"
9247           [(match_operand 4 "cc_register" "") (const_int 0)])
9248          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9249          (match_operator:SI 6 "shiftable_operator"
9250           [(match_operand:SI 2 "s_register_operand" "r")
9251            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9252   "TARGET_ARM"
9253   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9254   [(set_attr "conds" "use")
9255    (set_attr "length" "8")]
9256 )
9257
9258 (define_insn "*ifcompare_arith_not"
9259   [(set (match_operand:SI 0 "s_register_operand" "=r")
9260         (if_then_else:SI
9261          (match_operator 6 "arm_comparison_operator"
9262           [(match_operand:SI 4 "s_register_operand" "r")
9263            (match_operand:SI 5 "arm_add_operand" "rIL")])
9264          (match_operator:SI 7 "shiftable_operator"
9265           [(match_operand:SI 2 "s_register_operand" "r")
9266            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9267          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9268    (clobber (reg:CC CC_REGNUM))]
9269   "TARGET_ARM"
9270   "#"
9271   [(set_attr "conds" "clob")
9272    (set_attr "length" "12")]
9273 )
9274
9275 (define_insn "*if_arith_not"
9276   [(set (match_operand:SI 0 "s_register_operand" "=r")
9277         (if_then_else:SI
9278          (match_operator 5 "arm_comparison_operator"
9279           [(match_operand 4 "cc_register" "") (const_int 0)])
9280          (match_operator:SI 6 "shiftable_operator"
9281           [(match_operand:SI 2 "s_register_operand" "r")
9282            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9283          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9284   "TARGET_ARM"
9285   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9286   [(set_attr "conds" "use")
9287    (set_attr "length" "8")]
9288 )
9289
9290 (define_insn "*ifcompare_neg_move"
9291   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9292         (if_then_else:SI
9293          (match_operator 5 "arm_comparison_operator"
9294           [(match_operand:SI 3 "s_register_operand" "r,r")
9295            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9296          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9297          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9298    (clobber (reg:CC CC_REGNUM))]
9299   "TARGET_ARM"
9300   "#"
9301   [(set_attr "conds" "clob")
9302    (set_attr "length" "8,12")]
9303 )
9304
9305 (define_insn "*if_neg_move"
9306   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9307         (if_then_else:SI
9308          (match_operator 4 "arm_comparison_operator"
9309           [(match_operand 3 "cc_register" "") (const_int 0)])
9310          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9311          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9312   "TARGET_ARM"
9313   "@
9314    rsb%d4\\t%0, %2, #0
9315    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9316    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9317   [(set_attr "conds" "use")
9318    (set_attr "length" "4,8,8")]
9319 )
9320
9321 (define_insn "*ifcompare_move_neg"
9322   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9323         (if_then_else:SI
9324          (match_operator 5 "arm_comparison_operator"
9325           [(match_operand:SI 3 "s_register_operand" "r,r")
9326            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9327          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9328          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9329    (clobber (reg:CC CC_REGNUM))]
9330   "TARGET_ARM"
9331   "#"
9332   [(set_attr "conds" "clob")
9333    (set_attr "length" "8,12")]
9334 )
9335
9336 (define_insn "*if_move_neg"
9337   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9338         (if_then_else:SI
9339          (match_operator 4 "arm_comparison_operator"
9340           [(match_operand 3 "cc_register" "") (const_int 0)])
9341          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9342          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9343   "TARGET_ARM"
9344   "@
9345    rsb%D4\\t%0, %2, #0
9346    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9347    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9348   [(set_attr "conds" "use")
9349    (set_attr "length" "4,8,8")]
9350 )
9351
9352 (define_insn "*arith_adjacentmem"
9353   [(set (match_operand:SI 0 "s_register_operand" "=r")
9354         (match_operator:SI 1 "shiftable_operator"
9355          [(match_operand:SI 2 "memory_operand" "m")
9356           (match_operand:SI 3 "memory_operand" "m")]))
9357    (clobber (match_scratch:SI 4 "=r"))]
9358   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9359   "*
9360   {
9361     rtx ldm[3];
9362     rtx arith[4];
9363     rtx base_reg;
9364     HOST_WIDE_INT val1 = 0, val2 = 0;
9365
9366     if (REGNO (operands[0]) > REGNO (operands[4]))
9367       {
9368         ldm[1] = operands[4];
9369         ldm[2] = operands[0];
9370       }
9371     else
9372       {
9373         ldm[1] = operands[0];
9374         ldm[2] = operands[4];
9375       }
9376
9377     base_reg = XEXP (operands[2], 0);
9378
9379     if (!REG_P (base_reg))
9380       {
9381         val1 = INTVAL (XEXP (base_reg, 1));
9382         base_reg = XEXP (base_reg, 0);
9383       }
9384
9385     if (!REG_P (XEXP (operands[3], 0)))
9386       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9387
9388     arith[0] = operands[0];
9389     arith[3] = operands[1];
9390
9391     if (val1 < val2)
9392       {
9393         arith[1] = ldm[1];
9394         arith[2] = ldm[2];
9395       }
9396     else
9397       {
9398         arith[1] = ldm[2];
9399         arith[2] = ldm[1];
9400       }
9401
9402     ldm[0] = base_reg;
9403     if (val1 !=0 && val2 != 0)
9404       {
9405         if (val1 == 4 || val2 == 4)
9406           /* Other val must be 8, since we know they are adjacent and neither
9407              is zero.  */
9408           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9409         else
9410           {
9411             rtx ops[3];
9412
9413             ldm[0] = ops[0] = operands[4];
9414             ops[1] = base_reg;
9415             ops[2] = GEN_INT (val1);
9416             output_add_immediate (ops);
9417             if (val1 < val2)
9418               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9419             else
9420               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9421           }
9422       }
9423     else if (val1 != 0)
9424       {
9425         if (val1 < val2)
9426           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9427         else
9428           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9429       }
9430     else
9431       {
9432         if (val1 < val2)
9433           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9434         else
9435           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9436       }
9437     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9438     return \"\";
9439   }"
9440   [(set_attr "length" "12")
9441    (set_attr "predicable" "yes")
9442    (set_attr "type" "load1")]
9443 )
9444
9445 ; This pattern is never tried by combine, so do it as a peephole
9446
9447 (define_peephole2
9448   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9449         (match_operand:SI 1 "arm_general_register_operand" ""))
9450    (set (reg:CC CC_REGNUM)
9451         (compare:CC (match_dup 1) (const_int 0)))]
9452   "TARGET_ARM"
9453   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9454               (set (match_dup 0) (match_dup 1))])]
9455   ""
9456 )
9457
9458 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9459 ; reversed, check that the memory references aren't volatile.
9460
9461 (define_peephole
9462   [(set (match_operand:SI 0 "s_register_operand" "=r")
9463         (match_operand:SI 4 "memory_operand" "m"))
9464    (set (match_operand:SI 1 "s_register_operand" "=r")
9465         (match_operand:SI 5 "memory_operand" "m"))
9466    (set (match_operand:SI 2 "s_register_operand" "=r")
9467         (match_operand:SI 6 "memory_operand" "m"))
9468    (set (match_operand:SI 3 "s_register_operand" "=r")
9469         (match_operand:SI 7 "memory_operand" "m"))]
9470   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9471   "*
9472   return emit_ldm_seq (operands, 4);
9473   "
9474 )
9475
9476 (define_peephole
9477   [(set (match_operand:SI 0 "s_register_operand" "=r")
9478         (match_operand:SI 3 "memory_operand" "m"))
9479    (set (match_operand:SI 1 "s_register_operand" "=r")
9480         (match_operand:SI 4 "memory_operand" "m"))
9481    (set (match_operand:SI 2 "s_register_operand" "=r")
9482         (match_operand:SI 5 "memory_operand" "m"))]
9483   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9484   "*
9485   return emit_ldm_seq (operands, 3);
9486   "
9487 )
9488
9489 (define_peephole
9490   [(set (match_operand:SI 0 "s_register_operand" "=r")
9491         (match_operand:SI 2 "memory_operand" "m"))
9492    (set (match_operand:SI 1 "s_register_operand" "=r")
9493         (match_operand:SI 3 "memory_operand" "m"))]
9494   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9495   "*
9496   return emit_ldm_seq (operands, 2);
9497   "
9498 )
9499
9500 (define_peephole
9501   [(set (match_operand:SI 4 "memory_operand" "=m")
9502         (match_operand:SI 0 "s_register_operand" "r"))
9503    (set (match_operand:SI 5 "memory_operand" "=m")
9504         (match_operand:SI 1 "s_register_operand" "r"))
9505    (set (match_operand:SI 6 "memory_operand" "=m")
9506         (match_operand:SI 2 "s_register_operand" "r"))
9507    (set (match_operand:SI 7 "memory_operand" "=m")
9508         (match_operand:SI 3 "s_register_operand" "r"))]
9509   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9510   "*
9511   return emit_stm_seq (operands, 4);
9512   "
9513 )
9514
9515 (define_peephole
9516   [(set (match_operand:SI 3 "memory_operand" "=m")
9517         (match_operand:SI 0 "s_register_operand" "r"))
9518    (set (match_operand:SI 4 "memory_operand" "=m")
9519         (match_operand:SI 1 "s_register_operand" "r"))
9520    (set (match_operand:SI 5 "memory_operand" "=m")
9521         (match_operand:SI 2 "s_register_operand" "r"))]
9522   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9523   "*
9524   return emit_stm_seq (operands, 3);
9525   "
9526 )
9527
9528 (define_peephole
9529   [(set (match_operand:SI 2 "memory_operand" "=m")
9530         (match_operand:SI 0 "s_register_operand" "r"))
9531    (set (match_operand:SI 3 "memory_operand" "=m")
9532         (match_operand:SI 1 "s_register_operand" "r"))]
9533   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9534   "*
9535   return emit_stm_seq (operands, 2);
9536   "
9537 )
9538
9539 (define_split
9540   [(set (match_operand:SI 0 "s_register_operand" "")
9541         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9542                        (const_int 0))
9543                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9544                          [(match_operand:SI 3 "s_register_operand" "")
9545                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9546    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9547   "TARGET_ARM"
9548   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9549    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9550                               (match_dup 5)))]
9551   ""
9552 )
9553
9554 ;; This split can be used because CC_Z mode implies that the following
9555 ;; branch will be an equality, or an unsigned inequality, so the sign
9556 ;; extension is not needed.
9557
9558 (define_split
9559   [(set (reg:CC_Z CC_REGNUM)
9560         (compare:CC_Z
9561          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9562                     (const_int 24))
9563          (match_operand 1 "const_int_operand" "")))
9564    (clobber (match_scratch:SI 2 ""))]
9565   "TARGET_ARM
9566    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9567        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9568   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9569    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9570   "
9571   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9572   "
9573 )
9574
9575 (define_expand "prologue"
9576   [(clobber (const_int 0))]
9577   "TARGET_EITHER"
9578   "if (TARGET_ARM)
9579      arm_expand_prologue ();
9580    else
9581      thumb_expand_prologue ();
9582   DONE;
9583   "
9584 )
9585
9586 (define_expand "epilogue"
9587   [(clobber (const_int 0))]
9588   "TARGET_EITHER"
9589   "
9590   if (current_function_calls_eh_return)
9591     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9592   if (TARGET_THUMB)
9593     thumb_expand_epilogue ();
9594   else if (USE_RETURN_INSN (FALSE))
9595     {
9596       emit_jump_insn (gen_return ());
9597       DONE;
9598     }
9599   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9600         gen_rtvec (1,
9601                 gen_rtx_RETURN (VOIDmode)),
9602         VUNSPEC_EPILOGUE));
9603   DONE;
9604   "
9605 )
9606
9607 ;; Note - although unspec_volatile's USE all hard registers,
9608 ;; USEs are ignored after relaod has completed.  Thus we need
9609 ;; to add an unspec of the link register to ensure that flow
9610 ;; does not think that it is unused by the sibcall branch that
9611 ;; will replace the standard function epilogue.
9612 (define_insn "sibcall_epilogue"
9613   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9614               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9615   "TARGET_ARM"
9616   "*
9617   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9618     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9619   return arm_output_epilogue (next_nonnote_insn (insn));
9620   "
9621 ;; Length is absolute worst case
9622   [(set_attr "length" "44")
9623    (set_attr "type" "block")
9624    ;; We don't clobber the conditions, but the potential length of this
9625    ;; operation is sufficient to make conditionalizing the sequence 
9626    ;; unlikely to be profitable.
9627    (set_attr "conds" "clob")]
9628 )
9629
9630 (define_insn "*epilogue_insns"
9631   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9632   "TARGET_EITHER"
9633   "*
9634   if (TARGET_ARM)
9635     return arm_output_epilogue (NULL);
9636   else /* TARGET_THUMB */
9637     return thumb_unexpanded_epilogue ();
9638   "
9639   ; Length is absolute worst case
9640   [(set_attr "length" "44")
9641    (set_attr "type" "block")
9642    ;; We don't clobber the conditions, but the potential length of this
9643    ;; operation is sufficient to make conditionalizing the sequence 
9644    ;; unlikely to be profitable.
9645    (set_attr "conds" "clob")]
9646 )
9647
9648 (define_expand "eh_epilogue"
9649   [(use (match_operand:SI 0 "register_operand" ""))
9650    (use (match_operand:SI 1 "register_operand" ""))
9651    (use (match_operand:SI 2 "register_operand" ""))]
9652   "TARGET_EITHER"
9653   "
9654   {
9655     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9656     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9657       {
9658         rtx ra = gen_rtx_REG (Pmode, 2);
9659
9660         emit_move_insn (ra, operands[2]);
9661         operands[2] = ra;
9662       }
9663     /* This is a hack -- we may have crystalized the function type too
9664        early.  */
9665     cfun->machine->func_type = 0;
9666   }"
9667 )
9668
9669 ;; This split is only used during output to reduce the number of patterns
9670 ;; that need assembler instructions adding to them.  We allowed the setting
9671 ;; of the conditions to be implicit during rtl generation so that
9672 ;; the conditional compare patterns would work.  However this conflicts to
9673 ;; some extent with the conditional data operations, so we have to split them
9674 ;; up again here.
9675
9676 (define_split
9677   [(set (match_operand:SI 0 "s_register_operand" "")
9678         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9679                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9680                          (match_dup 0)
9681                          (match_operand 4 "" "")))
9682    (clobber (reg:CC CC_REGNUM))]
9683   "TARGET_ARM && reload_completed"
9684   [(set (match_dup 5) (match_dup 6))
9685    (cond_exec (match_dup 7)
9686               (set (match_dup 0) (match_dup 4)))]
9687   "
9688   {
9689     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9690                                              operands[2], operands[3]);
9691     enum rtx_code rc = GET_CODE (operands[1]);
9692
9693     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9694     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9695     if (mode == CCFPmode || mode == CCFPEmode)
9696       rc = reverse_condition_maybe_unordered (rc);
9697     else
9698       rc = reverse_condition (rc);
9699
9700     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9701   }"
9702 )
9703
9704 (define_split
9705   [(set (match_operand:SI 0 "s_register_operand" "")
9706         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9707                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9708                          (match_operand 4 "" "")
9709                          (match_dup 0)))
9710    (clobber (reg:CC CC_REGNUM))]
9711   "TARGET_ARM && reload_completed"
9712   [(set (match_dup 5) (match_dup 6))
9713    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9714               (set (match_dup 0) (match_dup 4)))]
9715   "
9716   {
9717     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9718                                              operands[2], operands[3]);
9719
9720     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9721     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9722   }"
9723 )
9724
9725 (define_split
9726   [(set (match_operand:SI 0 "s_register_operand" "")
9727         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9728                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9729                          (match_operand 4 "" "")
9730                          (match_operand 5 "" "")))
9731    (clobber (reg:CC CC_REGNUM))]
9732   "TARGET_ARM && reload_completed"
9733   [(set (match_dup 6) (match_dup 7))
9734    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9735               (set (match_dup 0) (match_dup 4)))
9736    (cond_exec (match_dup 8)
9737               (set (match_dup 0) (match_dup 5)))]
9738   "
9739   {
9740     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9741                                              operands[2], operands[3]);
9742     enum rtx_code rc = GET_CODE (operands[1]);
9743
9744     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9745     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9746     if (mode == CCFPmode || mode == CCFPEmode)
9747       rc = reverse_condition_maybe_unordered (rc);
9748     else
9749       rc = reverse_condition (rc);
9750
9751     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9752   }"
9753 )
9754
9755 (define_split
9756   [(set (match_operand:SI 0 "s_register_operand" "")
9757         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9758                           [(match_operand:SI 2 "s_register_operand" "")
9759                            (match_operand:SI 3 "arm_add_operand" "")])
9760                          (match_operand:SI 4 "arm_rhs_operand" "")
9761                          (not:SI
9762                           (match_operand:SI 5 "s_register_operand" ""))))
9763    (clobber (reg:CC CC_REGNUM))]
9764   "TARGET_ARM && reload_completed"
9765   [(set (match_dup 6) (match_dup 7))
9766    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9767               (set (match_dup 0) (match_dup 4)))
9768    (cond_exec (match_dup 8)
9769               (set (match_dup 0) (not:SI (match_dup 5))))]
9770   "
9771   {
9772     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9773                                              operands[2], operands[3]);
9774     enum rtx_code rc = GET_CODE (operands[1]);
9775
9776     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9777     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9778     if (mode == CCFPmode || mode == CCFPEmode)
9779       rc = reverse_condition_maybe_unordered (rc);
9780     else
9781       rc = reverse_condition (rc);
9782
9783     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9784   }"
9785 )
9786
9787 (define_insn "*cond_move_not"
9788   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9789         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9790                           [(match_operand 3 "cc_register" "") (const_int 0)])
9791                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9792                          (not:SI
9793                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9794   "TARGET_ARM"
9795   "@
9796    mvn%D4\\t%0, %2
9797    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9798   [(set_attr "conds" "use")
9799    (set_attr "length" "4,8")]
9800 )
9801
9802 ;; The next two patterns occur when an AND operation is followed by a
9803 ;; scc insn sequence 
9804
9805 (define_insn "*sign_extract_onebit"
9806   [(set (match_operand:SI 0 "s_register_operand" "=r")
9807         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9808                          (const_int 1)
9809                          (match_operand:SI 2 "const_int_operand" "n")))
9810     (clobber (reg:CC CC_REGNUM))]
9811   "TARGET_ARM"
9812   "*
9813     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9814     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9815     return \"mvnne\\t%0, #0\";
9816   "
9817   [(set_attr "conds" "clob")
9818    (set_attr "length" "8")]
9819 )
9820
9821 (define_insn "*not_signextract_onebit"
9822   [(set (match_operand:SI 0 "s_register_operand" "=r")
9823         (not:SI
9824          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9825                           (const_int 1)
9826                           (match_operand:SI 2 "const_int_operand" "n"))))
9827    (clobber (reg:CC CC_REGNUM))]
9828   "TARGET_ARM"
9829   "*
9830     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9831     output_asm_insn (\"tst\\t%1, %2\", operands);
9832     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9833     return \"movne\\t%0, #0\";
9834   "
9835   [(set_attr "conds" "clob")
9836    (set_attr "length" "12")]
9837 )
9838
9839 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9840 ;; expressions.  For simplicity, the first register is also in the unspec
9841 ;; part.
9842 (define_insn "*push_multi"
9843   [(match_parallel 2 "multi_register_push"
9844     [(set (match_operand:BLK 0 "memory_operand" "=m")
9845           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9846                       UNSPEC_PUSH_MULT))])]
9847   "TARGET_ARM"
9848   "*
9849   {
9850     int num_saves = XVECLEN (operands[2], 0);
9851      
9852     /* For the StrongARM at least it is faster to
9853        use STR to store only a single register.  */
9854     if (num_saves == 1)
9855       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9856     else
9857       {
9858         int i;
9859         char pattern[100];
9860
9861         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9862
9863         for (i = 1; i < num_saves; i++)
9864           {
9865             strcat (pattern, \", %|\");
9866             strcat (pattern,
9867                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9868           }
9869
9870         strcat (pattern, \"}\");
9871         output_asm_insn (pattern, operands);
9872       }
9873
9874     return \"\";
9875   }"
9876   [(set_attr "type" "store4")]
9877 )
9878
9879 (define_insn "stack_tie"
9880   [(set (mem:BLK (scratch))
9881         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9882                      (match_operand:SI 1 "s_register_operand" "r")]
9883                     UNSPEC_PRLG_STK))]
9884   ""
9885   ""
9886   [(set_attr "length" "0")]
9887 )
9888
9889 ;; Similarly for the floating point registers
9890 (define_insn "*push_fp_multi"
9891   [(match_parallel 2 "multi_register_push"
9892     [(set (match_operand:BLK 0 "memory_operand" "=m")
9893           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9894                       UNSPEC_PUSH_MULT))])]
9895   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
9896   "*
9897   {
9898     char pattern[100];
9899
9900     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9901     output_asm_insn (pattern, operands);
9902     return \"\";
9903   }"
9904   [(set_attr "type" "f_store")]
9905 )
9906
9907 ;; Special patterns for dealing with the constant pool
9908
9909 (define_insn "align_4"
9910   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9911   "TARGET_EITHER"
9912   "*
9913   assemble_align (32);
9914   return \"\";
9915   "
9916 )
9917
9918 (define_insn "align_8"
9919   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9920   "TARGET_EITHER"
9921   "*
9922   assemble_align (64);
9923   return \"\";
9924   "
9925 )
9926
9927 (define_insn "consttable_end"
9928   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9929   "TARGET_EITHER"
9930   "*
9931   making_const_table = FALSE;
9932   return \"\";
9933   "
9934 )
9935
9936 (define_insn "consttable_1"
9937   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9938   "TARGET_THUMB"
9939   "*
9940   making_const_table = TRUE;
9941   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9942   assemble_zeros (3);
9943   return \"\";
9944   "
9945   [(set_attr "length" "4")]
9946 )
9947
9948 (define_insn "consttable_2"
9949   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9950   "TARGET_THUMB"
9951   "*
9952   making_const_table = TRUE;
9953   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9954   assemble_zeros (2);
9955   return \"\";
9956   "
9957   [(set_attr "length" "4")]
9958 )
9959
9960 (define_insn "consttable_4"
9961   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9962   "TARGET_EITHER"
9963   "*
9964   {
9965     making_const_table = TRUE;
9966     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9967       {
9968       case MODE_FLOAT:
9969       {
9970         REAL_VALUE_TYPE r;
9971         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9972         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9973         break;
9974       }
9975       default:
9976         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9977         break;
9978       }
9979     return \"\";
9980   }"
9981   [(set_attr "length" "4")]
9982 )
9983
9984 (define_insn "consttable_8"
9985   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9986   "TARGET_EITHER"
9987   "*
9988   {
9989     making_const_table = TRUE;
9990     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9991       {
9992        case MODE_FLOAT:
9993         {
9994           REAL_VALUE_TYPE r;
9995           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9996           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9997           break;
9998         }
9999       default:
10000         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10001         break;
10002       }
10003     return \"\";
10004   }"
10005   [(set_attr "length" "8")]
10006 )
10007
10008 ;; Miscellaneous Thumb patterns
10009
10010 (define_expand "tablejump"
10011   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10012               (use (label_ref (match_operand 1 "" "")))])]
10013   "TARGET_THUMB"
10014   "
10015   if (flag_pic)
10016     {
10017       /* Hopefully, CSE will eliminate this copy.  */
10018       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10019       rtx reg2 = gen_reg_rtx (SImode);
10020
10021       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10022       operands[0] = reg2;
10023     }
10024   "
10025 )
10026
10027 ;; NB never uses BX.
10028 (define_insn "*thumb_tablejump"
10029   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10030    (use (label_ref (match_operand 1 "" "")))]
10031   "TARGET_THUMB"
10032   "mov\\t%|pc, %0"
10033   [(set_attr "length" "2")]
10034 )
10035
10036 ;; V5 Instructions,
10037
10038 (define_insn "clzsi2"
10039   [(set (match_operand:SI 0 "s_register_operand" "=r")
10040         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10041   "TARGET_ARM && arm_arch5"
10042   "clz%?\\t%0, %1"
10043   [(set_attr "predicable" "yes")])
10044
10045 (define_expand "ffssi2"
10046   [(set (match_operand:SI 0 "s_register_operand" "")
10047         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10048   "TARGET_ARM && arm_arch5"
10049   "
10050   {
10051     rtx t1, t2, t3;
10052
10053     t1 = gen_reg_rtx (SImode);
10054     t2 = gen_reg_rtx (SImode);
10055     t3 = gen_reg_rtx (SImode);
10056
10057     emit_insn (gen_negsi2 (t1, operands[1]));
10058     emit_insn (gen_andsi3 (t2, operands[1], t1));
10059     emit_insn (gen_clzsi2 (t3, t2));
10060     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10061     DONE;
10062   }"
10063 )
10064
10065 (define_expand "ctzsi2"
10066   [(set (match_operand:SI 0 "s_register_operand" "")
10067         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10068   "TARGET_ARM && arm_arch5"
10069   "
10070   {
10071     rtx t1, t2, t3;
10072
10073     t1 = gen_reg_rtx (SImode);
10074     t2 = gen_reg_rtx (SImode);
10075     t3 = gen_reg_rtx (SImode);
10076
10077     emit_insn (gen_negsi2 (t1, operands[1]));
10078     emit_insn (gen_andsi3 (t2, operands[1], t1));
10079     emit_insn (gen_clzsi2 (t3, t2));
10080     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10081     DONE;
10082   }"
10083 )
10084
10085 ;; V5E instructions.
10086
10087 (define_insn "prefetch"
10088   [(prefetch (match_operand:SI 0 "address_operand" "p")
10089              (match_operand:SI 1 "" "")
10090              (match_operand:SI 2 "" ""))]
10091   "TARGET_ARM && arm_arch5e"
10092   "pld\\t%a0")
10093
10094 ;; General predication pattern
10095
10096 (define_cond_exec
10097   [(match_operator 0 "arm_comparison_operator"
10098     [(match_operand 1 "cc_register" "")
10099      (const_int 0)])]
10100   "TARGET_ARM"
10101   ""
10102 )
10103
10104 (define_insn "prologue_use"
10105   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10106   ""
10107   "%@ %0 needed for prologue"
10108 )
10109
10110
10111 ;; Patterns for exception handling
10112
10113 (define_expand "eh_return"
10114   [(use (match_operand 0 "general_operand" ""))]
10115   "TARGET_EITHER"
10116   "
10117   {
10118     if (TARGET_ARM)
10119       emit_insn (gen_arm_eh_return (operands[0]));
10120     else
10121       emit_insn (gen_thumb_eh_return (operands[0]));
10122     DONE;
10123   }"
10124 )
10125                                    
10126 ;; We can't expand this before we know where the link register is stored.
10127 (define_insn_and_split "arm_eh_return"
10128   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10129                     VUNSPEC_EH_RETURN)
10130    (clobber (match_scratch:SI 1 "=&r"))]
10131   "TARGET_ARM"
10132   "#"
10133   "&& reload_completed"
10134   [(const_int 0)]
10135   "
10136   {
10137     arm_set_return_address (operands[0], operands[1]);
10138     DONE;
10139   }"
10140 )
10141
10142 (define_insn_and_split "thumb_eh_return"
10143   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10144                     VUNSPEC_EH_RETURN)
10145    (clobber (match_scratch:SI 1 "=&l"))]
10146   "TARGET_THUMB"
10147   "#"
10148   "&& reload_completed"
10149   [(const_int 0)]
10150   "
10151   {
10152     thumb_set_return_address (operands[0], operands[1]);
10153     DONE;
10154   }"
10155 )
10156
10157 \f
10158 ;; TLS support
10159
10160 (define_insn "load_tp_hard"
10161   [(set (match_operand:SI 0 "register_operand" "=r")
10162         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10163   "TARGET_HARD_TP"
10164   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10165   [(set_attr "predicable" "yes")]
10166 )
10167
10168 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
10169 (define_insn "load_tp_soft"
10170   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10171    (clobber (reg:SI LR_REGNUM))
10172    (clobber (reg:SI IP_REGNUM))
10173    (clobber (reg:CC CC_REGNUM))]
10174   "TARGET_SOFT_TP"
10175   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10176   [(set_attr "conds" "clob")]
10177 )
10178
10179 ;; Load the FPA co-processor patterns
10180 (include "fpa.md")
10181 ;; Load the Maverick co-processor patterns
10182 (include "cirrus.md")
10183 ;; Load the Intel Wireless Multimedia Extension patterns
10184 (include "iwmmxt.md")
10185 ;; Load the VFP co-processor patterns
10186 (include "vfp.md")
10187