OSDN Git Service

* arm.md (abssi2): Allow Thumb as well. Use an SImode scratch for
[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 (include "constraints.md")
313
314 ;;---------------------------------------------------------------------------
315 ;; Pipeline descriptions
316
317 ;; Processor type.  This is created automatically from arm-cores.def.
318 (include "arm-tune.md")
319
320 ;; True if the generic scheduling description should be used.
321
322 (define_attr "generic_sched" "yes,no"
323   (const (if_then_else 
324           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 
325           (const_string "no")
326           (const_string "yes"))))
327
328 (define_attr "generic_vfp" "yes,no"
329   (const (if_then_else
330           (and (eq_attr "fpu" "vfp")
331                (eq_attr "tune" "!arm1020e,arm1022e"))
332           (const_string "yes")
333           (const_string "no"))))
334
335 (include "arm-generic.md")
336 (include "arm926ejs.md")
337 (include "arm1020e.md")
338 (include "arm1026ejs.md")
339 (include "arm1136jfs.md")
340
341 \f
342 ;;---------------------------------------------------------------------------
343 ;; Insn patterns
344 ;;
345 ;; Addition insns.
346
347 ;; Note: For DImode insns, there is normally no reason why operands should
348 ;; not be in the same register, what we don't want is for something being
349 ;; written to partially overlap something that is an input.
350 ;; Cirrus 64bit additions should not be split because we have a native
351 ;; 64bit addition instructions.
352
353 (define_expand "adddi3"
354  [(parallel
355    [(set (match_operand:DI           0 "s_register_operand" "")
356           (plus:DI (match_operand:DI 1 "s_register_operand" "")
357                    (match_operand:DI 2 "s_register_operand" "")))
358     (clobber (reg:CC CC_REGNUM))])]
359   "TARGET_EITHER"
360   "
361   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
362     {
363       if (!cirrus_fp_register (operands[0], DImode))
364         operands[0] = force_reg (DImode, operands[0]);
365       if (!cirrus_fp_register (operands[1], DImode))
366         operands[1] = force_reg (DImode, operands[1]);
367       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
368       DONE;
369     }
370
371   if (TARGET_THUMB)
372     {
373       if (GET_CODE (operands[1]) != REG)
374         operands[1] = force_reg (SImode, operands[1]);
375       if (GET_CODE (operands[2]) != REG)
376         operands[2] = force_reg (SImode, operands[2]);
377      }
378   "
379 )
380
381 (define_insn "*thumb_adddi3"
382   [(set (match_operand:DI          0 "register_operand" "=l")
383         (plus:DI (match_operand:DI 1 "register_operand" "%0")
384                  (match_operand:DI 2 "register_operand" "l")))
385    (clobber (reg:CC CC_REGNUM))
386   ]
387   "TARGET_THUMB"
388   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
389   [(set_attr "length" "4")]
390 )
391
392 (define_insn_and_split "*arm_adddi3"
393   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
394         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
395                  (match_operand:DI 2 "s_register_operand" "r,  0")))
396    (clobber (reg:CC CC_REGNUM))]
397   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
398   "#"
399   "TARGET_ARM && reload_completed"
400   [(parallel [(set (reg:CC_C CC_REGNUM)
401                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
402                                  (match_dup 1)))
403               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
404    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
405                                (plus:SI (match_dup 4) (match_dup 5))))]
406   "
407   {
408     operands[3] = gen_highpart (SImode, operands[0]);
409     operands[0] = gen_lowpart (SImode, operands[0]);
410     operands[4] = gen_highpart (SImode, operands[1]);
411     operands[1] = gen_lowpart (SImode, operands[1]);
412     operands[5] = gen_highpart (SImode, operands[2]);
413     operands[2] = gen_lowpart (SImode, operands[2]);
414   }"
415   [(set_attr "conds" "clob")
416    (set_attr "length" "8")]
417 )
418
419 (define_insn_and_split "*adddi_sesidi_di"
420   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
421         (plus:DI (sign_extend:DI
422                   (match_operand:SI 2 "s_register_operand" "r,r"))
423                  (match_operand:DI 1 "s_register_operand" "r,0")))
424    (clobber (reg:CC CC_REGNUM))]
425   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
426   "#"
427   "TARGET_ARM && reload_completed"
428   [(parallel [(set (reg:CC_C CC_REGNUM)
429                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
430                                  (match_dup 1)))
431               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
432    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
433                                (plus:SI (ashiftrt:SI (match_dup 2)
434                                                      (const_int 31))
435                                         (match_dup 4))))]
436   "
437   {
438     operands[3] = gen_highpart (SImode, operands[0]);
439     operands[0] = gen_lowpart (SImode, operands[0]);
440     operands[4] = gen_highpart (SImode, operands[1]);
441     operands[1] = gen_lowpart (SImode, operands[1]);
442     operands[2] = gen_lowpart (SImode, operands[2]);
443   }"
444   [(set_attr "conds" "clob")
445    (set_attr "length" "8")]
446 )
447
448 (define_insn_and_split "*adddi_zesidi_di"
449   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
450         (plus:DI (zero_extend:DI
451                   (match_operand:SI 2 "s_register_operand" "r,r"))
452                  (match_operand:DI 1 "s_register_operand" "r,0")))
453    (clobber (reg:CC CC_REGNUM))]
454   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
455   "#"
456   "TARGET_ARM && reload_completed"
457   [(parallel [(set (reg:CC_C CC_REGNUM)
458                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
459                                  (match_dup 1)))
460               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
461    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
462                                (plus:SI (match_dup 4) (const_int 0))))]
463   "
464   {
465     operands[3] = gen_highpart (SImode, operands[0]);
466     operands[0] = gen_lowpart (SImode, operands[0]);
467     operands[4] = gen_highpart (SImode, operands[1]);
468     operands[1] = gen_lowpart (SImode, operands[1]);
469     operands[2] = gen_lowpart (SImode, operands[2]);
470   }"
471   [(set_attr "conds" "clob")
472    (set_attr "length" "8")]
473 )
474
475 (define_expand "addsi3"
476   [(set (match_operand:SI          0 "s_register_operand" "")
477         (plus:SI (match_operand:SI 1 "s_register_operand" "")
478                  (match_operand:SI 2 "reg_or_int_operand" "")))]
479   "TARGET_EITHER"
480   "
481   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
482     {
483       arm_split_constant (PLUS, SImode, NULL_RTX,
484                           INTVAL (operands[2]), operands[0], operands[1],
485                           optimize && !no_new_pseudos);
486       DONE;
487     }
488   "
489 )
490
491 ; If there is a scratch available, this will be faster than synthesizing the
492 ; addition.
493 (define_peephole2
494   [(match_scratch:SI 3 "r")
495    (set (match_operand:SI          0 "arm_general_register_operand" "")
496         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
497                  (match_operand:SI 2 "const_int_operand"  "")))]
498   "TARGET_ARM &&
499    !(const_ok_for_arm (INTVAL (operands[2]))
500      || const_ok_for_arm (-INTVAL (operands[2])))
501     && const_ok_for_arm (~INTVAL (operands[2]))"
502   [(set (match_dup 3) (match_dup 2))
503    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
504   ""
505 )
506
507 (define_insn_and_split "*arm_addsi3"
508   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
509         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
510                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
511   "TARGET_ARM"
512   "@
513    add%?\\t%0, %1, %2
514    sub%?\\t%0, %1, #%n2
515    #"
516   "TARGET_ARM &&
517    GET_CODE (operands[2]) == CONST_INT
518    && !(const_ok_for_arm (INTVAL (operands[2]))
519         || const_ok_for_arm (-INTVAL (operands[2])))"
520   [(clobber (const_int 0))]
521   "
522   arm_split_constant (PLUS, SImode, curr_insn,
523                       INTVAL (operands[2]), operands[0],
524                       operands[1], 0);
525   DONE;
526   "
527   [(set_attr "length" "4,4,16")
528    (set_attr "predicable" "yes")]
529 )
530
531 ;; Register group 'k' is a single register group containing only the stack
532 ;; register.  Trying to reload it will always fail catastrophically,
533 ;; so never allow those alternatives to match if reloading is needed.
534
535 (define_insn "*thumb_addsi3"
536   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
537         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
538                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
539   "TARGET_THUMB"
540   "*
541    static const char * const asms[] = 
542    {
543      \"add\\t%0, %0, %2\",
544      \"sub\\t%0, %0, #%n2\",
545      \"add\\t%0, %1, %2\",
546      \"add\\t%0, %0, %2\",
547      \"add\\t%0, %0, %2\",
548      \"add\\t%0, %1, %2\",
549      \"add\\t%0, %1, %2\"
550    };
551    if ((which_alternative == 2 || which_alternative == 6)
552        && GET_CODE (operands[2]) == CONST_INT
553        && INTVAL (operands[2]) < 0)
554      return \"sub\\t%0, %1, #%n2\";
555    return asms[which_alternative];
556   "
557   [(set_attr "length" "2")]
558 )
559
560 ;; Reloading and elimination of the frame pointer can
561 ;; sometimes cause this optimization to be missed.
562 (define_peephole2
563   [(set (match_operand:SI 0 "arm_general_register_operand" "")
564         (match_operand:SI 1 "const_int_operand" ""))
565    (set (match_dup 0)
566         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
567   "TARGET_THUMB
568    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
569    && (INTVAL (operands[1]) & 3) == 0"
570   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
571   ""
572 )
573
574 (define_insn "*addsi3_compare0"
575   [(set (reg:CC_NOOV CC_REGNUM)
576         (compare:CC_NOOV
577          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
578                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
579          (const_int 0)))
580    (set (match_operand:SI 0 "s_register_operand" "=r,r")
581         (plus:SI (match_dup 1) (match_dup 2)))]
582   "TARGET_ARM"
583   "@
584    add%?s\\t%0, %1, %2
585    sub%?s\\t%0, %1, #%n2"
586   [(set_attr "conds" "set")]
587 )
588
589 (define_insn "*addsi3_compare0_scratch"
590   [(set (reg:CC_NOOV CC_REGNUM)
591         (compare:CC_NOOV
592          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
593                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
594          (const_int 0)))]
595   "TARGET_ARM"
596   "@
597    cmn%?\\t%0, %1
598    cmp%?\\t%0, #%n1"
599   [(set_attr "conds" "set")]
600 )
601
602 (define_insn "*compare_negsi_si"
603   [(set (reg:CC_Z CC_REGNUM)
604         (compare:CC_Z
605          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
606          (match_operand:SI 1 "s_register_operand" "r")))]
607   "TARGET_ARM"
608   "cmn%?\\t%1, %0"
609   [(set_attr "conds" "set")]
610 )
611
612 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
613 ;; addend is a constant.
614 (define_insn "*cmpsi2_addneg"
615   [(set (reg:CC CC_REGNUM)
616         (compare:CC
617          (match_operand:SI 1 "s_register_operand" "r,r")
618          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
619    (set (match_operand:SI 0 "s_register_operand" "=r,r")
620         (plus:SI (match_dup 1)
621                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
622   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
623   "@
624    sub%?s\\t%0, %1, %2
625    add%?s\\t%0, %1, #%n2"
626   [(set_attr "conds" "set")]
627 )
628
629 ;; Convert the sequence
630 ;;  sub  rd, rn, #1
631 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
632 ;;  bne  dest
633 ;; into
634 ;;  subs rd, rn, #1
635 ;;  bcs  dest   ((unsigned)rn >= 1)
636 ;; similarly for the beq variant using bcc.
637 ;; This is a common looping idiom (while (n--))
638 (define_peephole2
639   [(set (match_operand:SI 0 "arm_general_register_operand" "")
640         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
641                  (const_int -1)))
642    (set (match_operand 2 "cc_register" "")
643         (compare (match_dup 0) (const_int -1)))
644    (set (pc)
645         (if_then_else (match_operator 3 "equality_operator"
646                        [(match_dup 2) (const_int 0)])
647                       (match_operand 4 "" "")
648                       (match_operand 5 "" "")))]
649   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
650   [(parallel[
651     (set (match_dup 2)
652          (compare:CC
653           (match_dup 1) (const_int 1)))
654     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
655    (set (pc)
656         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
657                       (match_dup 4)
658                       (match_dup 5)))]
659   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
660    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
661                                   ? GEU : LTU),
662                                  VOIDmode, 
663                                  operands[2], const0_rtx);"
664 )
665
666 ;; The next four insns work because they compare the result with one of
667 ;; the operands, and we know that the use of the condition code is
668 ;; either GEU or LTU, so we can use the carry flag from the addition
669 ;; instead of doing the compare a second time.
670 (define_insn "*addsi3_compare_op1"
671   [(set (reg:CC_C CC_REGNUM)
672         (compare:CC_C
673          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
674                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
675          (match_dup 1)))
676    (set (match_operand:SI 0 "s_register_operand" "=r,r")
677         (plus:SI (match_dup 1) (match_dup 2)))]
678   "TARGET_ARM"
679   "@
680    add%?s\\t%0, %1, %2
681    sub%?s\\t%0, %1, #%n2"
682   [(set_attr "conds" "set")]
683 )
684
685 (define_insn "*addsi3_compare_op2"
686   [(set (reg:CC_C CC_REGNUM)
687         (compare:CC_C
688          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
689                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
690          (match_dup 2)))
691    (set (match_operand:SI 0 "s_register_operand" "=r,r")
692         (plus:SI (match_dup 1) (match_dup 2)))]
693   "TARGET_ARM"
694   "@
695    add%?s\\t%0, %1, %2
696    sub%?s\\t%0, %1, #%n2"
697   [(set_attr "conds" "set")]
698 )
699
700 (define_insn "*compare_addsi2_op0"
701   [(set (reg:CC_C CC_REGNUM)
702         (compare:CC_C
703          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
704                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
705          (match_dup 0)))]
706   "TARGET_ARM"
707   "@
708    cmn%?\\t%0, %1
709    cmp%?\\t%0, #%n1"
710   [(set_attr "conds" "set")]
711 )
712
713 (define_insn "*compare_addsi2_op1"
714   [(set (reg:CC_C CC_REGNUM)
715         (compare:CC_C
716          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
717                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
718          (match_dup 1)))]
719   "TARGET_ARM"
720   "@
721    cmn%?\\t%0, %1
722    cmp%?\\t%0, #%n1"
723   [(set_attr "conds" "set")]
724 )
725
726 (define_insn "*addsi3_carryin"
727   [(set (match_operand:SI 0 "s_register_operand" "=r")
728         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
729                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
730                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
731   "TARGET_ARM"
732   "adc%?\\t%0, %1, %2"
733   [(set_attr "conds" "use")]
734 )
735
736 (define_insn "*addsi3_carryin_shift"
737   [(set (match_operand:SI 0 "s_register_operand" "=r")
738         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
739                  (plus:SI
740                    (match_operator:SI 2 "shift_operator"
741                       [(match_operand:SI 3 "s_register_operand" "r")
742                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
743                     (match_operand:SI 1 "s_register_operand" "r"))))]
744   "TARGET_ARM"
745   "adc%?\\t%0, %1, %3%S2"
746   [(set_attr "conds" "use")
747    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
748                       (const_string "alu_shift")
749                       (const_string "alu_shift_reg")))]
750 )
751
752 (define_insn "*addsi3_carryin_alt1"
753   [(set (match_operand:SI 0 "s_register_operand" "=r")
754         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
755                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
756                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
757   "TARGET_ARM"
758   "adc%?\\t%0, %1, %2"
759   [(set_attr "conds" "use")]
760 )
761
762 (define_insn "*addsi3_carryin_alt2"
763   [(set (match_operand:SI 0 "s_register_operand" "=r")
764         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
765                           (match_operand:SI 1 "s_register_operand" "r"))
766                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
767   "TARGET_ARM"
768   "adc%?\\t%0, %1, %2"
769   [(set_attr "conds" "use")]
770 )
771
772 (define_insn "*addsi3_carryin_alt3"
773   [(set (match_operand:SI 0 "s_register_operand" "=r")
774         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
775                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
776                  (match_operand:SI 1 "s_register_operand" "r")))]
777   "TARGET_ARM"
778   "adc%?\\t%0, %1, %2"
779   [(set_attr "conds" "use")]
780 )
781
782 (define_insn "incscc"
783   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
784         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
785                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
786                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
787   "TARGET_ARM"
788   "@
789   add%d2\\t%0, %1, #1
790   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
791   [(set_attr "conds" "use")
792    (set_attr "length" "4,8")]
793 )
794
795 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
796 (define_split
797   [(set (match_operand:SI 0 "s_register_operand" "")
798         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
799                             (match_operand:SI 2 "s_register_operand" ""))
800                  (const_int -1)))
801    (clobber (match_operand:SI 3 "s_register_operand" ""))]
802   "TARGET_ARM"
803   [(set (match_dup 3) (match_dup 1))
804    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
805   "
806   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
807 ")
808
809 (define_expand "addsf3"
810   [(set (match_operand:SF          0 "s_register_operand" "")
811         (plus:SF (match_operand:SF 1 "s_register_operand" "")
812                  (match_operand:SF 2 "arm_float_add_operand" "")))]
813   "TARGET_ARM && TARGET_HARD_FLOAT"
814   "
815   if (TARGET_MAVERICK
816       && !cirrus_fp_register (operands[2], SFmode))
817     operands[2] = force_reg (SFmode, operands[2]);
818 ")
819
820 (define_expand "adddf3"
821   [(set (match_operand:DF          0 "s_register_operand" "")
822         (plus:DF (match_operand:DF 1 "s_register_operand" "")
823                  (match_operand:DF 2 "arm_float_add_operand" "")))]
824   "TARGET_ARM && TARGET_HARD_FLOAT"
825   "
826   if (TARGET_MAVERICK
827       && !cirrus_fp_register (operands[2], DFmode))
828     operands[2] = force_reg (DFmode, operands[2]);
829 ")
830
831 (define_expand "subdi3"
832  [(parallel
833    [(set (match_operand:DI            0 "s_register_operand" "")
834           (minus:DI (match_operand:DI 1 "s_register_operand" "")
835                     (match_operand:DI 2 "s_register_operand" "")))
836     (clobber (reg:CC CC_REGNUM))])]
837   "TARGET_EITHER"
838   "
839   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
840       && TARGET_ARM
841       && cirrus_fp_register (operands[0], DImode)
842       && cirrus_fp_register (operands[1], DImode))
843     {
844       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
845       DONE;
846     }
847
848   if (TARGET_THUMB)
849     {
850       if (GET_CODE (operands[1]) != REG)
851         operands[1] = force_reg (SImode, operands[1]);
852       if (GET_CODE (operands[2]) != REG)
853         operands[2] = force_reg (SImode, operands[2]);
854      }  
855   "
856 )
857
858 (define_insn "*arm_subdi3"
859   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
860         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
861                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
862    (clobber (reg:CC CC_REGNUM))]
863   "TARGET_ARM"
864   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
865   [(set_attr "conds" "clob")
866    (set_attr "length" "8")]
867 )
868
869 (define_insn "*thumb_subdi3"
870   [(set (match_operand:DI           0 "register_operand" "=l")
871         (minus:DI (match_operand:DI 1 "register_operand"  "0")
872                   (match_operand:DI 2 "register_operand"  "l")))
873    (clobber (reg:CC CC_REGNUM))]
874   "TARGET_THUMB"
875   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
876   [(set_attr "length" "4")]
877 )
878
879 (define_insn "*subdi_di_zesidi"
880   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
881         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
882                   (zero_extend:DI
883                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
884    (clobber (reg:CC CC_REGNUM))]
885   "TARGET_ARM"
886   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
887   [(set_attr "conds" "clob")
888    (set_attr "length" "8")]
889 )
890
891 (define_insn "*subdi_di_sesidi"
892   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
893         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
894                   (sign_extend:DI
895                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
896    (clobber (reg:CC CC_REGNUM))]
897   "TARGET_ARM"
898   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
899   [(set_attr "conds" "clob")
900    (set_attr "length" "8")]
901 )
902
903 (define_insn "*subdi_zesidi_di"
904   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
905         (minus:DI (zero_extend:DI
906                    (match_operand:SI 2 "s_register_operand"  "r,r"))
907                   (match_operand:DI  1 "s_register_operand" "?r,0")))
908    (clobber (reg:CC CC_REGNUM))]
909   "TARGET_ARM"
910   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
911   [(set_attr "conds" "clob")
912    (set_attr "length" "8")]
913 )
914
915 (define_insn "*subdi_sesidi_di"
916   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
917         (minus:DI (sign_extend:DI
918                    (match_operand:SI 2 "s_register_operand"   "r,r"))
919                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
920    (clobber (reg:CC CC_REGNUM))]
921   "TARGET_ARM"
922   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
923   [(set_attr "conds" "clob")
924    (set_attr "length" "8")]
925 )
926
927 (define_insn "*subdi_zesidi_zesidi"
928   [(set (match_operand:DI            0 "s_register_operand" "=r")
929         (minus:DI (zero_extend:DI
930                    (match_operand:SI 1 "s_register_operand"  "r"))
931                   (zero_extend:DI
932                    (match_operand:SI 2 "s_register_operand"  "r"))))
933    (clobber (reg:CC CC_REGNUM))]
934   "TARGET_ARM"
935   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
936   [(set_attr "conds" "clob")
937    (set_attr "length" "8")]
938 )
939
940 (define_expand "subsi3"
941   [(set (match_operand:SI           0 "s_register_operand" "")
942         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
943                   (match_operand:SI 2 "s_register_operand" "")))]
944   "TARGET_EITHER"
945   "
946   if (GET_CODE (operands[1]) == CONST_INT)
947     {
948       if (TARGET_ARM)
949         {
950           arm_split_constant (MINUS, SImode, NULL_RTX,
951                               INTVAL (operands[1]), operands[0],
952                               operands[2], optimize && !no_new_pseudos);
953           DONE;
954         }
955       else /* TARGET_THUMB */
956         operands[1] = force_reg (SImode, operands[1]);
957     }
958   "
959 )
960
961 (define_insn "*thumb_subsi3_insn"
962   [(set (match_operand:SI           0 "register_operand" "=l")
963         (minus:SI (match_operand:SI 1 "register_operand" "l")
964                   (match_operand:SI 2 "register_operand" "l")))]
965   "TARGET_THUMB"
966   "sub\\t%0, %1, %2"
967   [(set_attr "length" "2")]
968 )
969
970 (define_insn_and_split "*arm_subsi3_insn"
971   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
972         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
973                   (match_operand:SI 2 "s_register_operand" "r,r")))]
974   "TARGET_ARM"
975   "@
976    rsb%?\\t%0, %2, %1
977    #"
978   "TARGET_ARM
979    && GET_CODE (operands[1]) == CONST_INT
980    && !const_ok_for_arm (INTVAL (operands[1]))"
981   [(clobber (const_int 0))]
982   "
983   arm_split_constant (MINUS, SImode, curr_insn,
984                       INTVAL (operands[1]), operands[0], operands[2], 0);
985   DONE;
986   "
987   [(set_attr "length" "4,16")
988    (set_attr "predicable" "yes")]
989 )
990
991 (define_peephole2
992   [(match_scratch:SI 3 "r")
993    (set (match_operand:SI 0 "arm_general_register_operand" "")
994         (minus:SI (match_operand:SI 1 "const_int_operand" "")
995                   (match_operand:SI 2 "arm_general_register_operand" "")))]
996   "TARGET_ARM
997    && !const_ok_for_arm (INTVAL (operands[1]))
998    && const_ok_for_arm (~INTVAL (operands[1]))"
999   [(set (match_dup 3) (match_dup 1))
1000    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1001   ""
1002 )
1003
1004 (define_insn "*subsi3_compare0"
1005   [(set (reg:CC_NOOV CC_REGNUM)
1006         (compare:CC_NOOV
1007          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1008                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1009          (const_int 0)))
1010    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1011         (minus:SI (match_dup 1) (match_dup 2)))]
1012   "TARGET_ARM"
1013   "@
1014    sub%?s\\t%0, %1, %2
1015    rsb%?s\\t%0, %2, %1"
1016   [(set_attr "conds" "set")]
1017 )
1018
1019 (define_insn "decscc"
1020   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1021         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1022                   (match_operator:SI 2 "arm_comparison_operator"
1023                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1024   "TARGET_ARM"
1025   "@
1026    sub%d2\\t%0, %1, #1
1027    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1028   [(set_attr "conds" "use")
1029    (set_attr "length" "*,8")]
1030 )
1031
1032 (define_expand "subsf3"
1033   [(set (match_operand:SF           0 "s_register_operand" "")
1034         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1035                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1036   "TARGET_ARM && TARGET_HARD_FLOAT"
1037   "
1038   if (TARGET_MAVERICK)
1039     {
1040       if (!cirrus_fp_register (operands[1], SFmode))
1041         operands[1] = force_reg (SFmode, operands[1]);
1042       if (!cirrus_fp_register (operands[2], SFmode))
1043         operands[2] = force_reg (SFmode, operands[2]);
1044     }
1045 ")
1046
1047 (define_expand "subdf3"
1048   [(set (match_operand:DF           0 "s_register_operand" "")
1049         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1050                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1051   "TARGET_ARM && TARGET_HARD_FLOAT"
1052   "
1053   if (TARGET_MAVERICK)
1054     {
1055        if (!cirrus_fp_register (operands[1], DFmode))
1056          operands[1] = force_reg (DFmode, operands[1]);
1057        if (!cirrus_fp_register (operands[2], DFmode))
1058          operands[2] = force_reg (DFmode, operands[2]);
1059     }
1060 ")
1061
1062 \f
1063 ;; Multiplication insns
1064
1065 (define_expand "mulsi3"
1066   [(set (match_operand:SI          0 "s_register_operand" "")
1067         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1068                  (match_operand:SI 1 "s_register_operand" "")))]
1069   "TARGET_EITHER"
1070   ""
1071 )
1072
1073 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1074 (define_insn "*arm_mulsi3"
1075   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1076         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1077                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1078   "TARGET_ARM"
1079   "mul%?\\t%0, %2, %1"
1080   [(set_attr "insn" "mul")
1081    (set_attr "predicable" "yes")]
1082 )
1083
1084 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1085 ; 1 and 2; are the same, because reload will make operand 0 match 
1086 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1087 ; this by adding another alternative to match this case, and then `reload' 
1088 ; it ourselves.  This alternative must come first.
1089 (define_insn "*thumb_mulsi3"
1090   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1091         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1092                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1093   "TARGET_THUMB"
1094   "*
1095   if (which_alternative < 2)
1096     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1097   else
1098     return \"mul\\t%0, %2\";
1099   "
1100   [(set_attr "length" "4,4,2")
1101    (set_attr "insn" "mul")]
1102 )
1103
1104 (define_insn "*mulsi3_compare0"
1105   [(set (reg:CC_NOOV CC_REGNUM)
1106         (compare:CC_NOOV (mult:SI
1107                           (match_operand:SI 2 "s_register_operand" "r,r")
1108                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1109                          (const_int 0)))
1110    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1111         (mult:SI (match_dup 2) (match_dup 1)))]
1112   "TARGET_ARM"
1113   "mul%?s\\t%0, %2, %1"
1114   [(set_attr "conds" "set")
1115    (set_attr "insn" "muls")]
1116 )
1117
1118 (define_insn "*mulsi_compare0_scratch"
1119   [(set (reg:CC_NOOV CC_REGNUM)
1120         (compare:CC_NOOV (mult:SI
1121                           (match_operand:SI 2 "s_register_operand" "r,r")
1122                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1123                          (const_int 0)))
1124    (clobber (match_scratch:SI 0 "=&r,&r"))]
1125   "TARGET_ARM"
1126   "mul%?s\\t%0, %2, %1"
1127   [(set_attr "conds" "set")
1128    (set_attr "insn" "muls")]
1129 )
1130
1131 ;; Unnamed templates to match MLA instruction.
1132
1133 (define_insn "*mulsi3addsi"
1134   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1135         (plus:SI
1136           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1137                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1138           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1139   "TARGET_ARM"
1140   "mla%?\\t%0, %2, %1, %3"
1141   [(set_attr "insn" "mla")
1142    (set_attr "predicable" "yes")]
1143 )
1144
1145 (define_insn "*mulsi3addsi_compare0"
1146   [(set (reg:CC_NOOV CC_REGNUM)
1147         (compare:CC_NOOV
1148          (plus:SI (mult:SI
1149                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1150                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1151                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1152          (const_int 0)))
1153    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1154         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1155                  (match_dup 3)))]
1156   "TARGET_ARM"
1157   "mla%?s\\t%0, %2, %1, %3"
1158   [(set_attr "conds" "set")
1159    (set_attr "insn" "mlas")]
1160 )
1161
1162 (define_insn "*mulsi3addsi_compare0_scratch"
1163   [(set (reg:CC_NOOV CC_REGNUM)
1164         (compare:CC_NOOV
1165          (plus:SI (mult:SI
1166                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1167                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1168                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1169          (const_int 0)))
1170    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1171   "TARGET_ARM"
1172   "mla%?s\\t%0, %2, %1, %3"
1173   [(set_attr "conds" "set")
1174    (set_attr "insn" "mlas")]
1175 )
1176
1177 ;; Unnamed template to match long long multiply-accumulate (smlal)
1178
1179 (define_insn "*mulsidi3adddi"
1180   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1181         (plus:DI
1182          (mult:DI
1183           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1184           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1185          (match_operand:DI 1 "s_register_operand" "0")))]
1186   "TARGET_ARM && arm_arch3m"
1187   "smlal%?\\t%Q0, %R0, %3, %2"
1188   [(set_attr "insn" "smlal")
1189    (set_attr "predicable" "yes")]
1190 )
1191
1192 (define_insn "mulsidi3"
1193   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1194         (mult:DI
1195          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1196          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1197   "TARGET_ARM && arm_arch3m"
1198   "smull%?\\t%Q0, %R0, %1, %2"
1199   [(set_attr "insn" "smull")
1200    (set_attr "predicable" "yes")]
1201 )
1202
1203 (define_insn "umulsidi3"
1204   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1205         (mult:DI
1206          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1207          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1208   "TARGET_ARM && arm_arch3m"
1209   "umull%?\\t%Q0, %R0, %1, %2"
1210   [(set_attr "insn" "umull")
1211    (set_attr "predicable" "yes")]
1212 )
1213
1214 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1215
1216 (define_insn "*umulsidi3adddi"
1217   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1218         (plus:DI
1219          (mult:DI
1220           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1221           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1222          (match_operand:DI 1 "s_register_operand" "0")))]
1223   "TARGET_ARM && arm_arch3m"
1224   "umlal%?\\t%Q0, %R0, %3, %2"
1225   [(set_attr "insn" "umlal")
1226    (set_attr "predicable" "yes")]
1227 )
1228
1229 (define_insn "smulsi3_highpart"
1230   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1231         (truncate:SI
1232          (lshiftrt:DI
1233           (mult:DI
1234            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1235            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1236           (const_int 32))))
1237    (clobber (match_scratch:SI 3 "=&r,&r"))]
1238   "TARGET_ARM && arm_arch3m"
1239   "smull%?\\t%3, %0, %2, %1"
1240   [(set_attr "insn" "smull")
1241    (set_attr "predicable" "yes")]
1242 )
1243
1244 (define_insn "umulsi3_highpart"
1245   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1246         (truncate:SI
1247          (lshiftrt:DI
1248           (mult:DI
1249            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1250            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1251           (const_int 32))))
1252    (clobber (match_scratch:SI 3 "=&r,&r"))]
1253   "TARGET_ARM && arm_arch3m"
1254   "umull%?\\t%3, %0, %2, %1"
1255   [(set_attr "insn" "umull")
1256    (set_attr "predicable" "yes")]
1257 )
1258
1259 (define_insn "mulhisi3"
1260   [(set (match_operand:SI 0 "s_register_operand" "=r")
1261         (mult:SI (sign_extend:SI
1262                   (match_operand:HI 1 "s_register_operand" "%r"))
1263                  (sign_extend:SI
1264                   (match_operand:HI 2 "s_register_operand" "r"))))]
1265   "TARGET_ARM && arm_arch5e"
1266   "smulbb%?\\t%0, %1, %2"
1267   [(set_attr "insn" "smulxy")
1268    (set_attr "predicable" "yes")]
1269 )
1270
1271 (define_insn "*mulhisi3tb"
1272   [(set (match_operand:SI 0 "s_register_operand" "=r")
1273         (mult:SI (ashiftrt:SI
1274                   (match_operand:SI 1 "s_register_operand" "r")
1275                   (const_int 16))
1276                  (sign_extend:SI
1277                   (match_operand:HI 2 "s_register_operand" "r"))))]
1278   "TARGET_ARM && arm_arch5e"
1279   "smultb%?\\t%0, %1, %2"
1280   [(set_attr "insn" "smulxy")
1281    (set_attr "predicable" "yes")]
1282 )
1283
1284 (define_insn "*mulhisi3bt"
1285   [(set (match_operand:SI 0 "s_register_operand" "=r")
1286         (mult:SI (sign_extend:SI
1287                   (match_operand:HI 1 "s_register_operand" "r"))
1288                  (ashiftrt:SI
1289                   (match_operand:SI 2 "s_register_operand" "r")
1290                   (const_int 16))))]
1291   "TARGET_ARM && arm_arch5e"
1292   "smulbt%?\\t%0, %1, %2"
1293   [(set_attr "insn" "smulxy")
1294    (set_attr "predicable" "yes")]
1295 )
1296
1297 (define_insn "*mulhisi3tt"
1298   [(set (match_operand:SI 0 "s_register_operand" "=r")
1299         (mult:SI (ashiftrt:SI
1300                   (match_operand:SI 1 "s_register_operand" "r")
1301                   (const_int 16))
1302                  (ashiftrt:SI
1303                   (match_operand:SI 2 "s_register_operand" "r")
1304                   (const_int 16))))]
1305   "TARGET_ARM && arm_arch5e"
1306   "smultt%?\\t%0, %1, %2"
1307   [(set_attr "insn" "smulxy")
1308    (set_attr "predicable" "yes")]
1309 )
1310
1311 (define_insn "*mulhisi3addsi"
1312   [(set (match_operand:SI 0 "s_register_operand" "=r")
1313         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1314                  (mult:SI (sign_extend:SI
1315                            (match_operand:HI 2 "s_register_operand" "%r"))
1316                           (sign_extend:SI
1317                            (match_operand:HI 3 "s_register_operand" "r")))))]
1318   "TARGET_ARM && arm_arch5e"
1319   "smlabb%?\\t%0, %2, %3, %1"
1320   [(set_attr "insn" "smlaxy")
1321    (set_attr "predicable" "yes")]
1322 )
1323
1324 (define_insn "*mulhidi3adddi"
1325   [(set (match_operand:DI 0 "s_register_operand" "=r")
1326         (plus:DI
1327           (match_operand:DI 1 "s_register_operand" "0")
1328           (mult:DI (sign_extend:DI
1329                     (match_operand:HI 2 "s_register_operand" "%r"))
1330                    (sign_extend:DI
1331                     (match_operand:HI 3 "s_register_operand" "r")))))]
1332   "TARGET_ARM && arm_arch5e"
1333   "smlalbb%?\\t%Q0, %R0, %2, %3"
1334   [(set_attr "insn" "smlalxy")
1335    (set_attr "predicable" "yes")])
1336
1337 (define_expand "mulsf3"
1338   [(set (match_operand:SF          0 "s_register_operand" "")
1339         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1340                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1341   "TARGET_ARM && TARGET_HARD_FLOAT"
1342   "
1343   if (TARGET_MAVERICK
1344       && !cirrus_fp_register (operands[2], SFmode))
1345     operands[2] = force_reg (SFmode, operands[2]);
1346 ")
1347
1348 (define_expand "muldf3"
1349   [(set (match_operand:DF          0 "s_register_operand" "")
1350         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1351                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1352   "TARGET_ARM && TARGET_HARD_FLOAT"
1353   "
1354   if (TARGET_MAVERICK
1355       && !cirrus_fp_register (operands[2], DFmode))
1356     operands[2] = force_reg (DFmode, operands[2]);
1357 ")
1358 \f
1359 ;; Division insns
1360
1361 (define_expand "divsf3"
1362   [(set (match_operand:SF 0 "s_register_operand" "")
1363         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1364                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1365   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1366   "")
1367
1368 (define_expand "divdf3"
1369   [(set (match_operand:DF 0 "s_register_operand" "")
1370         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1371                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1372   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1373   "")
1374 \f
1375 ;; Modulo insns
1376
1377 (define_expand "modsf3"
1378   [(set (match_operand:SF 0 "s_register_operand" "")
1379         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1380                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1381   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1382   "")
1383
1384 (define_expand "moddf3"
1385   [(set (match_operand:DF 0 "s_register_operand" "")
1386         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1387                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1388   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1389   "")
1390 \f
1391 ;; Boolean and,ior,xor insns
1392
1393 ;; Split up double word logical operations
1394
1395 ;; Split up simple DImode logical operations.  Simply perform the logical
1396 ;; operation on the upper and lower halves of the registers.
1397 (define_split
1398   [(set (match_operand:DI 0 "s_register_operand" "")
1399         (match_operator:DI 6 "logical_binary_operator"
1400           [(match_operand:DI 1 "s_register_operand" "")
1401            (match_operand:DI 2 "s_register_operand" "")]))]
1402   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1403   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1404    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1405   "
1406   {
1407     operands[3] = gen_highpart (SImode, operands[0]);
1408     operands[0] = gen_lowpart (SImode, operands[0]);
1409     operands[4] = gen_highpart (SImode, operands[1]);
1410     operands[1] = gen_lowpart (SImode, operands[1]);
1411     operands[5] = gen_highpart (SImode, operands[2]);
1412     operands[2] = gen_lowpart (SImode, operands[2]);
1413   }"
1414 )
1415
1416 (define_split
1417   [(set (match_operand:DI 0 "s_register_operand" "")
1418         (match_operator:DI 6 "logical_binary_operator"
1419           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1420            (match_operand:DI 1 "s_register_operand" "")]))]
1421   "TARGET_ARM && reload_completed"
1422   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1423    (set (match_dup 3) (match_op_dup:SI 6
1424                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1425                          (match_dup 4)]))]
1426   "
1427   {
1428     operands[3] = gen_highpart (SImode, operands[0]);
1429     operands[0] = gen_lowpart (SImode, operands[0]);
1430     operands[4] = gen_highpart (SImode, operands[1]);
1431     operands[1] = gen_lowpart (SImode, operands[1]);
1432     operands[5] = gen_highpart (SImode, operands[2]);
1433     operands[2] = gen_lowpart (SImode, operands[2]);
1434   }"
1435 )
1436
1437 ;; The zero extend of operand 2 means we can just copy the high part of
1438 ;; operand1 into operand0.
1439 (define_split
1440   [(set (match_operand:DI 0 "s_register_operand" "")
1441         (ior:DI
1442           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1443           (match_operand:DI 1 "s_register_operand" "")))]
1444   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1445   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1446    (set (match_dup 3) (match_dup 4))]
1447   "
1448   {
1449     operands[4] = gen_highpart (SImode, operands[1]);
1450     operands[3] = gen_highpart (SImode, operands[0]);
1451     operands[0] = gen_lowpart (SImode, operands[0]);
1452     operands[1] = gen_lowpart (SImode, operands[1]);
1453   }"
1454 )
1455
1456 ;; The zero extend of operand 2 means we can just copy the high part of
1457 ;; operand1 into operand0.
1458 (define_split
1459   [(set (match_operand:DI 0 "s_register_operand" "")
1460         (xor:DI
1461           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1462           (match_operand:DI 1 "s_register_operand" "")))]
1463   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1464   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1465    (set (match_dup 3) (match_dup 4))]
1466   "
1467   {
1468     operands[4] = gen_highpart (SImode, operands[1]);
1469     operands[3] = gen_highpart (SImode, operands[0]);
1470     operands[0] = gen_lowpart (SImode, operands[0]);
1471     operands[1] = gen_lowpart (SImode, operands[1]);
1472   }"
1473 )
1474
1475 (define_insn "anddi3"
1476   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1477         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1478                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1479   "TARGET_ARM && ! TARGET_IWMMXT"
1480   "#"
1481   [(set_attr "length" "8")]
1482 )
1483
1484 (define_insn_and_split "*anddi_zesidi_di"
1485   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1486         (and:DI (zero_extend:DI
1487                  (match_operand:SI 2 "s_register_operand" "r,r"))
1488                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1489   "TARGET_ARM"
1490   "#"
1491   "TARGET_ARM && reload_completed"
1492   ; The zero extend of operand 2 clears the high word of the output
1493   ; operand.
1494   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1495    (set (match_dup 3) (const_int 0))]
1496   "
1497   {
1498     operands[3] = gen_highpart (SImode, operands[0]);
1499     operands[0] = gen_lowpart (SImode, operands[0]);
1500     operands[1] = gen_lowpart (SImode, operands[1]);
1501   }"
1502   [(set_attr "length" "8")]
1503 )
1504
1505 (define_insn "*anddi_sesdi_di"
1506   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1507         (and:DI (sign_extend:DI
1508                  (match_operand:SI 2 "s_register_operand" "r,r"))
1509                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1510   "TARGET_ARM"
1511   "#"
1512   [(set_attr "length" "8")]
1513 )
1514
1515 (define_expand "andsi3"
1516   [(set (match_operand:SI         0 "s_register_operand" "")
1517         (and:SI (match_operand:SI 1 "s_register_operand" "")
1518                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1519   "TARGET_EITHER"
1520   "
1521   if (TARGET_ARM)
1522     {
1523       if (GET_CODE (operands[2]) == CONST_INT)
1524         {
1525           arm_split_constant (AND, SImode, NULL_RTX,
1526                               INTVAL (operands[2]), operands[0],
1527                               operands[1], optimize && !no_new_pseudos);
1528
1529           DONE;
1530         }
1531     }
1532   else /* TARGET_THUMB */
1533     {
1534       if (GET_CODE (operands[2]) != CONST_INT)
1535         operands[2] = force_reg (SImode, operands[2]);
1536       else
1537         {
1538           int i;
1539           
1540           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1541             {
1542               operands[2] = force_reg (SImode,
1543                                        GEN_INT (~INTVAL (operands[2])));
1544               
1545               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1546               
1547               DONE;
1548             }
1549
1550           for (i = 9; i <= 31; i++)
1551             {
1552               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1553                 {
1554                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1555                                         const0_rtx));
1556                   DONE;
1557                 }
1558               else if ((((HOST_WIDE_INT) 1) << i) - 1
1559                        == ~INTVAL (operands[2]))
1560                 {
1561                   rtx shift = GEN_INT (i);
1562                   rtx reg = gen_reg_rtx (SImode);
1563                 
1564                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1565                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1566                   
1567                   DONE;
1568                 }
1569             }
1570
1571           operands[2] = force_reg (SImode, operands[2]);
1572         }
1573     }
1574   "
1575 )
1576
1577 (define_insn_and_split "*arm_andsi3_insn"
1578   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1579         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1580                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1581   "TARGET_ARM"
1582   "@
1583    and%?\\t%0, %1, %2
1584    bic%?\\t%0, %1, #%B2
1585    #"
1586   "TARGET_ARM
1587    && GET_CODE (operands[2]) == CONST_INT
1588    && !(const_ok_for_arm (INTVAL (operands[2]))
1589         || const_ok_for_arm (~INTVAL (operands[2])))"
1590   [(clobber (const_int 0))]
1591   "
1592   arm_split_constant  (AND, SImode, curr_insn, 
1593                        INTVAL (operands[2]), operands[0], operands[1], 0);
1594   DONE;
1595   "
1596   [(set_attr "length" "4,4,16")
1597    (set_attr "predicable" "yes")]
1598 )
1599
1600 (define_insn "*thumb_andsi3_insn"
1601   [(set (match_operand:SI         0 "register_operand" "=l")
1602         (and:SI (match_operand:SI 1 "register_operand" "%0")
1603                 (match_operand:SI 2 "register_operand" "l")))]
1604   "TARGET_THUMB"
1605   "and\\t%0, %0, %2"
1606   [(set_attr "length" "2")]
1607 )
1608
1609 (define_insn "*andsi3_compare0"
1610   [(set (reg:CC_NOOV CC_REGNUM)
1611         (compare:CC_NOOV
1612          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1613                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1614          (const_int 0)))
1615    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1616         (and:SI (match_dup 1) (match_dup 2)))]
1617   "TARGET_ARM"
1618   "@
1619    and%?s\\t%0, %1, %2
1620    bic%?s\\t%0, %1, #%B2"
1621   [(set_attr "conds" "set")]
1622 )
1623
1624 (define_insn "*andsi3_compare0_scratch"
1625   [(set (reg:CC_NOOV CC_REGNUM)
1626         (compare:CC_NOOV
1627          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1628                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1629          (const_int 0)))
1630    (clobber (match_scratch:SI 2 "=X,r"))]
1631   "TARGET_ARM"
1632   "@
1633    tst%?\\t%0, %1
1634    bic%?s\\t%2, %0, #%B1"
1635   [(set_attr "conds" "set")]
1636 )
1637
1638 (define_insn "*zeroextractsi_compare0_scratch"
1639   [(set (reg:CC_NOOV CC_REGNUM)
1640         (compare:CC_NOOV (zero_extract:SI
1641                           (match_operand:SI 0 "s_register_operand" "r")
1642                           (match_operand 1 "const_int_operand" "n")
1643                           (match_operand 2 "const_int_operand" "n"))
1644                          (const_int 0)))]
1645   "TARGET_ARM
1646   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1647       && INTVAL (operands[1]) > 0 
1648       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1649       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1650   "*
1651   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1652                          << INTVAL (operands[2]));
1653   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1654   return \"\";
1655   "
1656   [(set_attr "conds" "set")]
1657 )
1658
1659 (define_insn_and_split "*ne_zeroextractsi"
1660   [(set (match_operand:SI 0 "s_register_operand" "=r")
1661         (ne:SI (zero_extract:SI
1662                 (match_operand:SI 1 "s_register_operand" "r")
1663                 (match_operand:SI 2 "const_int_operand" "n")
1664                 (match_operand:SI 3 "const_int_operand" "n"))
1665                (const_int 0)))
1666    (clobber (reg:CC CC_REGNUM))]
1667   "TARGET_ARM
1668    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1669        && INTVAL (operands[2]) > 0 
1670        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1671        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1672   "#"
1673   "TARGET_ARM
1674    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1675        && INTVAL (operands[2]) > 0 
1676        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1677        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1678   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1679                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1680                                     (const_int 0)))
1681               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1682    (set (match_dup 0)
1683         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1684                          (match_dup 0) (const_int 1)))]
1685   "
1686   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1687                          << INTVAL (operands[3])); 
1688   "
1689   [(set_attr "conds" "clob")
1690    (set_attr "length" "8")]
1691 )
1692
1693 (define_insn_and_split "*ne_zeroextractsi_shifted"
1694   [(set (match_operand:SI 0 "s_register_operand" "=r")
1695         (ne:SI (zero_extract:SI
1696                 (match_operand:SI 1 "s_register_operand" "r")
1697                 (match_operand:SI 2 "const_int_operand" "n")
1698                 (const_int 0))
1699                (const_int 0)))
1700    (clobber (reg:CC CC_REGNUM))]
1701   "TARGET_ARM"
1702   "#"
1703   "TARGET_ARM"
1704   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1705                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1706                                     (const_int 0)))
1707               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1708    (set (match_dup 0)
1709         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1710                          (match_dup 0) (const_int 1)))]
1711   "
1712   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1713   "
1714   [(set_attr "conds" "clob")
1715    (set_attr "length" "8")]
1716 )
1717
1718 (define_insn_and_split "*ite_ne_zeroextractsi"
1719   [(set (match_operand:SI 0 "s_register_operand" "=r")
1720         (if_then_else:SI (ne (zero_extract:SI
1721                               (match_operand:SI 1 "s_register_operand" "r")
1722                               (match_operand:SI 2 "const_int_operand" "n")
1723                               (match_operand:SI 3 "const_int_operand" "n"))
1724                              (const_int 0))
1725                          (match_operand:SI 4 "arm_not_operand" "rIK")
1726                          (const_int 0)))
1727    (clobber (reg:CC CC_REGNUM))]
1728   "TARGET_ARM
1729    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1730        && INTVAL (operands[2]) > 0 
1731        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1732        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1733    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1734   "#"
1735   "TARGET_ARM
1736    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1737        && INTVAL (operands[2]) > 0 
1738        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1739        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1740    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1741   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1742                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1743                                     (const_int 0)))
1744               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1745    (set (match_dup 0)
1746         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1747                          (match_dup 0) (match_dup 4)))]
1748   "
1749   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1750                          << INTVAL (operands[3])); 
1751   "
1752   [(set_attr "conds" "clob")
1753    (set_attr "length" "8")]
1754 )
1755
1756 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1757   [(set (match_operand:SI 0 "s_register_operand" "=r")
1758         (if_then_else:SI (ne (zero_extract:SI
1759                               (match_operand:SI 1 "s_register_operand" "r")
1760                               (match_operand:SI 2 "const_int_operand" "n")
1761                               (const_int 0))
1762                              (const_int 0))
1763                          (match_operand:SI 3 "arm_not_operand" "rIK")
1764                          (const_int 0)))
1765    (clobber (reg:CC CC_REGNUM))]
1766   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1767   "#"
1768   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1769   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1770                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1771                                     (const_int 0)))
1772               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1773    (set (match_dup 0)
1774         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1775                          (match_dup 0) (match_dup 3)))]
1776   "
1777   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1778   "
1779   [(set_attr "conds" "clob")
1780    (set_attr "length" "8")]
1781 )
1782
1783 (define_split
1784   [(set (match_operand:SI 0 "s_register_operand" "")
1785         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1786                          (match_operand:SI 2 "const_int_operand" "")
1787                          (match_operand:SI 3 "const_int_operand" "")))
1788    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1789   "TARGET_THUMB"
1790   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1791    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1792   "{
1793      HOST_WIDE_INT temp = INTVAL (operands[2]);
1794
1795      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1796      operands[3] = GEN_INT (32 - temp);
1797    }"
1798 )
1799
1800 (define_split
1801   [(set (match_operand:SI 0 "s_register_operand" "")
1802         (match_operator:SI 1 "shiftable_operator"
1803          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1804                            (match_operand:SI 3 "const_int_operand" "")
1805                            (match_operand:SI 4 "const_int_operand" ""))
1806           (match_operand:SI 5 "s_register_operand" "")]))
1807    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1808   "TARGET_ARM"
1809   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1810    (set (match_dup 0)
1811         (match_op_dup 1
1812          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1813           (match_dup 5)]))]
1814   "{
1815      HOST_WIDE_INT temp = INTVAL (operands[3]);
1816
1817      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1818      operands[4] = GEN_INT (32 - temp);
1819    }"
1820 )
1821   
1822 (define_split
1823   [(set (match_operand:SI 0 "s_register_operand" "")
1824         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1825                          (match_operand:SI 2 "const_int_operand" "")
1826                          (match_operand:SI 3 "const_int_operand" "")))]
1827   "TARGET_THUMB"
1828   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1829    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1830   "{
1831      HOST_WIDE_INT temp = INTVAL (operands[2]);
1832
1833      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1834      operands[3] = GEN_INT (32 - temp);
1835    }"
1836 )
1837
1838 (define_split
1839   [(set (match_operand:SI 0 "s_register_operand" "")
1840         (match_operator:SI 1 "shiftable_operator"
1841          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1842                            (match_operand:SI 3 "const_int_operand" "")
1843                            (match_operand:SI 4 "const_int_operand" ""))
1844           (match_operand:SI 5 "s_register_operand" "")]))
1845    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1846   "TARGET_ARM"
1847   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1848    (set (match_dup 0)
1849         (match_op_dup 1
1850          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1851           (match_dup 5)]))]
1852   "{
1853      HOST_WIDE_INT temp = INTVAL (operands[3]);
1854
1855      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1856      operands[4] = GEN_INT (32 - temp);
1857    }"
1858 )
1859   
1860 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1861 ;;; represented by the bitfield, then this will produce incorrect results.
1862 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1863 ;;; which have a real bit-field insert instruction, the truncation happens
1864 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1865 ;;; bit-field insert instruction, we would have to emit code here to truncate
1866 ;;; the value before we insert.  This loses some of the advantage of having
1867 ;;; this insv pattern, so this pattern needs to be reevalutated.
1868
1869 (define_expand "insv"
1870   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1871                          (match_operand:SI 1 "general_operand" "")
1872                          (match_operand:SI 2 "general_operand" ""))
1873         (match_operand:SI 3 "reg_or_int_operand" ""))]
1874   "TARGET_ARM"
1875   "
1876   {
1877     int start_bit = INTVAL (operands[2]);
1878     int width = INTVAL (operands[1]);
1879     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1880     rtx target, subtarget;
1881
1882     target = operands[0];
1883     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1884        subreg as the final target.  */
1885     if (GET_CODE (target) == SUBREG)
1886       {
1887         subtarget = gen_reg_rtx (SImode);
1888         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1889             < GET_MODE_SIZE (SImode))
1890           target = SUBREG_REG (target);
1891       }
1892     else
1893       subtarget = target;    
1894
1895     if (GET_CODE (operands[3]) == CONST_INT)
1896       {
1897         /* Since we are inserting a known constant, we may be able to
1898            reduce the number of bits that we have to clear so that
1899            the mask becomes simple.  */
1900         /* ??? This code does not check to see if the new mask is actually
1901            simpler.  It may not be.  */
1902         rtx op1 = gen_reg_rtx (SImode);
1903         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1904            start of this pattern.  */
1905         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1906         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1907
1908         emit_insn (gen_andsi3 (op1, operands[0],
1909                                gen_int_mode (~mask2, SImode)));
1910         emit_insn (gen_iorsi3 (subtarget, op1,
1911                                gen_int_mode (op3_value << start_bit, SImode)));
1912       }
1913     else if (start_bit == 0
1914              && !(const_ok_for_arm (mask)
1915                   || const_ok_for_arm (~mask)))
1916       {
1917         /* A Trick, since we are setting the bottom bits in the word,
1918            we can shift operand[3] up, operand[0] down, OR them together
1919            and rotate the result back again.  This takes 3 insns, and
1920            the third might be mergeable into another op.  */
1921         /* The shift up copes with the possibility that operand[3] is
1922            wider than the bitfield.  */
1923         rtx op0 = gen_reg_rtx (SImode);
1924         rtx op1 = gen_reg_rtx (SImode);
1925
1926         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1927         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1928         emit_insn (gen_iorsi3  (op1, op1, op0));
1929         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1930       }
1931     else if ((width + start_bit == 32)
1932              && !(const_ok_for_arm (mask)
1933                   || const_ok_for_arm (~mask)))
1934       {
1935         /* Similar trick, but slightly less efficient.  */
1936
1937         rtx op0 = gen_reg_rtx (SImode);
1938         rtx op1 = gen_reg_rtx (SImode);
1939
1940         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1941         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1942         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1943         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1944       }
1945     else
1946       {
1947         rtx op0 = gen_int_mode (mask, SImode);
1948         rtx op1 = gen_reg_rtx (SImode);
1949         rtx op2 = gen_reg_rtx (SImode);
1950
1951         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1952           {
1953             rtx tmp = gen_reg_rtx (SImode);
1954
1955             emit_insn (gen_movsi (tmp, op0));
1956             op0 = tmp;
1957           }
1958
1959         /* Mask out any bits in operand[3] that are not needed.  */
1960            emit_insn (gen_andsi3 (op1, operands[3], op0));
1961
1962         if (GET_CODE (op0) == CONST_INT
1963             && (const_ok_for_arm (mask << start_bit)
1964                 || const_ok_for_arm (~(mask << start_bit))))
1965           {
1966             op0 = gen_int_mode (~(mask << start_bit), SImode);
1967             emit_insn (gen_andsi3 (op2, operands[0], op0));
1968           }
1969         else
1970           {
1971             if (GET_CODE (op0) == CONST_INT)
1972               {
1973                 rtx tmp = gen_reg_rtx (SImode);
1974
1975                 emit_insn (gen_movsi (tmp, op0));
1976                 op0 = tmp;
1977               }
1978
1979             if (start_bit != 0)
1980               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1981             
1982             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1983           }
1984
1985         if (start_bit != 0)
1986           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1987
1988         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1989       }
1990
1991     if (subtarget != target)
1992       {
1993         /* If TARGET is still a SUBREG, then it must be wider than a word,
1994            so we must be careful only to set the subword we were asked to.  */
1995         if (GET_CODE (target) == SUBREG)
1996           emit_move_insn (target, subtarget);
1997         else
1998           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1999       }
2000
2001     DONE;
2002   }"
2003 )
2004
2005 ; constants for op 2 will never be given to these patterns.
2006 (define_insn_and_split "*anddi_notdi_di"
2007   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2008         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2009                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2010   "TARGET_ARM"
2011   "#"
2012   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2013   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2014    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2015   "
2016   {
2017     operands[3] = gen_highpart (SImode, operands[0]);
2018     operands[0] = gen_lowpart (SImode, operands[0]);
2019     operands[4] = gen_highpart (SImode, operands[1]);
2020     operands[1] = gen_lowpart (SImode, operands[1]);
2021     operands[5] = gen_highpart (SImode, operands[2]);
2022     operands[2] = gen_lowpart (SImode, operands[2]);
2023   }"
2024   [(set_attr "length" "8")
2025    (set_attr "predicable" "yes")]
2026 )
2027   
2028 (define_insn_and_split "*anddi_notzesidi_di"
2029   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2030         (and:DI (not:DI (zero_extend:DI
2031                          (match_operand:SI 2 "s_register_operand" "r,r")))
2032                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2033   "TARGET_ARM"
2034   "@
2035    bic%?\\t%Q0, %Q1, %2
2036    #"
2037   ; (not (zero_extend ...)) allows us to just copy the high word from
2038   ; operand1 to operand0.
2039   "TARGET_ARM
2040    && reload_completed
2041    && operands[0] != operands[1]"
2042   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2043    (set (match_dup 3) (match_dup 4))]
2044   "
2045   {
2046     operands[3] = gen_highpart (SImode, operands[0]);
2047     operands[0] = gen_lowpart (SImode, operands[0]);
2048     operands[4] = gen_highpart (SImode, operands[1]);
2049     operands[1] = gen_lowpart (SImode, operands[1]);
2050   }"
2051   [(set_attr "length" "4,8")
2052    (set_attr "predicable" "yes")]
2053 )
2054   
2055 (define_insn_and_split "*anddi_notsesidi_di"
2056   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2057         (and:DI (not:DI (sign_extend:DI
2058                          (match_operand:SI 2 "s_register_operand" "r,r")))
2059                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2060   "TARGET_ARM"
2061   "#"
2062   "TARGET_ARM && reload_completed"
2063   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2064    (set (match_dup 3) (and:SI (not:SI
2065                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2066                                (match_dup 4)))]
2067   "
2068   {
2069     operands[3] = gen_highpart (SImode, operands[0]);
2070     operands[0] = gen_lowpart (SImode, operands[0]);
2071     operands[4] = gen_highpart (SImode, operands[1]);
2072     operands[1] = gen_lowpart (SImode, operands[1]);
2073   }"
2074   [(set_attr "length" "8")
2075    (set_attr "predicable" "yes")]
2076 )
2077   
2078 (define_insn "andsi_notsi_si"
2079   [(set (match_operand:SI 0 "s_register_operand" "=r")
2080         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2081                 (match_operand:SI 1 "s_register_operand" "r")))]
2082   "TARGET_ARM"
2083   "bic%?\\t%0, %1, %2"
2084   [(set_attr "predicable" "yes")]
2085 )
2086
2087 (define_insn "bicsi3"
2088   [(set (match_operand:SI                 0 "register_operand" "=l")
2089         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2090                 (match_operand:SI         2 "register_operand" "0")))]
2091   "TARGET_THUMB"
2092   "bic\\t%0, %0, %1"
2093   [(set_attr "length" "2")]
2094 )
2095
2096 (define_insn "andsi_not_shiftsi_si"
2097   [(set (match_operand:SI 0 "s_register_operand" "=r")
2098         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2099                          [(match_operand:SI 2 "s_register_operand" "r")
2100                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2101                 (match_operand:SI 1 "s_register_operand" "r")))]
2102   "TARGET_ARM"
2103   "bic%?\\t%0, %1, %2%S4"
2104   [(set_attr "predicable" "yes")
2105    (set_attr "shift" "2")
2106    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2107                       (const_string "alu_shift")
2108                       (const_string "alu_shift_reg")))]
2109 )
2110
2111 (define_insn "*andsi_notsi_si_compare0"
2112   [(set (reg:CC_NOOV CC_REGNUM)
2113         (compare:CC_NOOV
2114          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2115                  (match_operand:SI 1 "s_register_operand" "r"))
2116          (const_int 0)))
2117    (set (match_operand:SI 0 "s_register_operand" "=r")
2118         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2119   "TARGET_ARM"
2120   "bic%?s\\t%0, %1, %2"
2121   [(set_attr "conds" "set")]
2122 )
2123
2124 (define_insn "*andsi_notsi_si_compare0_scratch"
2125   [(set (reg:CC_NOOV CC_REGNUM)
2126         (compare:CC_NOOV
2127          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2128                  (match_operand:SI 1 "s_register_operand" "r"))
2129          (const_int 0)))
2130    (clobber (match_scratch:SI 0 "=r"))]
2131   "TARGET_ARM"
2132   "bic%?s\\t%0, %1, %2"
2133   [(set_attr "conds" "set")]
2134 )
2135
2136 (define_insn "iordi3"
2137   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2138         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2139                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2140   "TARGET_ARM && ! TARGET_IWMMXT"
2141   "#"
2142   [(set_attr "length" "8")
2143    (set_attr "predicable" "yes")]
2144 )
2145
2146 (define_insn "*iordi_zesidi_di"
2147   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2148         (ior:DI (zero_extend:DI
2149                  (match_operand:SI 2 "s_register_operand" "r,r"))
2150                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2151   "TARGET_ARM"
2152   "@
2153    orr%?\\t%Q0, %Q1, %2
2154    #"
2155   [(set_attr "length" "4,8")
2156    (set_attr "predicable" "yes")]
2157 )
2158
2159 (define_insn "*iordi_sesidi_di"
2160   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2161         (ior:DI (sign_extend:DI
2162                  (match_operand:SI 2 "s_register_operand" "r,r"))
2163                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2164   "TARGET_ARM"
2165   "#"
2166   [(set_attr "length" "8")
2167    (set_attr "predicable" "yes")]
2168 )
2169
2170 (define_expand "iorsi3"
2171   [(set (match_operand:SI         0 "s_register_operand" "")
2172         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2173                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2174   "TARGET_EITHER"
2175   "
2176   if (GET_CODE (operands[2]) == CONST_INT)
2177     {
2178       if (TARGET_ARM)
2179         {
2180           arm_split_constant (IOR, SImode, NULL_RTX,
2181                               INTVAL (operands[2]), operands[0], operands[1],
2182                               optimize && !no_new_pseudos);
2183           DONE;
2184         }
2185       else /* TARGET_THUMB */
2186         operands [2] = force_reg (SImode, operands [2]);
2187     }
2188   "
2189 )
2190
2191 (define_insn_and_split "*arm_iorsi3"
2192   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2193         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2194                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2195   "TARGET_ARM"
2196   "@
2197    orr%?\\t%0, %1, %2
2198    #"
2199   "TARGET_ARM
2200    && GET_CODE (operands[2]) == CONST_INT
2201    && !const_ok_for_arm (INTVAL (operands[2]))"
2202   [(clobber (const_int 0))]
2203   "
2204   arm_split_constant (IOR, SImode, curr_insn, 
2205                       INTVAL (operands[2]), operands[0], operands[1], 0);
2206   DONE;
2207   "
2208   [(set_attr "length" "4,16")
2209    (set_attr "predicable" "yes")]
2210 )
2211
2212 (define_insn "*thumb_iorsi3"
2213   [(set (match_operand:SI         0 "register_operand" "=l")
2214         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2215                 (match_operand:SI 2 "register_operand" "l")))]
2216   "TARGET_THUMB"
2217   "orr\\t%0, %0, %2"
2218   [(set_attr "length" "2")]
2219 )
2220
2221 (define_peephole2
2222   [(match_scratch:SI 3 "r")
2223    (set (match_operand:SI 0 "arm_general_register_operand" "")
2224         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2225                 (match_operand:SI 2 "const_int_operand" "")))]
2226   "TARGET_ARM
2227    && !const_ok_for_arm (INTVAL (operands[2]))
2228    && const_ok_for_arm (~INTVAL (operands[2]))"
2229   [(set (match_dup 3) (match_dup 2))
2230    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2231   ""
2232 )
2233
2234 (define_insn "*iorsi3_compare0"
2235   [(set (reg:CC_NOOV CC_REGNUM)
2236         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2237                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2238                          (const_int 0)))
2239    (set (match_operand:SI 0 "s_register_operand" "=r")
2240         (ior:SI (match_dup 1) (match_dup 2)))]
2241   "TARGET_ARM"
2242   "orr%?s\\t%0, %1, %2"
2243   [(set_attr "conds" "set")]
2244 )
2245
2246 (define_insn "*iorsi3_compare0_scratch"
2247   [(set (reg:CC_NOOV CC_REGNUM)
2248         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2249                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2250                          (const_int 0)))
2251    (clobber (match_scratch:SI 0 "=r"))]
2252   "TARGET_ARM"
2253   "orr%?s\\t%0, %1, %2"
2254   [(set_attr "conds" "set")]
2255 )
2256
2257 (define_insn "xordi3"
2258   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2259         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2260                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2261   "TARGET_ARM && !TARGET_IWMMXT"
2262   "#"
2263   [(set_attr "length" "8")
2264    (set_attr "predicable" "yes")]
2265 )
2266
2267 (define_insn "*xordi_zesidi_di"
2268   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2269         (xor:DI (zero_extend:DI
2270                  (match_operand:SI 2 "s_register_operand" "r,r"))
2271                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2272   "TARGET_ARM"
2273   "@
2274    eor%?\\t%Q0, %Q1, %2
2275    #"
2276   [(set_attr "length" "4,8")
2277    (set_attr "predicable" "yes")]
2278 )
2279
2280 (define_insn "*xordi_sesidi_di"
2281   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2282         (xor:DI (sign_extend:DI
2283                  (match_operand:SI 2 "s_register_operand" "r,r"))
2284                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2285   "TARGET_ARM"
2286   "#"
2287   [(set_attr "length" "8")
2288    (set_attr "predicable" "yes")]
2289 )
2290
2291 (define_expand "xorsi3"
2292   [(set (match_operand:SI         0 "s_register_operand" "")
2293         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2294                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2295   "TARGET_EITHER"
2296   "if (TARGET_THUMB)
2297      if (GET_CODE (operands[2]) == CONST_INT)
2298        operands[2] = force_reg (SImode, operands[2]);
2299   "
2300 )
2301
2302 (define_insn "*arm_xorsi3"
2303   [(set (match_operand:SI         0 "s_register_operand" "=r")
2304         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2305                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2306   "TARGET_ARM"
2307   "eor%?\\t%0, %1, %2"
2308   [(set_attr "predicable" "yes")]
2309 )
2310
2311 (define_insn "*thumb_xorsi3"
2312   [(set (match_operand:SI         0 "register_operand" "=l")
2313         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2314                 (match_operand:SI 2 "register_operand" "l")))]
2315   "TARGET_THUMB"
2316   "eor\\t%0, %0, %2"
2317   [(set_attr "length" "2")]
2318 )
2319
2320 (define_insn "*xorsi3_compare0"
2321   [(set (reg:CC_NOOV CC_REGNUM)
2322         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2323                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2324                          (const_int 0)))
2325    (set (match_operand:SI 0 "s_register_operand" "=r")
2326         (xor:SI (match_dup 1) (match_dup 2)))]
2327   "TARGET_ARM"
2328   "eor%?s\\t%0, %1, %2"
2329   [(set_attr "conds" "set")]
2330 )
2331
2332 (define_insn "*xorsi3_compare0_scratch"
2333   [(set (reg:CC_NOOV CC_REGNUM)
2334         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2335                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2336                          (const_int 0)))]
2337   "TARGET_ARM"
2338   "teq%?\\t%0, %1"
2339   [(set_attr "conds" "set")]
2340 )
2341
2342 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2343 ; (NOT D) we can sometimes merge the final NOT into one of the following
2344 ; insns.
2345
2346 (define_split
2347   [(set (match_operand:SI 0 "s_register_operand" "")
2348         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2349                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2350                 (match_operand:SI 3 "arm_rhs_operand" "")))
2351    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2352   "TARGET_ARM"
2353   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2354                               (not:SI (match_dup 3))))
2355    (set (match_dup 0) (not:SI (match_dup 4)))]
2356   ""
2357 )
2358
2359 (define_insn "*andsi_iorsi3_notsi"
2360   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2361         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2362                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2363                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2364   "TARGET_ARM"
2365   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2366   [(set_attr "length" "8")
2367    (set_attr "predicable" "yes")]
2368 )
2369
2370 (define_split
2371   [(set (match_operand:SI 0 "s_register_operand" "")
2372         (match_operator:SI 1 "logical_binary_operator"
2373          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2374                            (match_operand:SI 3 "const_int_operand" "")
2375                            (match_operand:SI 4 "const_int_operand" ""))
2376           (match_operator:SI 9 "logical_binary_operator"
2377            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2378                          (match_operand:SI 6 "const_int_operand" ""))
2379             (match_operand:SI 7 "s_register_operand" "")])]))
2380    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2381   "TARGET_ARM
2382    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2383    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2384   [(set (match_dup 8)
2385         (match_op_dup 1
2386          [(ashift:SI (match_dup 2) (match_dup 4))
2387           (match_dup 5)]))
2388    (set (match_dup 0)
2389         (match_op_dup 1
2390          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2391           (match_dup 7)]))]
2392   "
2393   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2394 ")
2395
2396 (define_split
2397   [(set (match_operand:SI 0 "s_register_operand" "")
2398         (match_operator:SI 1 "logical_binary_operator"
2399          [(match_operator:SI 9 "logical_binary_operator"
2400            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2401                          (match_operand:SI 6 "const_int_operand" ""))
2402             (match_operand:SI 7 "s_register_operand" "")])
2403           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2404                            (match_operand:SI 3 "const_int_operand" "")
2405                            (match_operand:SI 4 "const_int_operand" ""))]))
2406    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2407   "TARGET_ARM
2408    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2409    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2410   [(set (match_dup 8)
2411         (match_op_dup 1
2412          [(ashift:SI (match_dup 2) (match_dup 4))
2413           (match_dup 5)]))
2414    (set (match_dup 0)
2415         (match_op_dup 1
2416          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2417           (match_dup 7)]))]
2418   "
2419   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2420 ")
2421
2422 (define_split
2423   [(set (match_operand:SI 0 "s_register_operand" "")
2424         (match_operator:SI 1 "logical_binary_operator"
2425          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2426                            (match_operand:SI 3 "const_int_operand" "")
2427                            (match_operand:SI 4 "const_int_operand" ""))
2428           (match_operator:SI 9 "logical_binary_operator"
2429            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2430                          (match_operand:SI 6 "const_int_operand" ""))
2431             (match_operand:SI 7 "s_register_operand" "")])]))
2432    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2433   "TARGET_ARM
2434    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2435    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2436   [(set (match_dup 8)
2437         (match_op_dup 1
2438          [(ashift:SI (match_dup 2) (match_dup 4))
2439           (match_dup 5)]))
2440    (set (match_dup 0)
2441         (match_op_dup 1
2442          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2443           (match_dup 7)]))]
2444   "
2445   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2446 ")
2447
2448 (define_split
2449   [(set (match_operand:SI 0 "s_register_operand" "")
2450         (match_operator:SI 1 "logical_binary_operator"
2451          [(match_operator:SI 9 "logical_binary_operator"
2452            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2453                          (match_operand:SI 6 "const_int_operand" ""))
2454             (match_operand:SI 7 "s_register_operand" "")])
2455           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2456                            (match_operand:SI 3 "const_int_operand" "")
2457                            (match_operand:SI 4 "const_int_operand" ""))]))
2458    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2459   "TARGET_ARM
2460    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2461    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2462   [(set (match_dup 8)
2463         (match_op_dup 1
2464          [(ashift:SI (match_dup 2) (match_dup 4))
2465           (match_dup 5)]))
2466    (set (match_dup 0)
2467         (match_op_dup 1
2468          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2469           (match_dup 7)]))]
2470   "
2471   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2472 ")
2473 \f
2474
2475 ;; Minimum and maximum insns
2476
2477 (define_expand "smaxsi3"
2478   [(parallel [
2479     (set (match_operand:SI 0 "s_register_operand" "")
2480          (smax:SI (match_operand:SI 1 "s_register_operand" "")
2481                   (match_operand:SI 2 "arm_rhs_operand" "")))
2482     (clobber (reg:CC CC_REGNUM))])]
2483   "TARGET_ARM"
2484   "
2485   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2486     {
2487       /* No need for a clobber of the condition code register here.  */
2488       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2489                               gen_rtx_SMAX (SImode, operands[1],
2490                                             operands[2])));
2491       DONE;
2492     }
2493 ")
2494
2495 (define_insn "*smax_0"
2496   [(set (match_operand:SI 0 "s_register_operand" "=r")
2497         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2498                  (const_int 0)))]
2499   "TARGET_ARM"
2500   "bic%?\\t%0, %1, %1, asr #31"
2501   [(set_attr "predicable" "yes")]
2502 )
2503
2504 (define_insn "*smax_m1"
2505   [(set (match_operand:SI 0 "s_register_operand" "=r")
2506         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2507                  (const_int -1)))]
2508   "TARGET_ARM"
2509   "orr%?\\t%0, %1, %1, asr #31"
2510   [(set_attr "predicable" "yes")]
2511 )
2512
2513 (define_insn "*smax_insn"
2514   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
2515         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
2516                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
2517    (clobber (reg:CC CC_REGNUM))]
2518   "TARGET_ARM"
2519   "@
2520    cmp\\t%1, %2\;movlt\\t%0, %2
2521    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2522   [(set_attr "conds" "clob")
2523    (set_attr "length" "8,12")]
2524 )
2525
2526 (define_expand "sminsi3"
2527   [(parallel [
2528     (set (match_operand:SI 0 "s_register_operand" "")
2529          (smin:SI (match_operand:SI 1 "s_register_operand" "")
2530                   (match_operand:SI 2 "arm_rhs_operand" "")))
2531     (clobber (reg:CC CC_REGNUM))])]
2532   "TARGET_ARM"
2533   "
2534   if (operands[2] == const0_rtx)
2535     {
2536       /* No need for a clobber of the condition code register here.  */
2537       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2538                               gen_rtx_SMIN (SImode, operands[1],
2539                                             operands[2])));
2540       DONE;
2541     }
2542 ")
2543
2544 (define_insn "*smin_0"
2545   [(set (match_operand:SI 0 "s_register_operand" "=r")
2546         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2547                  (const_int 0)))]
2548   "TARGET_ARM"
2549   "and%?\\t%0, %1, %1, asr #31"
2550   [(set_attr "predicable" "yes")]
2551 )
2552
2553 (define_insn "*smin_insn"
2554   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2555         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2556                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2557    (clobber (reg:CC CC_REGNUM))]
2558   "TARGET_ARM"
2559   "@
2560    cmp\\t%1, %2\;movge\\t%0, %2
2561    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2562   [(set_attr "conds" "clob")
2563    (set_attr "length" "8,12")]
2564 )
2565
2566 (define_insn "umaxsi3"
2567   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2568         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2569                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2570    (clobber (reg:CC CC_REGNUM))]
2571   "TARGET_ARM"
2572   "@
2573    cmp\\t%1, %2\;movcc\\t%0, %2
2574    cmp\\t%1, %2\;movcs\\t%0, %1
2575    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2576   [(set_attr "conds" "clob")
2577    (set_attr "length" "8,8,12")]
2578 )
2579
2580 (define_insn "uminsi3"
2581   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2582         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2583                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2584    (clobber (reg:CC CC_REGNUM))]
2585   "TARGET_ARM"
2586   "@
2587    cmp\\t%1, %2\;movcs\\t%0, %2
2588    cmp\\t%1, %2\;movcc\\t%0, %1
2589    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2590   [(set_attr "conds" "clob")
2591    (set_attr "length" "8,8,12")]
2592 )
2593
2594 (define_insn "*store_minmaxsi"
2595   [(set (match_operand:SI 0 "memory_operand" "=m")
2596         (match_operator:SI 3 "minmax_operator"
2597          [(match_operand:SI 1 "s_register_operand" "r")
2598           (match_operand:SI 2 "s_register_operand" "r")]))
2599    (clobber (reg:CC CC_REGNUM))]
2600   "TARGET_ARM"
2601   "*
2602   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2603                                 operands[1], operands[2]);
2604   output_asm_insn (\"cmp\\t%1, %2\", operands);
2605   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2606   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2607   return \"\";
2608   "
2609   [(set_attr "conds" "clob")
2610    (set_attr "length" "12")
2611    (set_attr "type" "store1")]
2612 )
2613
2614 ; Reject the frame pointer in operand[1], since reloading this after
2615 ; it has been eliminated can cause carnage.
2616 (define_insn "*minmax_arithsi"
2617   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2618         (match_operator:SI 4 "shiftable_operator"
2619          [(match_operator:SI 5 "minmax_operator"
2620            [(match_operand:SI 2 "s_register_operand" "r,r")
2621             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2622           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2623    (clobber (reg:CC CC_REGNUM))]
2624   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2625   "*
2626   {
2627     enum rtx_code code = GET_CODE (operands[4]);
2628
2629     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2630                                   operands[2], operands[3]);
2631     output_asm_insn (\"cmp\\t%2, %3\", operands);
2632     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2633     if (which_alternative != 0 || operands[3] != const0_rtx
2634         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2635       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2636     return \"\";
2637   }"
2638   [(set_attr "conds" "clob")
2639    (set_attr "length" "12")]
2640 )
2641
2642 \f
2643 ;; Shift and rotation insns
2644
2645 (define_expand "ashldi3"
2646   [(set (match_operand:DI            0 "s_register_operand" "")
2647         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2648                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2649   "TARGET_ARM"
2650   "
2651   if (GET_CODE (operands[2]) == CONST_INT)
2652     {
2653       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2654         {
2655           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2656           DONE;
2657         }
2658         /* Ideally we shouldn't fail here if we could know that operands[1] 
2659            ends up already living in an iwmmxt register. Otherwise it's
2660            cheaper to have the alternate code being generated than moving
2661            values to iwmmxt regs and back.  */
2662         FAIL;
2663     }
2664   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2665     FAIL;
2666   "
2667 )
2668
2669 (define_insn "arm_ashldi3_1bit"
2670   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2671         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2672                    (const_int 1)))
2673    (clobber (reg:CC CC_REGNUM))]
2674   "TARGET_ARM"
2675   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2676   [(set_attr "conds" "clob")
2677    (set_attr "length" "8")]
2678 )
2679
2680 (define_expand "ashlsi3"
2681   [(set (match_operand:SI            0 "s_register_operand" "")
2682         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2683                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2684   "TARGET_EITHER"
2685   "
2686   if (GET_CODE (operands[2]) == CONST_INT
2687       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2688     {
2689       emit_insn (gen_movsi (operands[0], const0_rtx));
2690       DONE;
2691     }
2692   "
2693 )
2694
2695 (define_insn "*thumb_ashlsi3"
2696   [(set (match_operand:SI            0 "register_operand" "=l,l")
2697         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2698                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2699   "TARGET_THUMB"
2700   "lsl\\t%0, %1, %2"
2701   [(set_attr "length" "2")]
2702 )
2703
2704 (define_expand "ashrdi3"
2705   [(set (match_operand:DI              0 "s_register_operand" "")
2706         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2707                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2708   "TARGET_ARM"
2709   "
2710   if (GET_CODE (operands[2]) == CONST_INT)
2711     {
2712       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2713         {
2714           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2715           DONE;
2716         }
2717         /* Ideally we shouldn't fail here if we could know that operands[1] 
2718            ends up already living in an iwmmxt register. Otherwise it's
2719            cheaper to have the alternate code being generated than moving
2720            values to iwmmxt regs and back.  */
2721         FAIL;
2722     }
2723   else if (!TARGET_REALLY_IWMMXT)
2724     FAIL;
2725   "
2726 )
2727
2728 (define_insn "arm_ashrdi3_1bit"
2729   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2730         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2731                      (const_int 1)))
2732    (clobber (reg:CC CC_REGNUM))]
2733   "TARGET_ARM"
2734   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2735   [(set_attr "conds" "clob")
2736    (set_attr "length" "8")]
2737 )
2738
2739 (define_expand "ashrsi3"
2740   [(set (match_operand:SI              0 "s_register_operand" "")
2741         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2742                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2743   "TARGET_EITHER"
2744   "
2745   if (GET_CODE (operands[2]) == CONST_INT
2746       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2747     operands[2] = GEN_INT (31);
2748   "
2749 )
2750
2751 (define_insn "*thumb_ashrsi3"
2752   [(set (match_operand:SI              0 "register_operand" "=l,l")
2753         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2754                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2755   "TARGET_THUMB"
2756   "asr\\t%0, %1, %2"
2757   [(set_attr "length" "2")]
2758 )
2759
2760 (define_expand "lshrdi3"
2761   [(set (match_operand:DI              0 "s_register_operand" "")
2762         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2763                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2764   "TARGET_ARM"
2765   "
2766   if (GET_CODE (operands[2]) == CONST_INT)
2767     {
2768       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2769         {
2770           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2771           DONE;
2772         }
2773         /* Ideally we shouldn't fail here if we could know that operands[1] 
2774            ends up already living in an iwmmxt register. Otherwise it's
2775            cheaper to have the alternate code being generated than moving
2776            values to iwmmxt regs and back.  */
2777         FAIL;
2778     }
2779   else if (!TARGET_REALLY_IWMMXT)
2780     FAIL;
2781   "
2782 )
2783
2784 (define_insn "arm_lshrdi3_1bit"
2785   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2786         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2787                      (const_int 1)))
2788    (clobber (reg:CC CC_REGNUM))]
2789   "TARGET_ARM"
2790   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2791   [(set_attr "conds" "clob")
2792    (set_attr "length" "8")]
2793 )
2794
2795 (define_expand "lshrsi3"
2796   [(set (match_operand:SI              0 "s_register_operand" "")
2797         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2798                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2799   "TARGET_EITHER"
2800   "
2801   if (GET_CODE (operands[2]) == CONST_INT
2802       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2803     {
2804       emit_insn (gen_movsi (operands[0], const0_rtx));
2805       DONE;
2806     }
2807   "
2808 )
2809
2810 (define_insn "*thumb_lshrsi3"
2811   [(set (match_operand:SI              0 "register_operand" "=l,l")
2812         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2813                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2814   "TARGET_THUMB"
2815   "lsr\\t%0, %1, %2"
2816   [(set_attr "length" "2")]
2817 )
2818
2819 (define_expand "rotlsi3"
2820   [(set (match_operand:SI              0 "s_register_operand" "")
2821         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2822                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2823   "TARGET_ARM"
2824   "
2825   if (GET_CODE (operands[2]) == CONST_INT)
2826     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2827   else
2828     {
2829       rtx reg = gen_reg_rtx (SImode);
2830       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2831       operands[2] = reg;
2832     }
2833   "
2834 )
2835
2836 (define_expand "rotrsi3"
2837   [(set (match_operand:SI              0 "s_register_operand" "")
2838         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2839                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2840   "TARGET_EITHER"
2841   "
2842   if (TARGET_ARM)
2843     {
2844       if (GET_CODE (operands[2]) == CONST_INT
2845           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2846         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2847     }
2848   else /* TARGET_THUMB */
2849     {
2850       if (GET_CODE (operands [2]) == CONST_INT)
2851         operands [2] = force_reg (SImode, operands[2]);
2852     }
2853   "
2854 )
2855
2856 (define_insn "*thumb_rotrsi3"
2857   [(set (match_operand:SI              0 "register_operand" "=l")
2858         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2859                      (match_operand:SI 2 "register_operand" "l")))]
2860   "TARGET_THUMB"
2861   "ror\\t%0, %0, %2"
2862   [(set_attr "length" "2")]
2863 )
2864
2865 (define_insn "*arm_shiftsi3"
2866   [(set (match_operand:SI   0 "s_register_operand" "=r")
2867         (match_operator:SI  3 "shift_operator"
2868          [(match_operand:SI 1 "s_register_operand"  "r")
2869           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2870   "TARGET_ARM"
2871   "mov%?\\t%0, %1%S3"
2872   [(set_attr "predicable" "yes")
2873    (set_attr "shift" "1")
2874    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2875                       (const_string "alu_shift")
2876                       (const_string "alu_shift_reg")))]
2877 )
2878
2879 (define_insn "*shiftsi3_compare0"
2880   [(set (reg:CC_NOOV CC_REGNUM)
2881         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2882                           [(match_operand:SI 1 "s_register_operand" "r")
2883                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2884                          (const_int 0)))
2885    (set (match_operand:SI 0 "s_register_operand" "=r")
2886         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2887   "TARGET_ARM"
2888   "mov%?s\\t%0, %1%S3"
2889   [(set_attr "conds" "set")
2890    (set_attr "shift" "1")
2891    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2892                       (const_string "alu_shift")
2893                       (const_string "alu_shift_reg")))]
2894 )
2895
2896 (define_insn "*shiftsi3_compare0_scratch"
2897   [(set (reg:CC_NOOV CC_REGNUM)
2898         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2899                           [(match_operand:SI 1 "s_register_operand" "r")
2900                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2901                          (const_int 0)))
2902    (clobber (match_scratch:SI 0 "=r"))]
2903   "TARGET_ARM"
2904   "mov%?s\\t%0, %1%S3"
2905   [(set_attr "conds" "set")
2906    (set_attr "shift" "1")]
2907 )
2908
2909 (define_insn "*notsi_shiftsi"
2910   [(set (match_operand:SI 0 "s_register_operand" "=r")
2911         (not:SI (match_operator:SI 3 "shift_operator"
2912                  [(match_operand:SI 1 "s_register_operand" "r")
2913                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2914   "TARGET_ARM"
2915   "mvn%?\\t%0, %1%S3"
2916   [(set_attr "predicable" "yes")
2917    (set_attr "shift" "1")
2918    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2919                       (const_string "alu_shift")
2920                       (const_string "alu_shift_reg")))]
2921 )
2922
2923 (define_insn "*notsi_shiftsi_compare0"
2924   [(set (reg:CC_NOOV CC_REGNUM)
2925         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2926                           [(match_operand:SI 1 "s_register_operand" "r")
2927                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2928                          (const_int 0)))
2929    (set (match_operand:SI 0 "s_register_operand" "=r")
2930         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2931   "TARGET_ARM"
2932   "mvn%?s\\t%0, %1%S3"
2933   [(set_attr "conds" "set")
2934    (set_attr "shift" "1")
2935    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2936                       (const_string "alu_shift")
2937                       (const_string "alu_shift_reg")))]
2938 )
2939
2940 (define_insn "*not_shiftsi_compare0_scratch"
2941   [(set (reg:CC_NOOV CC_REGNUM)
2942         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2943                           [(match_operand:SI 1 "s_register_operand" "r")
2944                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2945                          (const_int 0)))
2946    (clobber (match_scratch:SI 0 "=r"))]
2947   "TARGET_ARM"
2948   "mvn%?s\\t%0, %1%S3"
2949   [(set_attr "conds" "set")
2950    (set_attr "shift" "1")
2951    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2952                       (const_string "alu_shift")
2953                       (const_string "alu_shift_reg")))]
2954 )
2955
2956 ;; We don't really have extzv, but defining this using shifts helps
2957 ;; to reduce register pressure later on.
2958
2959 (define_expand "extzv"
2960   [(set (match_dup 4)
2961         (ashift:SI (match_operand:SI   1 "register_operand" "")
2962                    (match_operand:SI   2 "const_int_operand" "")))
2963    (set (match_operand:SI              0 "register_operand" "")
2964         (lshiftrt:SI (match_dup 4)
2965                      (match_operand:SI 3 "const_int_operand" "")))]
2966   "TARGET_THUMB"
2967   "
2968   {
2969     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2970     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2971     
2972     operands[3] = GEN_INT (rshift);
2973     
2974     if (lshift == 0)
2975       {
2976         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2977         DONE;
2978       }
2979       
2980     operands[2] = GEN_INT (lshift);
2981     operands[4] = gen_reg_rtx (SImode);
2982   }"
2983 )
2984
2985 \f
2986 ;; Unary arithmetic insns
2987
2988 (define_expand "negdi2"
2989  [(parallel
2990    [(set (match_operand:DI          0 "s_register_operand" "")
2991           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2992     (clobber (reg:CC CC_REGNUM))])]
2993   "TARGET_EITHER"
2994   "
2995   if (TARGET_THUMB)
2996     {
2997       if (GET_CODE (operands[1]) != REG)
2998         operands[1] = force_reg (SImode, operands[1]);
2999      }
3000   "
3001 )
3002
3003 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3004 ;; The second alternative is to allow the common case of a *full* overlap.
3005 (define_insn "*arm_negdi2"
3006   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3007         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
3008    (clobber (reg:CC CC_REGNUM))]
3009   "TARGET_ARM"
3010   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3011   [(set_attr "conds" "clob")
3012    (set_attr "length" "8")]
3013 )
3014
3015 (define_insn "*thumb_negdi2"
3016   [(set (match_operand:DI         0 "register_operand" "=&l")
3017         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
3018    (clobber (reg:CC CC_REGNUM))]
3019   "TARGET_THUMB"
3020   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3021   [(set_attr "length" "6")]
3022 )
3023
3024 (define_expand "negsi2"
3025   [(set (match_operand:SI         0 "s_register_operand" "")
3026         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3027   "TARGET_EITHER"
3028   ""
3029 )
3030
3031 (define_insn "*arm_negsi2"
3032   [(set (match_operand:SI         0 "s_register_operand" "=r")
3033         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3034   "TARGET_ARM"
3035   "rsb%?\\t%0, %1, #0"
3036   [(set_attr "predicable" "yes")]
3037 )
3038
3039 (define_insn "*thumb_negsi2"
3040   [(set (match_operand:SI         0 "register_operand" "=l")
3041         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3042   "TARGET_THUMB"
3043   "neg\\t%0, %1"
3044   [(set_attr "length" "2")]
3045 )
3046
3047 (define_expand "negsf2"
3048   [(set (match_operand:SF         0 "s_register_operand" "")
3049         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3050   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3051   ""
3052 )
3053
3054 (define_expand "negdf2"
3055   [(set (match_operand:DF         0 "s_register_operand" "")
3056         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3057   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3058   "")
3059
3060 ;; abssi2 doesn't really clobber the condition codes if a different register
3061 ;; is being set.  To keep things simple, assume during rtl manipulations that
3062 ;; it does, but tell the final scan operator the truth.  Similarly for
3063 ;; (neg (abs...))
3064
3065 (define_expand "abssi2"
3066   [(parallel
3067     [(set (match_operand:SI         0 "s_register_operand" "")
3068           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3069      (clobber (match_dup 2))])]
3070   "TARGET_EITHER"
3071   "
3072   if (TARGET_THUMB)
3073     operands[2] = gen_rtx_SCRATCH (SImode);
3074   else
3075     operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3076 ")
3077
3078 (define_insn "*arm_abssi2"
3079   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3080         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3081    (clobber (reg:CC CC_REGNUM))]
3082   "TARGET_ARM"
3083   "@
3084    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3085    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3086   [(set_attr "conds" "clob,*")
3087    (set_attr "shift" "1")
3088    ;; predicable can't be set based on the variant, so left as no
3089    (set_attr "length" "8")]
3090 )
3091
3092 (define_insn_and_split "*thumb_abssi2"
3093   [(set (match_operand:SI 0 "s_register_operand" "=l")
3094         (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3095    (clobber (match_scratch:SI 2 "=&l"))]
3096   "TARGET_THUMB"
3097   "#"
3098   "TARGET_THUMB && reload_completed"
3099   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3100    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3101    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3102   ""
3103   [(set_attr "length" "6")]
3104 )
3105
3106 (define_insn "*arm_neg_abssi2"
3107   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3108         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3109    (clobber (reg:CC CC_REGNUM))]
3110   "TARGET_ARM"
3111   "@
3112    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3113    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3114   [(set_attr "conds" "clob,*")
3115    (set_attr "shift" "1")
3116    ;; predicable can't be set based on the variant, so left as no
3117    (set_attr "length" "8")]
3118 )
3119
3120 (define_insn_and_split "*thumb_neg_abssi2"
3121   [(set (match_operand:SI 0 "s_register_operand" "=l")
3122         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3123    (clobber (match_scratch:SI 2 "=&l"))]
3124   "TARGET_THUMB"
3125   "#"
3126   "TARGET_THUMB && reload_completed"
3127   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3128    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3129    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3130   ""
3131   [(set_attr "length" "6")]
3132 )
3133
3134 (define_expand "abssf2"
3135   [(set (match_operand:SF         0 "s_register_operand" "")
3136         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3137   "TARGET_ARM && TARGET_HARD_FLOAT"
3138   "")
3139
3140 (define_expand "absdf2"
3141   [(set (match_operand:DF         0 "s_register_operand" "")
3142         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3143   "TARGET_ARM && TARGET_HARD_FLOAT"
3144   "")
3145
3146 (define_expand "sqrtsf2"
3147   [(set (match_operand:SF 0 "s_register_operand" "")
3148         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3149   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3150   "")
3151
3152 (define_expand "sqrtdf2"
3153   [(set (match_operand:DF 0 "s_register_operand" "")
3154         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3155   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3156   "")
3157
3158 (define_insn_and_split "one_cmpldi2"
3159   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3160         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3161   "TARGET_ARM"
3162   "#"
3163   "TARGET_ARM && reload_completed"
3164   [(set (match_dup 0) (not:SI (match_dup 1)))
3165    (set (match_dup 2) (not:SI (match_dup 3)))]
3166   "
3167   {
3168     operands[2] = gen_highpart (SImode, operands[0]);
3169     operands[0] = gen_lowpart (SImode, operands[0]);
3170     operands[3] = gen_highpart (SImode, operands[1]);
3171     operands[1] = gen_lowpart (SImode, operands[1]);
3172   }"
3173   [(set_attr "length" "8")
3174    (set_attr "predicable" "yes")]
3175 )
3176
3177 (define_expand "one_cmplsi2"
3178   [(set (match_operand:SI         0 "s_register_operand" "")
3179         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3180   "TARGET_EITHER"
3181   ""
3182 )
3183
3184 (define_insn "*arm_one_cmplsi2"
3185   [(set (match_operand:SI         0 "s_register_operand" "=r")
3186         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3187   "TARGET_ARM"
3188   "mvn%?\\t%0, %1"
3189   [(set_attr "predicable" "yes")]
3190 )
3191
3192 (define_insn "*thumb_one_cmplsi2"
3193   [(set (match_operand:SI         0 "register_operand" "=l")
3194         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3195   "TARGET_THUMB"
3196   "mvn\\t%0, %1"
3197   [(set_attr "length" "2")]
3198 )
3199
3200 (define_insn "*notsi_compare0"
3201   [(set (reg:CC_NOOV CC_REGNUM)
3202         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3203                          (const_int 0)))
3204    (set (match_operand:SI 0 "s_register_operand" "=r")
3205         (not:SI (match_dup 1)))]
3206   "TARGET_ARM"
3207   "mvn%?s\\t%0, %1"
3208   [(set_attr "conds" "set")]
3209 )
3210
3211 (define_insn "*notsi_compare0_scratch"
3212   [(set (reg:CC_NOOV CC_REGNUM)
3213         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3214                          (const_int 0)))
3215    (clobber (match_scratch:SI 0 "=r"))]
3216   "TARGET_ARM"
3217   "mvn%?s\\t%0, %1"
3218   [(set_attr "conds" "set")]
3219 )
3220 \f
3221 ;; Fixed <--> Floating conversion insns
3222
3223 (define_expand "floatsisf2"
3224   [(set (match_operand:SF           0 "s_register_operand" "")
3225         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3226   "TARGET_ARM && TARGET_HARD_FLOAT"
3227   "
3228   if (TARGET_MAVERICK)
3229     {
3230       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3231       DONE;
3232     }
3233 ")
3234
3235 (define_expand "floatsidf2"
3236   [(set (match_operand:DF           0 "s_register_operand" "")
3237         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3238   "TARGET_ARM && TARGET_HARD_FLOAT"
3239   "
3240   if (TARGET_MAVERICK)
3241     {
3242       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3243       DONE;
3244     }
3245 ")
3246
3247 (define_expand "fix_truncsfsi2"
3248   [(set (match_operand:SI         0 "s_register_operand" "")
3249         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3250   "TARGET_ARM && TARGET_HARD_FLOAT"
3251   "
3252   if (TARGET_MAVERICK)
3253     {
3254       if (!cirrus_fp_register (operands[0], SImode))
3255         operands[0] = force_reg (SImode, operands[0]);
3256       if (!cirrus_fp_register (operands[1], SFmode))
3257         operands[1] = force_reg (SFmode, operands[0]);
3258       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3259       DONE;
3260     }
3261 ")
3262
3263 (define_expand "fix_truncdfsi2"
3264   [(set (match_operand:SI         0 "s_register_operand" "")
3265         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3266   "TARGET_ARM && TARGET_HARD_FLOAT"
3267   "
3268   if (TARGET_MAVERICK)
3269     {
3270       if (!cirrus_fp_register (operands[1], DFmode))
3271         operands[1] = force_reg (DFmode, operands[0]);
3272       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3273       DONE;
3274     }
3275 ")
3276
3277 ;; Truncation insns
3278
3279 (define_expand "truncdfsf2"
3280   [(set (match_operand:SF  0 "s_register_operand" "")
3281         (float_truncate:SF
3282          (match_operand:DF 1 "s_register_operand" "")))]
3283   "TARGET_ARM && TARGET_HARD_FLOAT"
3284   ""
3285 )
3286 \f
3287 ;; Zero and sign extension instructions.
3288
3289 (define_insn "zero_extendsidi2"
3290   [(set (match_operand:DI 0 "s_register_operand" "=r")
3291         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3292   "TARGET_ARM"
3293   "*
3294     if (REGNO (operands[1])
3295         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3296       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3297     return \"mov%?\\t%R0, #0\";
3298   "
3299   [(set_attr "length" "8")
3300    (set_attr "predicable" "yes")]
3301 )
3302
3303 (define_insn "zero_extendqidi2"
3304   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3305         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3306   "TARGET_ARM"
3307   "@
3308    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3309    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3310   [(set_attr "length" "8")
3311    (set_attr "predicable" "yes")
3312    (set_attr "type" "*,load_byte")
3313    (set_attr "pool_range" "*,4092")
3314    (set_attr "neg_pool_range" "*,4084")]
3315 )
3316
3317 (define_insn "extendsidi2"
3318   [(set (match_operand:DI 0 "s_register_operand" "=r")
3319         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3320   "TARGET_ARM"
3321   "*
3322     if (REGNO (operands[1])
3323         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3324       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3325     return \"mov%?\\t%R0, %Q0, asr #31\";
3326   "
3327   [(set_attr "length" "8")
3328    (set_attr "shift" "1")
3329    (set_attr "predicable" "yes")]
3330 )
3331
3332 (define_expand "zero_extendhisi2"
3333   [(set (match_dup 2)
3334         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3335                    (const_int 16)))
3336    (set (match_operand:SI 0 "s_register_operand" "")
3337         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3338   "TARGET_EITHER"
3339   "
3340   {
3341     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3342       {
3343         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3344                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3345         DONE;
3346       }
3347
3348     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3349       {
3350         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3351         DONE;
3352       }
3353
3354     if (!s_register_operand (operands[1], HImode))
3355       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3356
3357     if (arm_arch6)
3358       {
3359         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3360                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3361         DONE;
3362       }
3363
3364     operands[1] = gen_lowpart (SImode, operands[1]);
3365     operands[2] = gen_reg_rtx (SImode);
3366   }"
3367 )
3368
3369 (define_insn "*thumb_zero_extendhisi2"
3370   [(set (match_operand:SI 0 "register_operand" "=l")
3371         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3372   "TARGET_THUMB && !arm_arch6"
3373   "*
3374   rtx mem = XEXP (operands[1], 0);
3375
3376   if (GET_CODE (mem) == CONST)
3377     mem = XEXP (mem, 0);
3378     
3379   if (GET_CODE (mem) == LABEL_REF)
3380     return \"ldr\\t%0, %1\";
3381     
3382   if (GET_CODE (mem) == PLUS)
3383     {
3384       rtx a = XEXP (mem, 0);
3385       rtx b = XEXP (mem, 1);
3386
3387       /* This can happen due to bugs in reload.  */
3388       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3389         {
3390           rtx ops[2];
3391           ops[0] = operands[0];
3392           ops[1] = a;
3393       
3394           output_asm_insn (\"mov        %0, %1\", ops);
3395
3396           XEXP (mem, 0) = operands[0];
3397        }
3398
3399       else if (   GET_CODE (a) == LABEL_REF
3400                && GET_CODE (b) == CONST_INT)
3401         return \"ldr\\t%0, %1\";
3402     }
3403     
3404   return \"ldrh\\t%0, %1\";
3405   "
3406   [(set_attr "length" "4")
3407    (set_attr "type" "load_byte")
3408    (set_attr "pool_range" "60")]
3409 )
3410
3411 (define_insn "*thumb_zero_extendhisi2_v6"
3412   [(set (match_operand:SI 0 "register_operand" "=l,l")
3413         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3414   "TARGET_THUMB && arm_arch6"
3415   "*
3416   rtx mem;
3417
3418   if (which_alternative == 0)
3419     return \"uxth\\t%0, %1\";
3420
3421   mem = XEXP (operands[1], 0);
3422
3423   if (GET_CODE (mem) == CONST)
3424     mem = XEXP (mem, 0);
3425     
3426   if (GET_CODE (mem) == LABEL_REF)
3427     return \"ldr\\t%0, %1\";
3428     
3429   if (GET_CODE (mem) == PLUS)
3430     {
3431       rtx a = XEXP (mem, 0);
3432       rtx b = XEXP (mem, 1);
3433
3434       /* This can happen due to bugs in reload.  */
3435       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3436         {
3437           rtx ops[2];
3438           ops[0] = operands[0];
3439           ops[1] = a;
3440       
3441           output_asm_insn (\"mov        %0, %1\", ops);
3442
3443           XEXP (mem, 0) = operands[0];
3444        }
3445
3446       else if (   GET_CODE (a) == LABEL_REF
3447                && GET_CODE (b) == CONST_INT)
3448         return \"ldr\\t%0, %1\";
3449     }
3450     
3451   return \"ldrh\\t%0, %1\";
3452   "
3453   [(set_attr "length" "2,4")
3454    (set_attr "type" "alu_shift,load_byte")
3455    (set_attr "pool_range" "*,60")]
3456 )
3457
3458 (define_insn "*arm_zero_extendhisi2"
3459   [(set (match_operand:SI 0 "s_register_operand" "=r")
3460         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3461   "TARGET_ARM && arm_arch4 && !arm_arch6"
3462   "ldr%?h\\t%0, %1"
3463   [(set_attr "type" "load_byte")
3464    (set_attr "predicable" "yes")
3465    (set_attr "pool_range" "256")
3466    (set_attr "neg_pool_range" "244")]
3467 )
3468
3469 (define_insn "*arm_zero_extendhisi2_v6"
3470   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3471         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3472   "TARGET_ARM && arm_arch6"
3473   "@
3474    uxth%?\\t%0, %1
3475    ldr%?h\\t%0, %1"
3476   [(set_attr "type" "alu_shift,load_byte")
3477    (set_attr "predicable" "yes")
3478    (set_attr "pool_range" "*,256")
3479    (set_attr "neg_pool_range" "*,244")]
3480 )
3481
3482 (define_insn "*arm_zero_extendhisi2addsi"
3483   [(set (match_operand:SI 0 "s_register_operand" "=r")
3484         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3485                  (match_operand:SI 2 "s_register_operand" "r")))]
3486   "TARGET_ARM && arm_arch6"
3487   "uxtah%?\\t%0, %2, %1"
3488   [(set_attr "type" "alu_shift")
3489    (set_attr "predicable" "yes")]
3490 )
3491
3492 (define_expand "zero_extendqisi2"
3493   [(set (match_operand:SI 0 "s_register_operand" "")
3494         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3495   "TARGET_EITHER"
3496   "
3497   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3498     {
3499       if (TARGET_ARM)
3500         {
3501           emit_insn (gen_andsi3 (operands[0],
3502                                  gen_lowpart (SImode, operands[1]),
3503                                  GEN_INT (255)));
3504         }
3505       else /* TARGET_THUMB */
3506         {
3507           rtx temp = gen_reg_rtx (SImode);
3508           rtx ops[3];
3509           
3510           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3511           operands[1] = gen_lowpart (SImode, operands[1]);
3512
3513           ops[0] = temp;
3514           ops[1] = operands[1];
3515           ops[2] = GEN_INT (24);
3516
3517           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3518                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3519           
3520           ops[0] = operands[0];
3521           ops[1] = temp;
3522           ops[2] = GEN_INT (24);
3523
3524           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3525                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3526         }
3527       DONE;
3528     }
3529   "
3530 )
3531
3532 (define_insn "*thumb_zero_extendqisi2"
3533   [(set (match_operand:SI 0 "register_operand" "=l")
3534         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3535   "TARGET_THUMB && !arm_arch6"
3536   "ldrb\\t%0, %1"
3537   [(set_attr "length" "2")
3538    (set_attr "type" "load_byte")
3539    (set_attr "pool_range" "32")]
3540 )
3541
3542 (define_insn "*thumb_zero_extendqisi2_v6"
3543   [(set (match_operand:SI 0 "register_operand" "=l,l")
3544         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3545   "TARGET_THUMB && arm_arch6"
3546   "@
3547    uxtb\\t%0, %1
3548    ldrb\\t%0, %1"
3549   [(set_attr "length" "2,2")
3550    (set_attr "type" "alu_shift,load_byte")
3551    (set_attr "pool_range" "*,32")]
3552 )
3553
3554 (define_insn "*arm_zero_extendqisi2"
3555   [(set (match_operand:SI 0 "s_register_operand" "=r")
3556         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3557   "TARGET_ARM && !arm_arch6"
3558   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3559   [(set_attr "type" "load_byte")
3560    (set_attr "predicable" "yes")
3561    (set_attr "pool_range" "4096")
3562    (set_attr "neg_pool_range" "4084")]
3563 )
3564
3565 (define_insn "*arm_zero_extendqisi2_v6"
3566   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3567         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3568   "TARGET_ARM && arm_arch6"
3569   "@
3570    uxtb%?\\t%0, %1
3571    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3572   [(set_attr "type" "alu_shift,load_byte")
3573    (set_attr "predicable" "yes")
3574    (set_attr "pool_range" "*,4096")
3575    (set_attr "neg_pool_range" "*,4084")]
3576 )
3577
3578 (define_insn "*arm_zero_extendqisi2addsi"
3579   [(set (match_operand:SI 0 "s_register_operand" "=r")
3580         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3581                  (match_operand:SI 2 "s_register_operand" "r")))]
3582   "TARGET_ARM && arm_arch6"
3583   "uxtab%?\\t%0, %2, %1"
3584   [(set_attr "predicable" "yes")
3585    (set_attr "type" "alu_shift")]
3586 )
3587
3588 (define_split
3589   [(set (match_operand:SI 0 "s_register_operand" "")
3590         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3591    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3592   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3593   [(set (match_dup 2) (match_dup 1))
3594    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3595   ""
3596 )
3597
3598 (define_split
3599   [(set (match_operand:SI 0 "s_register_operand" "")
3600         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3601    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3602   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3603   [(set (match_dup 2) (match_dup 1))
3604    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3605   ""
3606 )
3607
3608 (define_insn "*compareqi_eq0"
3609   [(set (reg:CC_Z CC_REGNUM)
3610         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3611                          (const_int 0)))]
3612   "TARGET_ARM"
3613   "tst\\t%0, #255"
3614   [(set_attr "conds" "set")]
3615 )
3616
3617 (define_expand "extendhisi2"
3618   [(set (match_dup 2)
3619         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3620                    (const_int 16)))
3621    (set (match_operand:SI 0 "s_register_operand" "")
3622         (ashiftrt:SI (match_dup 2)
3623                      (const_int 16)))]
3624   "TARGET_EITHER"
3625   "
3626   {
3627     if (GET_CODE (operands[1]) == MEM)
3628       {
3629         if (TARGET_THUMB)
3630           {
3631             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3632             DONE;
3633           }
3634         else if (arm_arch4)
3635           {
3636             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3637                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3638             DONE;
3639           }
3640       }
3641
3642     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3643       {
3644         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3645         DONE;
3646       }
3647
3648     if (!s_register_operand (operands[1], HImode))
3649       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3650
3651     if (arm_arch6)
3652       {
3653         if (TARGET_THUMB)
3654           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3655         else
3656           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3657                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3658
3659         DONE;
3660       }
3661
3662     operands[1] = gen_lowpart (SImode, operands[1]);
3663     operands[2] = gen_reg_rtx (SImode);
3664   }"
3665 )
3666
3667 (define_insn "thumb_extendhisi2"
3668   [(set (match_operand:SI 0 "register_operand" "=l")
3669         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3670    (clobber (match_scratch:SI 2 "=&l"))]
3671   "TARGET_THUMB && !arm_arch6"
3672   "*
3673   {
3674     rtx ops[4];
3675     rtx mem = XEXP (operands[1], 0);
3676
3677     /* This code used to try to use 'V', and fix the address only if it was
3678        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3679        range of QImode offsets, and offsettable_address_p does a QImode
3680        address check.  */
3681        
3682     if (GET_CODE (mem) == CONST)
3683       mem = XEXP (mem, 0);
3684     
3685     if (GET_CODE (mem) == LABEL_REF)
3686       return \"ldr\\t%0, %1\";
3687     
3688     if (GET_CODE (mem) == PLUS)
3689       {
3690         rtx a = XEXP (mem, 0);
3691         rtx b = XEXP (mem, 1);
3692
3693         if (GET_CODE (a) == LABEL_REF
3694             && GET_CODE (b) == CONST_INT)
3695           return \"ldr\\t%0, %1\";
3696
3697         if (GET_CODE (b) == REG)
3698           return \"ldrsh\\t%0, %1\";
3699           
3700         ops[1] = a;
3701         ops[2] = b;
3702       }
3703     else
3704       {
3705         ops[1] = mem;
3706         ops[2] = const0_rtx;
3707       }
3708
3709     gcc_assert (GET_CODE (ops[1]) == REG);
3710
3711     ops[0] = operands[0];
3712     ops[3] = operands[2];
3713     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3714     return \"\";
3715   }"
3716   [(set_attr "length" "4")
3717    (set_attr "type" "load_byte")
3718    (set_attr "pool_range" "1020")]
3719 )
3720
3721 ;; We used to have an early-clobber on the scratch register here.
3722 ;; However, there's a bug somewhere in reload which means that this
3723 ;; can be partially ignored during spill allocation if the memory
3724 ;; address also needs reloading; this causes us to die later on when
3725 ;; we try to verify the operands.  Fortunately, we don't really need
3726 ;; the early-clobber: we can always use operand 0 if operand 2
3727 ;; overlaps the address.
3728 (define_insn "*thumb_extendhisi2_insn_v6"
3729   [(set (match_operand:SI 0 "register_operand" "=l,l")
3730         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3731    (clobber (match_scratch:SI 2 "=X,l"))]
3732   "TARGET_THUMB && arm_arch6"
3733   "*
3734   {
3735     rtx ops[4];
3736     rtx mem;
3737
3738     if (which_alternative == 0)
3739       return \"sxth\\t%0, %1\";
3740
3741     mem = XEXP (operands[1], 0);
3742
3743     /* This code used to try to use 'V', and fix the address only if it was
3744        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3745        range of QImode offsets, and offsettable_address_p does a QImode
3746        address check.  */
3747        
3748     if (GET_CODE (mem) == CONST)
3749       mem = XEXP (mem, 0);
3750     
3751     if (GET_CODE (mem) == LABEL_REF)
3752       return \"ldr\\t%0, %1\";
3753     
3754     if (GET_CODE (mem) == PLUS)
3755       {
3756         rtx a = XEXP (mem, 0);
3757         rtx b = XEXP (mem, 1);
3758
3759         if (GET_CODE (a) == LABEL_REF
3760             && GET_CODE (b) == CONST_INT)
3761           return \"ldr\\t%0, %1\";
3762
3763         if (GET_CODE (b) == REG)
3764           return \"ldrsh\\t%0, %1\";
3765           
3766         ops[1] = a;
3767         ops[2] = b;
3768       }
3769     else
3770       {
3771         ops[1] = mem;
3772         ops[2] = const0_rtx;
3773       }
3774       
3775     gcc_assert (GET_CODE (ops[1]) == REG);
3776
3777     ops[0] = operands[0];
3778     if (reg_mentioned_p (operands[2], ops[1]))
3779       ops[3] = ops[0];
3780     else
3781       ops[3] = operands[2];
3782     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3783     return \"\";
3784   }"
3785   [(set_attr "length" "2,4")
3786    (set_attr "type" "alu_shift,load_byte")
3787    (set_attr "pool_range" "*,1020")]
3788 )
3789
3790 (define_expand "extendhisi2_mem"
3791   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3792    (set (match_dup 3)
3793         (zero_extend:SI (match_dup 7)))
3794    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3795    (set (match_operand:SI 0 "" "")
3796         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3797   "TARGET_ARM"
3798   "
3799   {
3800     rtx mem1, mem2;
3801     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3802
3803     mem1 = change_address (operands[1], QImode, addr);
3804     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3805     operands[0] = gen_lowpart (SImode, operands[0]);
3806     operands[1] = mem1;
3807     operands[2] = gen_reg_rtx (SImode);
3808     operands[3] = gen_reg_rtx (SImode);
3809     operands[6] = gen_reg_rtx (SImode);
3810     operands[7] = mem2;
3811
3812     if (BYTES_BIG_ENDIAN)
3813       {
3814         operands[4] = operands[2];
3815         operands[5] = operands[3];
3816       }
3817     else
3818       {
3819         operands[4] = operands[3];
3820         operands[5] = operands[2];
3821       }
3822   }"
3823 )
3824
3825 (define_insn "*arm_extendhisi2"
3826   [(set (match_operand:SI 0 "s_register_operand" "=r")
3827         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3828   "TARGET_ARM && arm_arch4 && !arm_arch6"
3829   "ldr%?sh\\t%0, %1"
3830   [(set_attr "type" "load_byte")
3831    (set_attr "predicable" "yes")
3832    (set_attr "pool_range" "256")
3833    (set_attr "neg_pool_range" "244")]
3834 )
3835
3836 (define_insn "*arm_extendhisi2_v6"
3837   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3838         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3839   "TARGET_ARM && arm_arch6"
3840   "@
3841    sxth%?\\t%0, %1
3842    ldr%?sh\\t%0, %1"
3843   [(set_attr "type" "alu_shift,load_byte")
3844    (set_attr "predicable" "yes")
3845    (set_attr "pool_range" "*,256")
3846    (set_attr "neg_pool_range" "*,244")]
3847 )
3848
3849 (define_insn "*arm_extendhisi2addsi"
3850   [(set (match_operand:SI 0 "s_register_operand" "=r")
3851         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3852                  (match_operand:SI 2 "s_register_operand" "r")))]
3853   "TARGET_ARM && arm_arch6"
3854   "sxtah%?\\t%0, %2, %1"
3855 )
3856
3857 (define_expand "extendqihi2"
3858   [(set (match_dup 2)
3859         (ashift:SI (match_operand:QI 1 "general_operand" "")
3860                    (const_int 24)))
3861    (set (match_operand:HI 0 "s_register_operand" "")
3862         (ashiftrt:SI (match_dup 2)
3863                      (const_int 24)))]
3864   "TARGET_ARM"
3865   "
3866   {
3867     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3868       {
3869         emit_insn (gen_rtx_SET (VOIDmode,
3870                                 operands[0],
3871                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3872         DONE;
3873       }
3874     if (!s_register_operand (operands[1], QImode))
3875       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3876     operands[0] = gen_lowpart (SImode, operands[0]);
3877     operands[1] = gen_lowpart (SImode, operands[1]);
3878     operands[2] = gen_reg_rtx (SImode);
3879   }"
3880 )
3881
3882 (define_insn "*extendqihi_insn"
3883   [(set (match_operand:HI 0 "s_register_operand" "=r")
3884         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3885   "TARGET_ARM && arm_arch4"
3886   "ldr%?sb\\t%0, %1"
3887   [(set_attr "type" "load_byte")
3888    (set_attr "predicable" "yes")
3889    (set_attr "pool_range" "256")
3890    (set_attr "neg_pool_range" "244")]
3891 )
3892
3893 (define_expand "extendqisi2"
3894   [(set (match_dup 2)
3895         (ashift:SI (match_operand:QI 1 "general_operand" "")
3896                    (const_int 24)))
3897    (set (match_operand:SI 0 "s_register_operand" "")
3898         (ashiftrt:SI (match_dup 2)
3899                      (const_int 24)))]
3900   "TARGET_EITHER"
3901   "
3902   {
3903     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3904       {
3905         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3906                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3907         DONE;
3908       }
3909
3910     if (!s_register_operand (operands[1], QImode))
3911       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3912
3913     if (arm_arch6)
3914       {
3915         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3916                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3917         DONE;
3918       }
3919
3920     operands[1] = gen_lowpart (SImode, operands[1]);
3921     operands[2] = gen_reg_rtx (SImode);
3922   }"
3923 )
3924
3925 (define_insn "*arm_extendqisi"
3926   [(set (match_operand:SI 0 "s_register_operand" "=r")
3927         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3928   "TARGET_ARM && arm_arch4 && !arm_arch6"
3929   "ldr%?sb\\t%0, %1"
3930   [(set_attr "type" "load_byte")
3931    (set_attr "predicable" "yes")
3932    (set_attr "pool_range" "256")
3933    (set_attr "neg_pool_range" "244")]
3934 )
3935
3936 (define_insn "*arm_extendqisi_v6"
3937   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3938         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3939   "TARGET_ARM && arm_arch6"
3940   "@
3941    sxtb%?\\t%0, %1
3942    ldr%?sb\\t%0, %1"
3943   [(set_attr "type" "alu_shift,load_byte")
3944    (set_attr "predicable" "yes")
3945    (set_attr "pool_range" "*,256")
3946    (set_attr "neg_pool_range" "*,244")]
3947 )
3948
3949 (define_insn "*arm_extendqisi2addsi"
3950   [(set (match_operand:SI 0 "s_register_operand" "=r")
3951         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3952                  (match_operand:SI 2 "s_register_operand" "r")))]
3953   "TARGET_ARM && arm_arch6"
3954   "sxtab%?\\t%0, %2, %1"
3955   [(set_attr "type" "alu_shift")
3956    (set_attr "predicable" "yes")]
3957 )
3958
3959 (define_insn "*thumb_extendqisi2"
3960   [(set (match_operand:SI 0 "register_operand" "=l,l")
3961         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3962   "TARGET_THUMB && !arm_arch6"
3963   "*
3964   {
3965     rtx ops[3];
3966     rtx mem = XEXP (operands[1], 0);
3967     
3968     if (GET_CODE (mem) == CONST)
3969       mem = XEXP (mem, 0);
3970     
3971     if (GET_CODE (mem) == LABEL_REF)
3972       return \"ldr\\t%0, %1\";
3973
3974     if (GET_CODE (mem) == PLUS
3975         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3976       return \"ldr\\t%0, %1\";
3977       
3978     if (which_alternative == 0)
3979       return \"ldrsb\\t%0, %1\";
3980       
3981     ops[0] = operands[0];
3982     
3983     if (GET_CODE (mem) == PLUS)
3984       {
3985         rtx a = XEXP (mem, 0);
3986         rtx b = XEXP (mem, 1);
3987         
3988         ops[1] = a;
3989         ops[2] = b;
3990
3991         if (GET_CODE (a) == REG)
3992           {
3993             if (GET_CODE (b) == REG)
3994               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3995             else if (REGNO (a) == REGNO (ops[0]))
3996               {
3997                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3998                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3999                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4000               }
4001             else
4002               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4003           }
4004         else
4005           {
4006             gcc_assert (GET_CODE (b) == REG);
4007             if (REGNO (b) == REGNO (ops[0]))
4008               {
4009                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4010                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4011                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4012               }
4013             else
4014               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4015           }
4016       }
4017     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4018       {
4019         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4020         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4021         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4022       }
4023     else
4024       {
4025         ops[1] = mem;
4026         ops[2] = const0_rtx;
4027         
4028         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4029       }
4030     return \"\";
4031   }"
4032   [(set_attr "length" "2,6")
4033    (set_attr "type" "load_byte,load_byte")
4034    (set_attr "pool_range" "32,32")]
4035 )
4036
4037 (define_insn "*thumb_extendqisi2_v6"
4038   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4039         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4040   "TARGET_THUMB && arm_arch6"
4041   "*
4042   {
4043     rtx ops[3];
4044     rtx mem;
4045
4046     if (which_alternative == 0)
4047       return \"sxtb\\t%0, %1\";
4048
4049     mem = XEXP (operands[1], 0);
4050     
4051     if (GET_CODE (mem) == CONST)
4052       mem = XEXP (mem, 0);
4053     
4054     if (GET_CODE (mem) == LABEL_REF)
4055       return \"ldr\\t%0, %1\";
4056
4057     if (GET_CODE (mem) == PLUS
4058         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4059       return \"ldr\\t%0, %1\";
4060       
4061     if (which_alternative == 0)
4062       return \"ldrsb\\t%0, %1\";
4063       
4064     ops[0] = operands[0];
4065     
4066     if (GET_CODE (mem) == PLUS)
4067       {
4068         rtx a = XEXP (mem, 0);
4069         rtx b = XEXP (mem, 1);
4070         
4071         ops[1] = a;
4072         ops[2] = b;
4073
4074         if (GET_CODE (a) == REG)
4075           {
4076             if (GET_CODE (b) == REG)
4077               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4078             else if (REGNO (a) == REGNO (ops[0]))
4079               {
4080                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4081                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4082               }
4083             else
4084               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4085           }
4086         else
4087           {
4088             gcc_assert (GET_CODE (b) == REG);
4089             if (REGNO (b) == REGNO (ops[0]))
4090               {
4091                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4092                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4093               }
4094             else
4095               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4096           }
4097       }
4098     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4099       {
4100         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4101         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4102       }
4103     else
4104       {
4105         ops[1] = mem;
4106         ops[2] = const0_rtx;
4107         
4108         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4109       }
4110     return \"\";
4111   }"
4112   [(set_attr "length" "2,2,4")
4113    (set_attr "type" "alu_shift,load_byte,load_byte")
4114    (set_attr "pool_range" "*,32,32")]
4115 )
4116
4117 (define_expand "extendsfdf2"
4118   [(set (match_operand:DF                  0 "s_register_operand" "")
4119         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4120   "TARGET_ARM && TARGET_HARD_FLOAT"
4121   ""
4122 )
4123 \f
4124 ;; Move insns (including loads and stores)
4125
4126 ;; XXX Just some ideas about movti.
4127 ;; I don't think these are a good idea on the arm, there just aren't enough
4128 ;; registers
4129 ;;(define_expand "loadti"
4130 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4131 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4132 ;;  "" "")
4133
4134 ;;(define_expand "storeti"
4135 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4136 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4137 ;;  "" "")
4138
4139 ;;(define_expand "movti"
4140 ;;  [(set (match_operand:TI 0 "general_operand" "")
4141 ;;      (match_operand:TI 1 "general_operand" ""))]
4142 ;;  ""
4143 ;;  "
4144 ;;{
4145 ;;  rtx insn;
4146 ;;
4147 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4148 ;;    operands[1] = copy_to_reg (operands[1]);
4149 ;;  if (GET_CODE (operands[0]) == MEM)
4150 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4151 ;;  else if (GET_CODE (operands[1]) == MEM)
4152 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4153 ;;  else
4154 ;;    FAIL;
4155 ;;
4156 ;;  emit_insn (insn);
4157 ;;  DONE;
4158 ;;}")
4159
4160 ;; Recognize garbage generated above.
4161
4162 ;;(define_insn ""
4163 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4164 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4165 ;;  ""
4166 ;;  "*
4167 ;;  {
4168 ;;    register mem = (which_alternative < 3);
4169 ;;    register const char *template;
4170 ;;
4171 ;;    operands[mem] = XEXP (operands[mem], 0);
4172 ;;    switch (which_alternative)
4173 ;;      {
4174 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4175 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4176 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4177 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4178 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4179 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4180 ;;      }
4181 ;;    output_asm_insn (template, operands);
4182 ;;    return \"\";
4183 ;;  }")
4184
4185 (define_expand "movdi"
4186   [(set (match_operand:DI 0 "general_operand" "")
4187         (match_operand:DI 1 "general_operand" ""))]
4188   "TARGET_EITHER"
4189   "
4190   if (!no_new_pseudos)
4191     {
4192       if (GET_CODE (operands[0]) != REG)
4193         operands[1] = force_reg (DImode, operands[1]);
4194     }
4195   "
4196 )
4197
4198 (define_insn "*arm_movdi"
4199   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4200         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4201   "TARGET_ARM
4202    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4203    && !TARGET_IWMMXT
4204    && (   register_operand (operands[0], DImode)
4205        || register_operand (operands[1], DImode))"
4206   "*
4207   switch (which_alternative)
4208     {
4209     case 0:
4210     case 1:
4211     case 2:
4212       return \"#\";
4213     default:
4214       return output_move_double (operands);
4215     }
4216   "
4217   [(set_attr "length" "8,12,16,8,8")
4218    (set_attr "type" "*,*,*,load2,store2")
4219    (set_attr "pool_range" "*,*,*,1020,*")
4220    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4221 )
4222
4223 (define_split
4224   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4225         (match_operand:ANY64 1 "const_double_operand" ""))]
4226   "TARGET_ARM
4227    && reload_completed
4228    && (arm_const_double_inline_cost (operands[1])
4229        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4230   [(const_int 0)]
4231   "
4232   arm_split_constant (SET, SImode, curr_insn,
4233                       INTVAL (gen_lowpart (SImode, operands[1])),
4234                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4235   arm_split_constant (SET, SImode, curr_insn,
4236                       INTVAL (gen_highpart_mode (SImode,
4237                                                  GET_MODE (operands[0]),
4238                                                  operands[1])),
4239                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4240   DONE;
4241   "
4242 )
4243
4244 ; If optimizing for size, or if we have load delay slots, then 
4245 ; we want to split the constant into two separate operations. 
4246 ; In both cases this may split a trivial part into a single data op
4247 ; leaving a single complex constant to load.  We can also get longer
4248 ; offsets in a LDR which means we get better chances of sharing the pool
4249 ; entries.  Finally, we can normally do a better job of scheduling
4250 ; LDR instructions than we can with LDM.
4251 ; This pattern will only match if the one above did not.
4252 (define_split
4253   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4254         (match_operand:ANY64 1 "const_double_operand" ""))]
4255   "TARGET_ARM && reload_completed
4256    && arm_const_double_by_parts (operands[1])"
4257   [(set (match_dup 0) (match_dup 1))
4258    (set (match_dup 2) (match_dup 3))]
4259   "
4260   operands[2] = gen_highpart (SImode, operands[0]);
4261   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4262                                    operands[1]);
4263   operands[0] = gen_lowpart (SImode, operands[0]);
4264   operands[1] = gen_lowpart (SImode, operands[1]);
4265   "
4266 )
4267
4268 (define_split
4269   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4270         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4271   "TARGET_EITHER && reload_completed"
4272   [(set (match_dup 0) (match_dup 1))
4273    (set (match_dup 2) (match_dup 3))]
4274   "
4275   operands[2] = gen_highpart (SImode, operands[0]);
4276   operands[3] = gen_highpart (SImode, operands[1]);
4277   operands[0] = gen_lowpart (SImode, operands[0]);
4278   operands[1] = gen_lowpart (SImode, operands[1]);
4279
4280   /* Handle a partial overlap.  */
4281   if (rtx_equal_p (operands[0], operands[3]))
4282     {
4283       rtx tmp0 = operands[0];
4284       rtx tmp1 = operands[1];
4285
4286       operands[0] = operands[2];
4287       operands[1] = operands[3];
4288       operands[2] = tmp0;
4289       operands[3] = tmp1;
4290     }
4291   "
4292 )
4293
4294 ;; We can't actually do base+index doubleword loads if the index and
4295 ;; destination overlap.  Split here so that we at least have chance to
4296 ;; schedule.
4297 (define_split
4298   [(set (match_operand:DI 0 "s_register_operand" "")
4299         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4300                          (match_operand:SI 2 "s_register_operand" ""))))]
4301   "TARGET_LDRD
4302   && reg_overlap_mentioned_p (operands[0], operands[1])
4303   && reg_overlap_mentioned_p (operands[0], operands[2])"
4304   [(set (match_dup 4)
4305         (plus:SI (match_dup 1)
4306                  (match_dup 2)))
4307    (set (match_dup 0)
4308         (mem:DI (match_dup 4)))]
4309   "
4310   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4311   "
4312 )
4313
4314 ;;; ??? This should have alternatives for constants.
4315 ;;; ??? This was originally identical to the movdf_insn pattern.
4316 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4317 ;;; thumb_reorg with a memory reference.
4318 (define_insn "*thumb_movdi_insn"
4319   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4320         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4321   "TARGET_THUMB
4322    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4323    && (   register_operand (operands[0], DImode)
4324        || register_operand (operands[1], DImode))"
4325   "*
4326   {
4327   switch (which_alternative)
4328     {
4329     default:
4330     case 0:
4331       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4332         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4333       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4334     case 1:
4335       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4336     case 2:
4337       operands[1] = GEN_INT (- INTVAL (operands[1]));
4338       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4339     case 3:
4340       return \"ldmia\\t%1, {%0, %H0}\";
4341     case 4:
4342       return \"stmia\\t%0, {%1, %H1}\";
4343     case 5:
4344       return thumb_load_double_from_address (operands);
4345     case 6:
4346       operands[2] = gen_rtx_MEM (SImode,
4347                              plus_constant (XEXP (operands[0], 0), 4));
4348       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4349       return \"\";
4350     case 7:
4351       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4352         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4353       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4354     }
4355   }"
4356   [(set_attr "length" "4,4,6,2,2,6,4,4")
4357    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4358    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4359 )
4360
4361 (define_expand "movsi"
4362   [(set (match_operand:SI 0 "general_operand" "")
4363         (match_operand:SI 1 "general_operand" ""))]
4364   "TARGET_EITHER"
4365   "
4366   if (TARGET_ARM)
4367     {
4368       /* Everything except mem = const or mem = mem can be done easily.  */
4369       if (GET_CODE (operands[0]) == MEM)
4370         operands[1] = force_reg (SImode, operands[1]);
4371       if (arm_general_register_operand (operands[0], SImode)
4372           && GET_CODE (operands[1]) == CONST_INT
4373           && !(const_ok_for_arm (INTVAL (operands[1]))
4374                || const_ok_for_arm (~INTVAL (operands[1]))))
4375         {
4376            arm_split_constant (SET, SImode, NULL_RTX,
4377                                INTVAL (operands[1]), operands[0], NULL_RTX,
4378                                optimize && !no_new_pseudos);
4379           DONE;
4380         }
4381     }
4382   else /* TARGET_THUMB....  */
4383     {
4384       if (!no_new_pseudos)
4385         {
4386           if (GET_CODE (operands[0]) != REG)
4387             operands[1] = force_reg (SImode, operands[1]);
4388         }
4389     }
4390
4391   /* Recognize the case where operand[1] is a reference to thread-local
4392      data and load its address to a register.  */
4393   if (arm_tls_referenced_p (operands[1]))
4394     {
4395       rtx tmp = operands[1];
4396       rtx addend = NULL;
4397
4398       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4399         {
4400           addend = XEXP (XEXP (tmp, 0), 1);
4401           tmp = XEXP (XEXP (tmp, 0), 0);
4402         }
4403
4404       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4405       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4406
4407       tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4408       if (addend)
4409         {
4410           tmp = gen_rtx_PLUS (SImode, tmp, addend);
4411           tmp = force_operand (tmp, operands[0]);
4412         }
4413       operands[1] = tmp;
4414     }
4415   else if (flag_pic
4416            && (CONSTANT_P (operands[1])
4417                || symbol_mentioned_p (operands[1])
4418                || label_mentioned_p (operands[1])))
4419       operands[1] = legitimize_pic_address (operands[1], SImode,
4420                                             (no_new_pseudos ? operands[0] : 0));
4421   "
4422 )
4423
4424 (define_insn "*arm_movsi_insn"
4425   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4426         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4427   "TARGET_ARM && ! TARGET_IWMMXT
4428    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4429    && (   register_operand (operands[0], SImode)
4430        || register_operand (operands[1], SImode))"
4431   "@
4432    mov%?\\t%0, %1
4433    mvn%?\\t%0, #%B1
4434    ldr%?\\t%0, %1
4435    str%?\\t%1, %0"
4436   [(set_attr "type" "*,*,load1,store1")
4437    (set_attr "predicable" "yes")
4438    (set_attr "pool_range" "*,*,4096,*")
4439    (set_attr "neg_pool_range" "*,*,4084,*")]
4440 )
4441
4442 (define_split
4443   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4444         (match_operand:SI 1 "const_int_operand" ""))]
4445   "TARGET_ARM
4446   && (!(const_ok_for_arm (INTVAL (operands[1]))
4447         || const_ok_for_arm (~INTVAL (operands[1]))))"
4448   [(clobber (const_int 0))]
4449   "
4450   arm_split_constant (SET, SImode, NULL_RTX, 
4451                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4452   DONE;
4453   "
4454 )
4455
4456 (define_insn "*thumb_movsi_insn"
4457   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4458         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4459   "TARGET_THUMB
4460    && (   register_operand (operands[0], SImode) 
4461        || register_operand (operands[1], SImode))"
4462   "@
4463    mov  %0, %1
4464    mov  %0, %1
4465    #
4466    #
4467    ldmia\\t%1, {%0}
4468    stmia\\t%0, {%1}
4469    ldr\\t%0, %1
4470    str\\t%1, %0
4471    mov\\t%0, %1"
4472   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4473    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4474    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4475 )
4476
4477 (define_split 
4478   [(set (match_operand:SI 0 "register_operand" "")
4479         (match_operand:SI 1 "const_int_operand" ""))]
4480   "TARGET_THUMB && satisfies_constraint_J (operands[1])"
4481   [(set (match_dup 0) (match_dup 1))
4482    (set (match_dup 0) (neg:SI (match_dup 0)))]
4483   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4484 )
4485
4486 (define_split 
4487   [(set (match_operand:SI 0 "register_operand" "")
4488         (match_operand:SI 1 "const_int_operand" ""))]
4489   "TARGET_THUMB && satisfies_constraint_K (operands[1])"
4490   [(set (match_dup 0) (match_dup 1))
4491    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4492   "
4493   {
4494     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4495     unsigned HOST_WIDE_INT mask = 0xff;
4496     int i;
4497     
4498     for (i = 0; i < 25; i++)
4499       if ((val & (mask << i)) == val)
4500         break;
4501
4502     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4503     if (i == 0)
4504       FAIL;
4505
4506     operands[1] = GEN_INT (val >> i);
4507     operands[2] = GEN_INT (i);
4508   }"
4509 )
4510
4511 ;; When generating pic, we need to load the symbol offset into a register.
4512 ;; So that the optimizer does not confuse this with a normal symbol load
4513 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4514 ;; since that is the only type of relocation we can use.
4515
4516 ;; The rather odd constraints on the following are to force reload to leave
4517 ;; the insn alone, and to force the minipool generation pass to then move
4518 ;; the GOT symbol to memory.
4519
4520 (define_insn "pic_load_addr_arm"
4521   [(set (match_operand:SI 0 "s_register_operand" "=r")
4522         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4523   "TARGET_ARM && flag_pic"
4524   "ldr%?\\t%0, %1"
4525   [(set_attr "type" "load1")
4526    (set (attr "pool_range")     (const_int 4096))
4527    (set (attr "neg_pool_range") (const_int 4084))]
4528 )
4529
4530 (define_insn "pic_load_addr_thumb"
4531   [(set (match_operand:SI 0 "s_register_operand" "=l")
4532         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4533   "TARGET_THUMB && flag_pic"
4534   "ldr\\t%0, %1"
4535   [(set_attr "type" "load1")
4536    (set (attr "pool_range") (const_int 1024))]
4537 )
4538
4539 ;; This variant is used for AOF assembly, since it needs to mention the
4540 ;; pic register in the rtl.
4541 (define_expand "pic_load_addr_based"
4542   [(set (match_operand:SI 0 "s_register_operand" "")
4543         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4544   "TARGET_ARM && flag_pic"
4545   "operands[2] = cfun->machine->pic_reg;"
4546 )
4547
4548 (define_insn "*pic_load_addr_based_insn"
4549   [(set (match_operand:SI 0 "s_register_operand" "=r")
4550         (unspec:SI [(match_operand 1 "" "")
4551                     (match_operand 2 "s_register_operand" "r")]
4552                    UNSPEC_PIC_SYM))]
4553   "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
4554   "*
4555 #ifdef AOF_ASSEMBLER
4556   operands[1] = aof_pic_entry (operands[1]);
4557 #endif
4558   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4559   return \"\";
4560   "
4561   [(set_attr "type" "load1")
4562    (set (attr "pool_range")
4563         (if_then_else (eq_attr "is_thumb" "yes")
4564                       (const_int 1024)
4565                       (const_int 4096)))
4566    (set (attr "neg_pool_range")
4567         (if_then_else (eq_attr "is_thumb" "yes")
4568                       (const_int 0)
4569                       (const_int 4084)))]
4570 )
4571
4572 (define_insn "pic_add_dot_plus_four"
4573   [(set (match_operand:SI 0 "register_operand" "=r")
4574         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4575                              (const (plus:SI (pc) (const_int 4))))]
4576                    UNSPEC_PIC_BASE))
4577    (use (match_operand 2 "" ""))]
4578   "TARGET_THUMB"
4579   "*
4580   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4581                                      INTVAL (operands[2]));
4582   return \"add\\t%0, %|pc\";
4583   "
4584   [(set_attr "length" "2")]
4585 )
4586
4587 (define_insn "pic_add_dot_plus_eight"
4588   [(set (match_operand:SI 0 "register_operand" "=r")
4589         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4590                              (const (plus:SI (pc) (const_int 8))))]
4591                    UNSPEC_PIC_BASE))
4592    (use (match_operand 2 "" ""))]
4593   "TARGET_ARM"
4594   "*
4595     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4596                                        INTVAL (operands[2]));
4597     return \"add%?\\t%0, %|pc, %1\";
4598   "
4599   [(set_attr "predicable" "yes")]
4600 )
4601
4602 (define_insn "tls_load_dot_plus_eight"
4603   [(set (match_operand:SI 0 "register_operand" "+r")
4604         (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4605                                      (const (plus:SI (pc) (const_int 8))))]
4606                            UNSPEC_PIC_BASE)))
4607    (use (match_operand 2 "" ""))]
4608   "TARGET_ARM"
4609   "*
4610     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4611                                        INTVAL (operands[2]));
4612     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4613   "
4614   [(set_attr "predicable" "yes")]
4615 )
4616
4617 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4618 ;; followed by a load.  These sequences can be crunched down to
4619 ;; tls_load_dot_plus_eight by a peephole.
4620
4621 (define_peephole2
4622   [(parallel [(set (match_operand:SI 0 "register_operand" "")
4623                    (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4624                                         (const (plus:SI (pc) (const_int 8))))]
4625                               UNSPEC_PIC_BASE))
4626               (use (label_ref (match_operand 1 "" "")))])
4627    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4628   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4629   [(parallel [(set (match_dup 2)
4630                    (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4631                                                 (const (plus:SI (pc) (const_int 8))))]
4632                                       UNSPEC_PIC_BASE)))
4633               (use (label_ref (match_dup 1)))])]
4634   ""
4635 )
4636
4637 (define_expand "builtin_setjmp_receiver"
4638   [(label_ref (match_operand 0 "" ""))]
4639   "flag_pic"
4640   "
4641 {
4642   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4643      register.  */
4644   if (arm_pic_register != INVALID_REGNUM)
4645     arm_load_pic_register (1UL << 3);
4646   DONE;
4647 }")
4648
4649 ;; If copying one reg to another we can set the condition codes according to
4650 ;; its value.  Such a move is common after a return from subroutine and the
4651 ;; result is being tested against zero.
4652
4653 (define_insn "*movsi_compare0"
4654   [(set (reg:CC CC_REGNUM)
4655         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4656                     (const_int 0)))
4657    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4658         (match_dup 1))]
4659   "TARGET_ARM"
4660   "@
4661    cmp%?\\t%0, #0
4662    sub%?s\\t%0, %1, #0"
4663   [(set_attr "conds" "set")]
4664 )
4665
4666 ;; Subroutine to store a half word from a register into memory.
4667 ;; Operand 0 is the source register (HImode)
4668 ;; Operand 1 is the destination address in a register (SImode)
4669
4670 ;; In both this routine and the next, we must be careful not to spill
4671 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4672 ;; can generate unrecognizable rtl.
4673
4674 (define_expand "storehi"
4675   [;; store the low byte
4676    (set (match_operand 1 "" "") (match_dup 3))
4677    ;; extract the high byte
4678    (set (match_dup 2)
4679         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4680    ;; store the high byte
4681    (set (match_dup 4) (match_dup 5))]
4682   "TARGET_ARM"
4683   "
4684   {
4685     rtx op1 = operands[1];
4686     rtx addr = XEXP (op1, 0);
4687     enum rtx_code code = GET_CODE (addr);
4688
4689     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4690         || code == MINUS)
4691       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4692
4693     operands[4] = adjust_address (op1, QImode, 1);
4694     operands[1] = adjust_address (operands[1], QImode, 0);
4695     operands[3] = gen_lowpart (QImode, operands[0]);
4696     operands[0] = gen_lowpart (SImode, operands[0]);
4697     operands[2] = gen_reg_rtx (SImode);
4698     operands[5] = gen_lowpart (QImode, operands[2]);
4699   }"
4700 )
4701
4702 (define_expand "storehi_bigend"
4703   [(set (match_dup 4) (match_dup 3))
4704    (set (match_dup 2)
4705         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4706    (set (match_operand 1 "" "") (match_dup 5))]
4707   "TARGET_ARM"
4708   "
4709   {
4710     rtx op1 = operands[1];
4711     rtx addr = XEXP (op1, 0);
4712     enum rtx_code code = GET_CODE (addr);
4713
4714     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4715         || code == MINUS)
4716       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4717
4718     operands[4] = adjust_address (op1, QImode, 1);
4719     operands[1] = adjust_address (operands[1], QImode, 0);
4720     operands[3] = gen_lowpart (QImode, operands[0]);
4721     operands[0] = gen_lowpart (SImode, operands[0]);
4722     operands[2] = gen_reg_rtx (SImode);
4723     operands[5] = gen_lowpart (QImode, operands[2]);
4724   }"
4725 )
4726
4727 ;; Subroutine to store a half word integer constant into memory.
4728 (define_expand "storeinthi"
4729   [(set (match_operand 0 "" "")
4730         (match_operand 1 "" ""))
4731    (set (match_dup 3) (match_dup 2))]
4732   "TARGET_ARM"
4733   "
4734   {
4735     HOST_WIDE_INT value = INTVAL (operands[1]);
4736     rtx addr = XEXP (operands[0], 0);
4737     rtx op0 = operands[0];
4738     enum rtx_code code = GET_CODE (addr);
4739
4740     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4741         || code == MINUS)
4742       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4743
4744     operands[1] = gen_reg_rtx (SImode);
4745     if (BYTES_BIG_ENDIAN)
4746       {
4747         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4748         if ((value & 255) == ((value >> 8) & 255))
4749           operands[2] = operands[1];
4750         else
4751           {
4752             operands[2] = gen_reg_rtx (SImode);
4753             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4754           }
4755       }
4756     else
4757       {
4758         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4759         if ((value & 255) == ((value >> 8) & 255))
4760           operands[2] = operands[1];
4761         else
4762           {
4763             operands[2] = gen_reg_rtx (SImode);
4764             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4765           }
4766       }
4767
4768     operands[3] = adjust_address (op0, QImode, 1);
4769     operands[0] = adjust_address (operands[0], QImode, 0);
4770     operands[2] = gen_lowpart (QImode, operands[2]);
4771     operands[1] = gen_lowpart (QImode, operands[1]);
4772   }"
4773 )
4774
4775 (define_expand "storehi_single_op"
4776   [(set (match_operand:HI 0 "memory_operand" "")
4777         (match_operand:HI 1 "general_operand" ""))]
4778   "TARGET_ARM && arm_arch4"
4779   "
4780   if (!s_register_operand (operands[1], HImode))
4781     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4782   "
4783 )
4784
4785 (define_expand "movhi"
4786   [(set (match_operand:HI 0 "general_operand" "")
4787         (match_operand:HI 1 "general_operand" ""))]
4788   "TARGET_EITHER"
4789   "
4790   if (TARGET_ARM)
4791     {
4792       if (!no_new_pseudos)
4793         {
4794           if (GET_CODE (operands[0]) == MEM)
4795             {
4796               if (arm_arch4)
4797                 {
4798                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4799                   DONE;
4800                 }
4801               if (GET_CODE (operands[1]) == CONST_INT)
4802                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4803               else
4804                 {
4805                   if (GET_CODE (operands[1]) == MEM)
4806                     operands[1] = force_reg (HImode, operands[1]);
4807                   if (BYTES_BIG_ENDIAN)
4808                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4809                   else
4810                    emit_insn (gen_storehi (operands[1], operands[0]));
4811                 }
4812               DONE;
4813             }
4814           /* Sign extend a constant, and keep it in an SImode reg.  */
4815           else if (GET_CODE (operands[1]) == CONST_INT)
4816             {
4817               rtx reg = gen_reg_rtx (SImode);
4818               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4819
4820               /* If the constant is already valid, leave it alone.  */
4821               if (!const_ok_for_arm (val))
4822                 {
4823                   /* If setting all the top bits will make the constant 
4824                      loadable in a single instruction, then set them.  
4825                      Otherwise, sign extend the number.  */
4826
4827                   if (const_ok_for_arm (~(val | ~0xffff)))
4828                     val |= ~0xffff;
4829                   else if (val & 0x8000)
4830                     val |= ~0xffff;
4831                 }
4832
4833               emit_insn (gen_movsi (reg, GEN_INT (val)));
4834               operands[1] = gen_lowpart (HImode, reg);
4835             }
4836           else if (arm_arch4 && optimize && !no_new_pseudos
4837                    && GET_CODE (operands[1]) == MEM)
4838             {
4839               rtx reg = gen_reg_rtx (SImode);
4840
4841               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4842               operands[1] = gen_lowpart (HImode, reg);
4843             }
4844           else if (!arm_arch4)
4845             {
4846               if (GET_CODE (operands[1]) == MEM)
4847                 {
4848                   rtx base;
4849                   rtx offset = const0_rtx;
4850                   rtx reg = gen_reg_rtx (SImode);
4851
4852                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4853                        || (GET_CODE (base) == PLUS
4854                            && (GET_CODE (offset = XEXP (base, 1))
4855                                == CONST_INT)
4856                            && ((INTVAL(offset) & 1) != 1)
4857                            && GET_CODE (base = XEXP (base, 0)) == REG))
4858                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4859                     {
4860                       rtx new;
4861
4862                       new = widen_memory_access (operands[1], SImode,
4863                                                  ((INTVAL (offset) & ~3)
4864                                                   - INTVAL (offset)));
4865                       emit_insn (gen_movsi (reg, new));
4866                       if (((INTVAL (offset) & 2) != 0)
4867                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4868                         {
4869                           rtx reg2 = gen_reg_rtx (SImode);
4870
4871                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4872                           reg = reg2;
4873                         }
4874                     }
4875                   else
4876                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4877
4878                   operands[1] = gen_lowpart (HImode, reg);
4879                }
4880            }
4881         }
4882       /* Handle loading a large integer during reload.  */
4883       else if (GET_CODE (operands[1]) == CONST_INT
4884                && !const_ok_for_arm (INTVAL (operands[1]))
4885                && !const_ok_for_arm (~INTVAL (operands[1])))
4886         {
4887           /* Writing a constant to memory needs a scratch, which should
4888              be handled with SECONDARY_RELOADs.  */
4889           gcc_assert (GET_CODE (operands[0]) == REG);
4890
4891           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4892           emit_insn (gen_movsi (operands[0], operands[1]));
4893           DONE;
4894        }
4895     }
4896   else /* TARGET_THUMB */
4897     {
4898       if (!no_new_pseudos)
4899         {
4900           if (GET_CODE (operands[1]) == CONST_INT)
4901             {
4902               rtx reg = gen_reg_rtx (SImode);
4903
4904               emit_insn (gen_movsi (reg, operands[1]));
4905               operands[1] = gen_lowpart (HImode, reg);
4906             }
4907
4908           /* ??? We shouldn't really get invalid addresses here, but this can
4909              happen if we are passed a SP (never OK for HImode/QImode) or 
4910              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4911              HImode/QImode) relative address.  */
4912           /* ??? This should perhaps be fixed elsewhere, for instance, in
4913              fixup_stack_1, by checking for other kinds of invalid addresses,
4914              e.g. a bare reference to a virtual register.  This may confuse the
4915              alpha though, which must handle this case differently.  */
4916           if (GET_CODE (operands[0]) == MEM
4917               && !memory_address_p (GET_MODE (operands[0]),
4918                                     XEXP (operands[0], 0)))
4919             operands[0]
4920               = replace_equiv_address (operands[0],
4921                                        copy_to_reg (XEXP (operands[0], 0)));
4922    
4923           if (GET_CODE (operands[1]) == MEM
4924               && !memory_address_p (GET_MODE (operands[1]),
4925                                     XEXP (operands[1], 0)))
4926             operands[1]
4927               = replace_equiv_address (operands[1],
4928                                        copy_to_reg (XEXP (operands[1], 0)));
4929
4930           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4931             {
4932               rtx reg = gen_reg_rtx (SImode);
4933
4934               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4935               operands[1] = gen_lowpart (HImode, reg);
4936             }
4937
4938           if (GET_CODE (operands[0]) == MEM)
4939             operands[1] = force_reg (HImode, operands[1]);
4940         }
4941       else if (GET_CODE (operands[1]) == CONST_INT
4942                 && !satisfies_constraint_I (operands[1]))
4943         {
4944           /* Handle loading a large integer during reload.  */
4945
4946           /* Writing a constant to memory needs a scratch, which should
4947              be handled with SECONDARY_RELOADs.  */
4948           gcc_assert (GET_CODE (operands[0]) == REG);
4949
4950           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4951           emit_insn (gen_movsi (operands[0], operands[1]));
4952           DONE;
4953         }
4954     }
4955   "
4956 )
4957
4958 (define_insn "*thumb_movhi_insn"
4959   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4960         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4961   "TARGET_THUMB
4962    && (   register_operand (operands[0], HImode)
4963        || register_operand (operands[1], HImode))"
4964   "*
4965   switch (which_alternative)
4966     {
4967     case 0: return \"add        %0, %1, #0\";
4968     case 2: return \"strh       %1, %0\";
4969     case 3: return \"mov        %0, %1\";
4970     case 4: return \"mov        %0, %1\";
4971     case 5: return \"mov        %0, %1\";
4972     default: gcc_unreachable ();
4973     case 1:
4974       /* The stack pointer can end up being taken as an index register.
4975           Catch this case here and deal with it.  */
4976       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4977           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4978           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4979         {
4980           rtx ops[2];
4981           ops[0] = operands[0];
4982           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4983       
4984           output_asm_insn (\"mov        %0, %1\", ops);
4985
4986           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4987     
4988         }
4989       return \"ldrh     %0, %1\";
4990     }"
4991   [(set_attr "length" "2,4,2,2,2,2")
4992    (set_attr "type" "*,load1,store1,*,*,*")]
4993 )
4994
4995
4996 (define_expand "movhi_bytes"
4997   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4998    (set (match_dup 3)
4999         (zero_extend:SI (match_dup 6)))
5000    (set (match_operand:SI 0 "" "")
5001          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5002   "TARGET_ARM"
5003   "
5004   {
5005     rtx mem1, mem2;
5006     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5007
5008     mem1 = change_address (operands[1], QImode, addr);
5009     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5010     operands[0] = gen_lowpart (SImode, operands[0]);
5011     operands[1] = mem1;
5012     operands[2] = gen_reg_rtx (SImode);
5013     operands[3] = gen_reg_rtx (SImode);
5014     operands[6] = mem2;
5015
5016     if (BYTES_BIG_ENDIAN)
5017       {
5018         operands[4] = operands[2];
5019         operands[5] = operands[3];
5020       }
5021     else
5022       {
5023         operands[4] = operands[3];
5024         operands[5] = operands[2];
5025       }
5026   }"
5027 )
5028
5029 (define_expand "movhi_bigend"
5030   [(set (match_dup 2)
5031         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5032                    (const_int 16)))
5033    (set (match_dup 3)
5034         (ashiftrt:SI (match_dup 2) (const_int 16)))
5035    (set (match_operand:HI 0 "s_register_operand" "")
5036         (match_dup 4))]
5037   "TARGET_ARM"
5038   "
5039   operands[2] = gen_reg_rtx (SImode);
5040   operands[3] = gen_reg_rtx (SImode);
5041   operands[4] = gen_lowpart (HImode, operands[3]);
5042   "
5043 )
5044
5045 ;; Pattern to recognize insn generated default case above
5046 (define_insn "*movhi_insn_arch4"
5047   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
5048         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5049   "TARGET_ARM
5050    && arm_arch4
5051    && (GET_CODE (operands[1]) != CONST_INT
5052        || const_ok_for_arm (INTVAL (operands[1]))
5053        || const_ok_for_arm (~INTVAL (operands[1])))"
5054   "@
5055    mov%?\\t%0, %1\\t%@ movhi
5056    mvn%?\\t%0, #%B1\\t%@ movhi
5057    str%?h\\t%1, %0\\t%@ movhi
5058    ldr%?h\\t%0, %1\\t%@ movhi"
5059   [(set_attr "type" "*,*,store1,load1")
5060    (set_attr "predicable" "yes")
5061    (set_attr "pool_range" "*,*,*,256")
5062    (set_attr "neg_pool_range" "*,*,*,244")]
5063 )
5064
5065 (define_insn "*movhi_bytes"
5066   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5067         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5068   "TARGET_ARM"
5069   "@
5070    mov%?\\t%0, %1\\t%@ movhi
5071    mvn%?\\t%0, #%B1\\t%@ movhi"
5072   [(set_attr "predicable" "yes")]
5073 )
5074
5075 (define_expand "thumb_movhi_clobber"
5076   [(set (match_operand:HI     0 "memory_operand"   "")
5077         (match_operand:HI     1 "register_operand" ""))
5078    (clobber (match_operand:DI 2 "register_operand" ""))]
5079   "TARGET_THUMB"
5080   "
5081   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5082       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5083     {
5084       emit_insn (gen_movhi (operands[0], operands[1]));
5085       DONE;
5086     }
5087   /* XXX Fixme, need to handle other cases here as well.  */
5088   gcc_unreachable ();
5089   "
5090 )
5091         
5092 ;; We use a DImode scratch because we may occasionally need an additional
5093 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5094 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5095 (define_expand "reload_outhi"
5096   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5097               (match_operand:HI 1 "s_register_operand"        "r")
5098               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5099   "TARGET_EITHER"
5100   "if (TARGET_ARM)
5101      arm_reload_out_hi (operands);
5102    else
5103      thumb_reload_out_hi (operands);
5104   DONE;
5105   "
5106 )
5107
5108 (define_expand "reload_inhi"
5109   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5110               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5111               (match_operand:DI 2 "s_register_operand" "=&r")])]
5112   "TARGET_EITHER"
5113   "
5114   if (TARGET_ARM)
5115     arm_reload_in_hi (operands);
5116   else
5117     thumb_reload_out_hi (operands);
5118   DONE;
5119 ")
5120
5121 (define_expand "movqi"
5122   [(set (match_operand:QI 0 "general_operand" "")
5123         (match_operand:QI 1 "general_operand" ""))]
5124   "TARGET_EITHER"
5125   "
5126   /* Everything except mem = const or mem = mem can be done easily */
5127
5128   if (!no_new_pseudos)
5129     {
5130       if (GET_CODE (operands[1]) == CONST_INT)
5131         {
5132           rtx reg = gen_reg_rtx (SImode);
5133
5134           emit_insn (gen_movsi (reg, operands[1]));
5135           operands[1] = gen_lowpart (QImode, reg);
5136         }
5137
5138       if (TARGET_THUMB)
5139         {
5140           /* ??? We shouldn't really get invalid addresses here, but this can
5141              happen if we are passed a SP (never OK for HImode/QImode) or
5142              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5143              HImode/QImode) relative address.  */
5144           /* ??? This should perhaps be fixed elsewhere, for instance, in
5145              fixup_stack_1, by checking for other kinds of invalid addresses,
5146              e.g. a bare reference to a virtual register.  This may confuse the
5147              alpha though, which must handle this case differently.  */
5148           if (GET_CODE (operands[0]) == MEM
5149               && !memory_address_p (GET_MODE (operands[0]),
5150                                      XEXP (operands[0], 0)))
5151             operands[0]
5152               = replace_equiv_address (operands[0],
5153                                        copy_to_reg (XEXP (operands[0], 0)));
5154           if (GET_CODE (operands[1]) == MEM
5155               && !memory_address_p (GET_MODE (operands[1]),
5156                                     XEXP (operands[1], 0)))
5157              operands[1]
5158                = replace_equiv_address (operands[1],
5159                                         copy_to_reg (XEXP (operands[1], 0)));
5160         }
5161
5162       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5163         {
5164           rtx reg = gen_reg_rtx (SImode);
5165
5166           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5167           operands[1] = gen_lowpart (QImode, reg);
5168         }
5169
5170       if (GET_CODE (operands[0]) == MEM)
5171         operands[1] = force_reg (QImode, operands[1]);
5172     }
5173   else if (TARGET_THUMB
5174            && GET_CODE (operands[1]) == CONST_INT
5175            && !satisfies_constraint_I (operands[1]))
5176     {
5177       /* Handle loading a large integer during reload.  */
5178
5179       /* Writing a constant to memory needs a scratch, which should
5180          be handled with SECONDARY_RELOADs.  */
5181       gcc_assert (GET_CODE (operands[0]) == REG);
5182
5183       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5184       emit_insn (gen_movsi (operands[0], operands[1]));
5185       DONE;
5186     }
5187   "
5188 )
5189
5190
5191 (define_insn "*arm_movqi_insn"
5192   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5193         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5194   "TARGET_ARM
5195    && (   register_operand (operands[0], QImode)
5196        || register_operand (operands[1], QImode))"
5197   "@
5198    mov%?\\t%0, %1
5199    mvn%?\\t%0, #%B1
5200    ldr%?b\\t%0, %1
5201    str%?b\\t%1, %0"
5202   [(set_attr "type" "*,*,load1,store1")
5203    (set_attr "predicable" "yes")]
5204 )
5205
5206 (define_insn "*thumb_movqi_insn"
5207   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5208         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5209   "TARGET_THUMB
5210    && (   register_operand (operands[0], QImode)
5211        || register_operand (operands[1], QImode))"
5212   "@
5213    add\\t%0, %1, #0
5214    ldrb\\t%0, %1
5215    strb\\t%1, %0
5216    mov\\t%0, %1
5217    mov\\t%0, %1
5218    mov\\t%0, %1"
5219   [(set_attr "length" "2")
5220    (set_attr "type" "*,load1,store1,*,*,*")
5221    (set_attr "pool_range" "*,32,*,*,*,*")]
5222 )
5223
5224 (define_expand "movsf"
5225   [(set (match_operand:SF 0 "general_operand" "")
5226         (match_operand:SF 1 "general_operand" ""))]
5227   "TARGET_EITHER"
5228   "
5229   if (TARGET_ARM)
5230     {
5231       if (GET_CODE (operands[0]) == MEM)
5232         operands[1] = force_reg (SFmode, operands[1]);
5233     }
5234   else /* TARGET_THUMB */
5235     {
5236       if (!no_new_pseudos)
5237         {
5238            if (GET_CODE (operands[0]) != REG)
5239              operands[1] = force_reg (SFmode, operands[1]);
5240         }
5241     }
5242   "
5243 )
5244
5245 ;; Transform a floating-point move of a constant into a core register into
5246 ;; an SImode operation.
5247 (define_split
5248   [(set (match_operand:SF 0 "arm_general_register_operand" "")
5249         (match_operand:SF 1 "immediate_operand" ""))]
5250   "TARGET_ARM
5251    && reload_completed
5252    && GET_CODE (operands[1]) == CONST_DOUBLE"
5253   [(set (match_dup 2) (match_dup 3))]
5254   "
5255   operands[2] = gen_lowpart (SImode, operands[0]);
5256   operands[3] = gen_lowpart (SImode, operands[1]);
5257   if (operands[2] == 0 || operands[3] == 0)
5258     FAIL;
5259   "
5260 )
5261
5262 (define_insn "*arm_movsf_soft_insn"
5263   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5264         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5265   "TARGET_ARM
5266    && TARGET_SOFT_FLOAT
5267    && (GET_CODE (operands[0]) != MEM
5268        || register_operand (operands[1], SFmode))"
5269   "@
5270    mov%?\\t%0, %1
5271    ldr%?\\t%0, %1\\t%@ float
5272    str%?\\t%1, %0\\t%@ float"
5273   [(set_attr "length" "4,4,4")
5274    (set_attr "predicable" "yes")
5275    (set_attr "type" "*,load1,store1")
5276    (set_attr "pool_range" "*,4096,*")
5277    (set_attr "neg_pool_range" "*,4084,*")]
5278 )
5279
5280 ;;; ??? This should have alternatives for constants.
5281 (define_insn "*thumb_movsf_insn"
5282   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5283         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5284   "TARGET_THUMB
5285    && (   register_operand (operands[0], SFmode) 
5286        || register_operand (operands[1], SFmode))"
5287   "@
5288    add\\t%0, %1, #0
5289    ldmia\\t%1, {%0}
5290    stmia\\t%0, {%1}
5291    ldr\\t%0, %1
5292    str\\t%1, %0
5293    mov\\t%0, %1
5294    mov\\t%0, %1"
5295   [(set_attr "length" "2")
5296    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5297    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5298 )
5299
5300 (define_expand "movdf"
5301   [(set (match_operand:DF 0 "general_operand" "")
5302         (match_operand:DF 1 "general_operand" ""))]
5303   "TARGET_EITHER"
5304   "
5305   if (TARGET_ARM)
5306     {
5307       if (GET_CODE (operands[0]) == MEM)
5308         operands[1] = force_reg (DFmode, operands[1]);
5309     }
5310   else /* TARGET_THUMB */
5311     {
5312       if (!no_new_pseudos)
5313         {
5314           if (GET_CODE (operands[0]) != REG)
5315             operands[1] = force_reg (DFmode, operands[1]);
5316         }
5317     }
5318   "
5319 )
5320
5321 ;; Reloading a df mode value stored in integer regs to memory can require a
5322 ;; scratch reg.
5323 (define_expand "reload_outdf"
5324   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5325    (match_operand:DF 1 "s_register_operand" "r")
5326    (match_operand:SI 2 "s_register_operand" "=&r")]
5327   "TARGET_ARM"
5328   "
5329   {
5330     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5331
5332     if (code == REG)
5333       operands[2] = XEXP (operands[0], 0);
5334     else if (code == POST_INC || code == PRE_DEC)
5335       {
5336         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5337         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5338         emit_insn (gen_movdi (operands[0], operands[1]));
5339         DONE;
5340       }
5341     else if (code == PRE_INC)
5342       {
5343         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5344
5345         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5346         operands[2] = reg;
5347       }
5348     else if (code == POST_DEC)
5349       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5350     else
5351       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5352                              XEXP (XEXP (operands[0], 0), 1)));
5353
5354     emit_insn (gen_rtx_SET (VOIDmode,
5355                             replace_equiv_address (operands[0], operands[2]),
5356                             operands[1]));
5357
5358     if (code == POST_DEC)
5359       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5360
5361     DONE;
5362   }"
5363 )
5364
5365 (define_insn "*movdf_soft_insn"
5366   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5367         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5368   "TARGET_ARM && TARGET_SOFT_FLOAT
5369    && (   register_operand (operands[0], DFmode)
5370        || register_operand (operands[1], DFmode))"
5371   "*
5372   switch (which_alternative)
5373     {
5374     case 0:
5375     case 1:
5376     case 2:
5377       return \"#\";
5378     default:
5379       return output_move_double (operands);
5380     }
5381   "
5382   [(set_attr "length" "8,12,16,8,8")
5383    (set_attr "type" "*,*,*,load2,store2")
5384    (set_attr "pool_range" "1020")
5385    (set_attr "neg_pool_range" "1008")]
5386 )
5387
5388 ;;; ??? This should have alternatives for constants.
5389 ;;; ??? This was originally identical to the movdi_insn pattern.
5390 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5391 ;;; thumb_reorg with a memory reference.
5392 (define_insn "*thumb_movdf_insn"
5393   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5394         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5395   "TARGET_THUMB
5396    && (   register_operand (operands[0], DFmode)
5397        || register_operand (operands[1], DFmode))"
5398   "*
5399   switch (which_alternative)
5400     {
5401     default:
5402     case 0:
5403       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5404         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5405       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5406     case 1:
5407       return \"ldmia\\t%1, {%0, %H0}\";
5408     case 2:
5409       return \"stmia\\t%0, {%1, %H1}\";
5410     case 3:
5411       return thumb_load_double_from_address (operands);
5412     case 4:
5413       operands[2] = gen_rtx_MEM (SImode,
5414                                  plus_constant (XEXP (operands[0], 0), 4));
5415       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5416       return \"\";
5417     case 5:
5418       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5419         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5420       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5421     }
5422   "
5423   [(set_attr "length" "4,2,2,6,4,4")
5424    (set_attr "type" "*,load2,store2,load2,store2,*")
5425    (set_attr "pool_range" "*,*,*,1020,*,*")]
5426 )
5427
5428 (define_expand "movxf"
5429   [(set (match_operand:XF 0 "general_operand" "")
5430         (match_operand:XF 1 "general_operand" ""))]
5431   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5432   "
5433   if (GET_CODE (operands[0]) == MEM)
5434     operands[1] = force_reg (XFmode, operands[1]);
5435   "
5436 )
5437
5438 ;; Vector Moves
5439 (define_expand "movv2si"
5440   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5441         (match_operand:V2SI 1 "general_operand" ""))]
5442   "TARGET_REALLY_IWMMXT"
5443 {
5444 })
5445
5446 (define_expand "movv4hi"
5447   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5448         (match_operand:V4HI 1 "general_operand" ""))]
5449   "TARGET_REALLY_IWMMXT"
5450 {
5451 })
5452
5453 (define_expand "movv8qi"
5454   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5455         (match_operand:V8QI 1 "general_operand" ""))]
5456   "TARGET_REALLY_IWMMXT"
5457 {
5458 })
5459 \f
5460
5461 ;; load- and store-multiple insns
5462 ;; The arm can load/store any set of registers, provided that they are in
5463 ;; ascending order; but that is beyond GCC so stick with what it knows.
5464
5465 (define_expand "load_multiple"
5466   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5467                           (match_operand:SI 1 "" ""))
5468                      (use (match_operand:SI 2 "" ""))])]
5469   "TARGET_ARM"
5470 {
5471   HOST_WIDE_INT offset = 0;
5472
5473   /* Support only fixed point registers.  */
5474   if (GET_CODE (operands[2]) != CONST_INT
5475       || INTVAL (operands[2]) > 14
5476       || INTVAL (operands[2]) < 2
5477       || GET_CODE (operands[1]) != MEM
5478       || GET_CODE (operands[0]) != REG
5479       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5480       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5481     FAIL;
5482
5483   operands[3]
5484     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5485                              force_reg (SImode, XEXP (operands[1], 0)),
5486                              TRUE, FALSE, operands[1], &offset);
5487 })
5488
5489 ;; Load multiple with write-back
5490
5491 (define_insn "*ldmsi_postinc4"
5492   [(match_parallel 0 "load_multiple_operation"
5493     [(set (match_operand:SI 1 "s_register_operand" "=r")
5494           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5495                    (const_int 16)))
5496      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5497           (mem:SI (match_dup 2)))
5498      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5499           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5500      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5501           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5502      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5503           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5504   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5505   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5506   [(set_attr "type" "load4")
5507    (set_attr "predicable" "yes")]
5508 )
5509
5510 (define_insn "*ldmsi_postinc4_thumb"
5511   [(match_parallel 0 "load_multiple_operation"
5512     [(set (match_operand:SI 1 "s_register_operand" "=l")
5513           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5514                    (const_int 16)))
5515      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5516           (mem:SI (match_dup 2)))
5517      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5518           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5519      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5520           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5521      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5522           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5523   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5524   "ldmia\\t%1!, {%3, %4, %5, %6}"
5525   [(set_attr "type" "load4")]
5526 )
5527
5528 (define_insn "*ldmsi_postinc3"
5529   [(match_parallel 0 "load_multiple_operation"
5530     [(set (match_operand:SI 1 "s_register_operand" "=r")
5531           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5532                    (const_int 12)))
5533      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5534           (mem:SI (match_dup 2)))
5535      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5536           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5537      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5538           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5539   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5540   "ldm%?ia\\t%1!, {%3, %4, %5}"
5541   [(set_attr "type" "load3")
5542    (set_attr "predicable" "yes")]
5543 )
5544
5545 (define_insn "*ldmsi_postinc2"
5546   [(match_parallel 0 "load_multiple_operation"
5547     [(set (match_operand:SI 1 "s_register_operand" "=r")
5548           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5549                    (const_int 8)))
5550      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5551           (mem:SI (match_dup 2)))
5552      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5553           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5554   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5555   "ldm%?ia\\t%1!, {%3, %4}"
5556   [(set_attr "type" "load2")
5557    (set_attr "predicable" "yes")]
5558 )
5559
5560 ;; Ordinary load multiple
5561
5562 (define_insn "*ldmsi4"
5563   [(match_parallel 0 "load_multiple_operation"
5564     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5565           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5566      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5567           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5568      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5569           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5570      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5571           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5572   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5573   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5574   [(set_attr "type" "load4")
5575    (set_attr "predicable" "yes")]
5576 )
5577
5578 (define_insn "*ldmsi3"
5579   [(match_parallel 0 "load_multiple_operation"
5580     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5581           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5582      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5583           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5584      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5585           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5586   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5587   "ldm%?ia\\t%1, {%2, %3, %4}"
5588   [(set_attr "type" "load3")
5589    (set_attr "predicable" "yes")]
5590 )
5591
5592 (define_insn "*ldmsi2"
5593   [(match_parallel 0 "load_multiple_operation"
5594     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5595           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5596      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5597           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5598   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5599   "ldm%?ia\\t%1, {%2, %3}"
5600   [(set_attr "type" "load2")
5601    (set_attr "predicable" "yes")]
5602 )
5603
5604 (define_expand "store_multiple"
5605   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5606                           (match_operand:SI 1 "" ""))
5607                      (use (match_operand:SI 2 "" ""))])]
5608   "TARGET_ARM"
5609 {
5610   HOST_WIDE_INT offset = 0;
5611
5612   /* Support only fixed point registers.  */
5613   if (GET_CODE (operands[2]) != CONST_INT
5614       || INTVAL (operands[2]) > 14
5615       || INTVAL (operands[2]) < 2
5616       || GET_CODE (operands[1]) != REG
5617       || GET_CODE (operands[0]) != MEM
5618       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5619       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5620     FAIL;
5621
5622   operands[3]
5623     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5624                               force_reg (SImode, XEXP (operands[0], 0)),
5625                               TRUE, FALSE, operands[0], &offset);
5626 })
5627
5628 ;; Store multiple with write-back
5629
5630 (define_insn "*stmsi_postinc4"
5631   [(match_parallel 0 "store_multiple_operation"
5632     [(set (match_operand:SI 1 "s_register_operand" "=r")
5633           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5634                    (const_int 16)))
5635      (set (mem:SI (match_dup 2))
5636           (match_operand:SI 3 "arm_hard_register_operand" ""))
5637      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5638           (match_operand:SI 4 "arm_hard_register_operand" ""))
5639      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5640           (match_operand:SI 5 "arm_hard_register_operand" ""))
5641      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5642           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5643   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5644   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5645   [(set_attr "predicable" "yes")
5646    (set_attr "type" "store4")]
5647 )
5648
5649 (define_insn "*stmsi_postinc4_thumb"
5650   [(match_parallel 0 "store_multiple_operation"
5651     [(set (match_operand:SI 1 "s_register_operand" "=l")
5652           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5653                    (const_int 16)))
5654      (set (mem:SI (match_dup 2))
5655           (match_operand:SI 3 "arm_hard_register_operand" ""))
5656      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5657           (match_operand:SI 4 "arm_hard_register_operand" ""))
5658      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5659           (match_operand:SI 5 "arm_hard_register_operand" ""))
5660      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5661           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5662   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5663   "stmia\\t%1!, {%3, %4, %5, %6}"
5664   [(set_attr "type" "store4")]
5665 )
5666
5667 (define_insn "*stmsi_postinc3"
5668   [(match_parallel 0 "store_multiple_operation"
5669     [(set (match_operand:SI 1 "s_register_operand" "=r")
5670           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5671                    (const_int 12)))
5672      (set (mem:SI (match_dup 2))
5673           (match_operand:SI 3 "arm_hard_register_operand" ""))
5674      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5675           (match_operand:SI 4 "arm_hard_register_operand" ""))
5676      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5677           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5678   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5679   "stm%?ia\\t%1!, {%3, %4, %5}"
5680   [(set_attr "predicable" "yes")
5681    (set_attr "type" "store3")]
5682 )
5683
5684 (define_insn "*stmsi_postinc2"
5685   [(match_parallel 0 "store_multiple_operation"
5686     [(set (match_operand:SI 1 "s_register_operand" "=r")
5687           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5688                    (const_int 8)))
5689      (set (mem:SI (match_dup 2))
5690           (match_operand:SI 3 "arm_hard_register_operand" ""))
5691      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5692           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5693   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5694   "stm%?ia\\t%1!, {%3, %4}"
5695   [(set_attr "predicable" "yes")
5696    (set_attr "type" "store2")]
5697 )
5698
5699 ;; Ordinary store multiple
5700
5701 (define_insn "*stmsi4"
5702   [(match_parallel 0 "store_multiple_operation"
5703     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5704           (match_operand:SI 2 "arm_hard_register_operand" ""))
5705      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5706           (match_operand:SI 3 "arm_hard_register_operand" ""))
5707      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5708           (match_operand:SI 4 "arm_hard_register_operand" ""))
5709      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5710           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5711   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5712   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5713   [(set_attr "predicable" "yes")
5714    (set_attr "type" "store4")]
5715 )
5716
5717 (define_insn "*stmsi3"
5718   [(match_parallel 0 "store_multiple_operation"
5719     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5720           (match_operand:SI 2 "arm_hard_register_operand" ""))
5721      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5722           (match_operand:SI 3 "arm_hard_register_operand" ""))
5723      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5724           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5725   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5726   "stm%?ia\\t%1, {%2, %3, %4}"
5727   [(set_attr "predicable" "yes")
5728    (set_attr "type" "store3")]
5729 )
5730
5731 (define_insn "*stmsi2"
5732   [(match_parallel 0 "store_multiple_operation"
5733     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5734           (match_operand:SI 2 "arm_hard_register_operand" ""))
5735      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5736           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5737   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5738   "stm%?ia\\t%1, {%2, %3}"
5739   [(set_attr "predicable" "yes")
5740    (set_attr "type" "store2")]
5741 )
5742
5743 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5744 ;; We could let this apply for blocks of less than this, but it clobbers so
5745 ;; many registers that there is then probably a better way.
5746
5747 (define_expand "movmemqi"
5748   [(match_operand:BLK 0 "general_operand" "")
5749    (match_operand:BLK 1 "general_operand" "")
5750    (match_operand:SI 2 "const_int_operand" "")
5751    (match_operand:SI 3 "const_int_operand" "")]
5752   "TARGET_EITHER"
5753   "
5754   if (TARGET_ARM)
5755     {
5756       if (arm_gen_movmemqi (operands))
5757         DONE;
5758       FAIL;
5759     }
5760   else /* TARGET_THUMB */
5761     {
5762       if (   INTVAL (operands[3]) != 4
5763           || INTVAL (operands[2]) > 48)
5764         FAIL;
5765
5766       thumb_expand_movmemqi (operands);
5767       DONE;
5768     }
5769   "
5770 )
5771
5772 ;; Thumb block-move insns
5773
5774 (define_insn "movmem12b"
5775   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5776         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5777    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5778         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5779    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5780         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5781    (set (match_operand:SI 0 "register_operand" "=l")
5782         (plus:SI (match_dup 2) (const_int 12)))
5783    (set (match_operand:SI 1 "register_operand" "=l")
5784         (plus:SI (match_dup 3) (const_int 12)))
5785    (clobber (match_scratch:SI 4 "=&l"))
5786    (clobber (match_scratch:SI 5 "=&l"))
5787    (clobber (match_scratch:SI 6 "=&l"))]
5788   "TARGET_THUMB"
5789   "* return thumb_output_move_mem_multiple (3, operands);"
5790   [(set_attr "length" "4")
5791    ; This isn't entirely accurate...  It loads as well, but in terms of
5792    ; scheduling the following insn it is better to consider it as a store
5793    (set_attr "type" "store3")]
5794 )
5795
5796 (define_insn "movmem8b"
5797   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5798         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5799    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5800         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5801    (set (match_operand:SI 0 "register_operand" "=l")
5802         (plus:SI (match_dup 2) (const_int 8)))
5803    (set (match_operand:SI 1 "register_operand" "=l")
5804         (plus:SI (match_dup 3) (const_int 8)))
5805    (clobber (match_scratch:SI 4 "=&l"))
5806    (clobber (match_scratch:SI 5 "=&l"))]
5807   "TARGET_THUMB"
5808   "* return thumb_output_move_mem_multiple (2, operands);"
5809   [(set_attr "length" "4")
5810    ; This isn't entirely accurate...  It loads as well, but in terms of
5811    ; scheduling the following insn it is better to consider it as a store
5812    (set_attr "type" "store2")]
5813 )
5814
5815 \f
5816
5817 ;; Compare & branch insns
5818 ;; The range calculations are based as follows:
5819 ;; For forward branches, the address calculation returns the address of
5820 ;; the next instruction.  This is 2 beyond the branch instruction.
5821 ;; For backward branches, the address calculation returns the address of
5822 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5823 ;; instruction for the shortest sequence, and 4 before the branch instruction
5824 ;; if we have to jump around an unconditional branch.
5825 ;; To the basic branch range the PC offset must be added (this is +4).
5826 ;; So for forward branches we have 
5827 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5828 ;; And for backward branches we have 
5829 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5830 ;;
5831 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5832 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5833
5834 (define_expand "cbranchsi4"
5835   [(set (pc) (if_then_else
5836               (match_operator 0 "arm_comparison_operator"
5837                [(match_operand:SI 1 "s_register_operand" "")
5838                 (match_operand:SI 2 "nonmemory_operand" "")])
5839               (label_ref (match_operand 3 "" ""))
5840               (pc)))]
5841   "TARGET_THUMB"
5842   "
5843   if (thumb_cmpneg_operand (operands[2], SImode))
5844     {
5845       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5846                                               operands[3], operands[0]));
5847       DONE;
5848     }
5849   if (!thumb_cmp_operand (operands[2], SImode))
5850     operands[2] = force_reg (SImode, operands[2]);
5851   ")
5852
5853 (define_insn "*cbranchsi4_insn"
5854   [(set (pc) (if_then_else
5855               (match_operator 0 "arm_comparison_operator"
5856                [(match_operand:SI 1 "s_register_operand" "l,*h")
5857                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5858               (label_ref (match_operand 3 "" ""))
5859               (pc)))]
5860   "TARGET_THUMB"
5861   "*
5862   output_asm_insn (\"cmp\\t%1, %2\", operands);
5863
5864   switch (get_attr_length (insn))
5865     {
5866     case 4:  return \"b%d0\\t%l3\";
5867     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5868     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5869     }
5870   "
5871   [(set (attr "far_jump")
5872         (if_then_else
5873             (eq_attr "length" "8")
5874             (const_string "yes")
5875             (const_string "no")))
5876    (set (attr "length") 
5877         (if_then_else
5878             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5879                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5880             (const_int 4)
5881             (if_then_else
5882                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5883                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5884                 (const_int 6)
5885                 (const_int 8))))]
5886 )
5887
5888 (define_insn "cbranchsi4_scratch"
5889   [(set (pc) (if_then_else
5890               (match_operator 4 "arm_comparison_operator"
5891                [(match_operand:SI 1 "s_register_operand" "l,0")
5892                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5893               (label_ref (match_operand 3 "" ""))
5894               (pc)))
5895    (clobber (match_scratch:SI 0 "=l,l"))]
5896   "TARGET_THUMB"
5897   "*
5898   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5899
5900   switch (get_attr_length (insn))
5901     {
5902     case 4:  return \"b%d4\\t%l3\";
5903     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5904     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5905     }
5906   "
5907   [(set (attr "far_jump")
5908         (if_then_else
5909             (eq_attr "length" "8")
5910             (const_string "yes")
5911             (const_string "no")))
5912    (set (attr "length") 
5913         (if_then_else
5914             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5915                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5916             (const_int 4)
5917             (if_then_else
5918                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5919                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5920                 (const_int 6)
5921                 (const_int 8))))]
5922 )
5923 (define_insn "*movsi_cbranchsi4"
5924   [(set (pc)
5925         (if_then_else
5926          (match_operator 3 "arm_comparison_operator"
5927           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5928            (const_int 0)])
5929          (label_ref (match_operand 2 "" ""))
5930          (pc)))
5931    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5932         (match_dup 1))]
5933   "TARGET_THUMB"
5934   "*{
5935   if (which_alternative == 0)
5936     output_asm_insn (\"cmp\t%0, #0\", operands);
5937   else if (which_alternative == 1)
5938     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5939   else
5940     {
5941       output_asm_insn (\"cmp\t%1, #0\", operands);
5942       if (which_alternative == 2)
5943         output_asm_insn (\"mov\t%0, %1\", operands);
5944       else
5945         output_asm_insn (\"str\t%1, %0\", operands);
5946     }
5947   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5948     {
5949     case 4:  return \"b%d3\\t%l2\";
5950     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5951     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5952     }
5953   }"
5954   [(set (attr "far_jump")
5955         (if_then_else
5956             (ior (and (gt (symbol_ref ("which_alternative"))
5957                           (const_int 1))
5958                       (eq_attr "length" "8"))
5959                  (eq_attr "length" "10"))
5960             (const_string "yes")
5961             (const_string "no")))
5962    (set (attr "length")
5963      (if_then_else
5964        (le (symbol_ref ("which_alternative"))
5965                        (const_int 1))
5966        (if_then_else
5967          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5968               (le (minus (match_dup 2) (pc)) (const_int 256)))
5969          (const_int 4)
5970          (if_then_else
5971            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5972                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5973            (const_int 6)
5974            (const_int 8)))
5975        (if_then_else
5976          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5977               (le (minus (match_dup 2) (pc)) (const_int 256)))
5978          (const_int 6)
5979          (if_then_else
5980            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5981                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5982            (const_int 8)
5983            (const_int 10)))))]
5984 )
5985
5986 (define_insn "*negated_cbranchsi4"
5987   [(set (pc)
5988         (if_then_else
5989          (match_operator 0 "equality_operator"
5990           [(match_operand:SI 1 "s_register_operand" "l")
5991            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5992          (label_ref (match_operand 3 "" ""))
5993          (pc)))]
5994   "TARGET_THUMB"
5995   "*
5996   output_asm_insn (\"cmn\\t%1, %2\", operands);
5997   switch (get_attr_length (insn))
5998     {
5999     case 4:  return \"b%d0\\t%l3\";
6000     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6001     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6002     }
6003   "
6004   [(set (attr "far_jump")
6005         (if_then_else
6006             (eq_attr "length" "8")
6007             (const_string "yes")
6008             (const_string "no")))
6009    (set (attr "length") 
6010         (if_then_else
6011             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6012                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6013             (const_int 4)
6014             (if_then_else
6015                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6016                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6017                 (const_int 6)
6018                 (const_int 8))))]
6019 )
6020
6021 (define_insn "*tbit_cbranch"
6022   [(set (pc)
6023         (if_then_else
6024          (match_operator 0 "equality_operator"
6025           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6026                             (const_int 1)
6027                             (match_operand:SI 2 "const_int_operand" "i"))
6028            (const_int 0)])
6029          (label_ref (match_operand 3 "" ""))
6030          (pc)))
6031    (clobber (match_scratch:SI 4 "=l"))]
6032   "TARGET_THUMB"
6033   "*
6034   {
6035   rtx op[3];
6036   op[0] = operands[4];
6037   op[1] = operands[1];
6038   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6039
6040   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6041   switch (get_attr_length (insn))
6042     {
6043     case 4:  return \"b%d0\\t%l3\";
6044     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6045     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6046     }
6047   }"
6048   [(set (attr "far_jump")
6049         (if_then_else
6050             (eq_attr "length" "8")
6051             (const_string "yes")
6052             (const_string "no")))
6053    (set (attr "length") 
6054         (if_then_else
6055             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6056                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6057             (const_int 4)
6058             (if_then_else
6059                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6060                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6061                 (const_int 6)
6062                 (const_int 8))))]
6063 )
6064   
6065 (define_insn "*tlobits_cbranch"
6066   [(set (pc)
6067         (if_then_else
6068          (match_operator 0 "equality_operator"
6069           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6070                             (match_operand:SI 2 "const_int_operand" "i")
6071                             (const_int 0))
6072            (const_int 0)])
6073          (label_ref (match_operand 3 "" ""))
6074          (pc)))
6075    (clobber (match_scratch:SI 4 "=l"))]
6076   "TARGET_THUMB"
6077   "*
6078   {
6079   rtx op[3];
6080   op[0] = operands[4];
6081   op[1] = operands[1];
6082   op[2] = GEN_INT (32 - INTVAL (operands[2]));
6083
6084   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6085   switch (get_attr_length (insn))
6086     {
6087     case 4:  return \"b%d0\\t%l3\";
6088     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6089     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6090     }
6091   }"
6092   [(set (attr "far_jump")
6093         (if_then_else
6094             (eq_attr "length" "8")
6095             (const_string "yes")
6096             (const_string "no")))
6097    (set (attr "length") 
6098         (if_then_else
6099             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6100                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6101             (const_int 4)
6102             (if_then_else
6103                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6104                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6105                 (const_int 6)
6106                 (const_int 8))))]
6107 )
6108   
6109 (define_insn "*tstsi3_cbranch"
6110   [(set (pc)
6111         (if_then_else
6112          (match_operator 3 "equality_operator"
6113           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6114                    (match_operand:SI 1 "s_register_operand" "l"))
6115            (const_int 0)])
6116          (label_ref (match_operand 2 "" ""))
6117          (pc)))]
6118   "TARGET_THUMB"
6119   "*
6120   {
6121   output_asm_insn (\"tst\\t%0, %1\", operands);
6122   switch (get_attr_length (insn))
6123     {
6124     case 4:  return \"b%d3\\t%l2\";
6125     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6126     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6127     }
6128   }"
6129   [(set (attr "far_jump")
6130         (if_then_else
6131             (eq_attr "length" "8")
6132             (const_string "yes")
6133             (const_string "no")))
6134    (set (attr "length") 
6135         (if_then_else
6136             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6137                  (le (minus (match_dup 2) (pc)) (const_int 256)))
6138             (const_int 4)
6139             (if_then_else
6140                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6141                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6142                 (const_int 6)
6143                 (const_int 8))))]
6144 )
6145   
6146 (define_insn "*andsi3_cbranch"
6147   [(set (pc)
6148         (if_then_else
6149          (match_operator 5 "equality_operator"
6150           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6151                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6152            (const_int 0)])
6153          (label_ref (match_operand 4 "" ""))
6154          (pc)))
6155    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6156         (and:SI (match_dup 2) (match_dup 3)))
6157    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6158   "TARGET_THUMB"
6159   "*
6160   {
6161   if (which_alternative == 0)
6162     output_asm_insn (\"and\\t%0, %3\", operands);
6163   else if (which_alternative == 1)
6164     {
6165       output_asm_insn (\"and\\t%1, %3\", operands);
6166       output_asm_insn (\"mov\\t%0, %1\", operands);
6167     }
6168   else
6169     {
6170       output_asm_insn (\"and\\t%1, %3\", operands);
6171       output_asm_insn (\"str\\t%1, %0\", operands);
6172     }
6173
6174   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6175     {
6176     case 4:  return \"b%d5\\t%l4\";
6177     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6178     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6179     }
6180   }"
6181   [(set (attr "far_jump")
6182         (if_then_else
6183             (ior (and (eq (symbol_ref ("which_alternative"))
6184                           (const_int 0))
6185                       (eq_attr "length" "8"))
6186                  (eq_attr "length" "10"))
6187             (const_string "yes")
6188             (const_string "no")))
6189    (set (attr "length")
6190      (if_then_else
6191        (eq (symbol_ref ("which_alternative"))
6192                        (const_int 0))
6193        (if_then_else
6194          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6195               (le (minus (match_dup 4) (pc)) (const_int 256)))
6196          (const_int 4)
6197          (if_then_else
6198            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6199                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6200            (const_int 6)
6201            (const_int 8)))
6202        (if_then_else
6203          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6204               (le (minus (match_dup 4) (pc)) (const_int 256)))
6205          (const_int 6)
6206          (if_then_else
6207            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6208                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6209            (const_int 8)
6210            (const_int 10)))))]
6211 )
6212
6213 (define_insn "*orrsi3_cbranch_scratch"
6214   [(set (pc)
6215         (if_then_else
6216          (match_operator 4 "equality_operator"
6217           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6218                    (match_operand:SI 2 "s_register_operand" "l"))
6219            (const_int 0)])
6220          (label_ref (match_operand 3 "" ""))
6221          (pc)))
6222    (clobber (match_scratch:SI 0 "=l"))]
6223   "TARGET_THUMB"
6224   "*
6225   {
6226   output_asm_insn (\"orr\\t%0, %2\", operands);
6227   switch (get_attr_length (insn))
6228     {
6229     case 4:  return \"b%d4\\t%l3\";
6230     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6231     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6232     }
6233   }"
6234   [(set (attr "far_jump")
6235         (if_then_else
6236             (eq_attr "length" "8")
6237             (const_string "yes")
6238             (const_string "no")))
6239    (set (attr "length") 
6240         (if_then_else
6241             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6242                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6243             (const_int 4)
6244             (if_then_else
6245                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6246                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6247                 (const_int 6)
6248                 (const_int 8))))]
6249 )
6250   
6251 (define_insn "*orrsi3_cbranch"
6252   [(set (pc)
6253         (if_then_else
6254          (match_operator 5 "equality_operator"
6255           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6256                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6257            (const_int 0)])
6258          (label_ref (match_operand 4 "" ""))
6259          (pc)))
6260    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6261         (ior:SI (match_dup 2) (match_dup 3)))
6262    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6263   "TARGET_THUMB"
6264   "*
6265   {
6266   if (which_alternative == 0)
6267     output_asm_insn (\"orr\\t%0, %3\", operands);
6268   else if (which_alternative == 1)
6269     {
6270       output_asm_insn (\"orr\\t%1, %3\", operands);
6271       output_asm_insn (\"mov\\t%0, %1\", operands);
6272     }
6273   else
6274     {
6275       output_asm_insn (\"orr\\t%1, %3\", operands);
6276       output_asm_insn (\"str\\t%1, %0\", operands);
6277     }
6278
6279   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6280     {
6281     case 4:  return \"b%d5\\t%l4\";
6282     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6283     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6284     }
6285   }"
6286   [(set (attr "far_jump")
6287         (if_then_else
6288             (ior (and (eq (symbol_ref ("which_alternative"))
6289                           (const_int 0))
6290                       (eq_attr "length" "8"))
6291                  (eq_attr "length" "10"))
6292             (const_string "yes")
6293             (const_string "no")))
6294    (set (attr "length")
6295      (if_then_else
6296        (eq (symbol_ref ("which_alternative"))
6297                        (const_int 0))
6298        (if_then_else
6299          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6300               (le (minus (match_dup 4) (pc)) (const_int 256)))
6301          (const_int 4)
6302          (if_then_else
6303            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6304                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6305            (const_int 6)
6306            (const_int 8)))
6307        (if_then_else
6308          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6309               (le (minus (match_dup 4) (pc)) (const_int 256)))
6310          (const_int 6)
6311          (if_then_else
6312            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6313                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6314            (const_int 8)
6315            (const_int 10)))))]
6316 )
6317
6318 (define_insn "*xorsi3_cbranch_scratch"
6319   [(set (pc)
6320         (if_then_else
6321          (match_operator 4 "equality_operator"
6322           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6323                    (match_operand:SI 2 "s_register_operand" "l"))
6324            (const_int 0)])
6325          (label_ref (match_operand 3 "" ""))
6326          (pc)))
6327    (clobber (match_scratch:SI 0 "=l"))]
6328   "TARGET_THUMB"
6329   "*
6330   {
6331   output_asm_insn (\"eor\\t%0, %2\", operands);
6332   switch (get_attr_length (insn))
6333     {
6334     case 4:  return \"b%d4\\t%l3\";
6335     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6336     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6337     }
6338   }"
6339   [(set (attr "far_jump")
6340         (if_then_else
6341             (eq_attr "length" "8")
6342             (const_string "yes")
6343             (const_string "no")))
6344    (set (attr "length") 
6345         (if_then_else
6346             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6347                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6348             (const_int 4)
6349             (if_then_else
6350                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6351                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6352                 (const_int 6)
6353                 (const_int 8))))]
6354 )
6355   
6356 (define_insn "*xorsi3_cbranch"
6357   [(set (pc)
6358         (if_then_else
6359          (match_operator 5 "equality_operator"
6360           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6361                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6362            (const_int 0)])
6363          (label_ref (match_operand 4 "" ""))
6364          (pc)))
6365    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6366         (xor:SI (match_dup 2) (match_dup 3)))
6367    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6368   "TARGET_THUMB"
6369   "*
6370   {
6371   if (which_alternative == 0)
6372     output_asm_insn (\"eor\\t%0, %3\", operands);
6373   else if (which_alternative == 1)
6374     {
6375       output_asm_insn (\"eor\\t%1, %3\", operands);
6376       output_asm_insn (\"mov\\t%0, %1\", operands);
6377     }
6378   else
6379     {
6380       output_asm_insn (\"eor\\t%1, %3\", operands);
6381       output_asm_insn (\"str\\t%1, %0\", operands);
6382     }
6383
6384   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6385     {
6386     case 4:  return \"b%d5\\t%l4\";
6387     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6388     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6389     }
6390   }"
6391   [(set (attr "far_jump")
6392         (if_then_else
6393             (ior (and (eq (symbol_ref ("which_alternative"))
6394                           (const_int 0))
6395                       (eq_attr "length" "8"))
6396                  (eq_attr "length" "10"))
6397             (const_string "yes")
6398             (const_string "no")))
6399    (set (attr "length")
6400      (if_then_else
6401        (eq (symbol_ref ("which_alternative"))
6402                        (const_int 0))
6403        (if_then_else
6404          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6405               (le (minus (match_dup 4) (pc)) (const_int 256)))
6406          (const_int 4)
6407          (if_then_else
6408            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6409                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6410            (const_int 6)
6411            (const_int 8)))
6412        (if_then_else
6413          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6414               (le (minus (match_dup 4) (pc)) (const_int 256)))
6415          (const_int 6)
6416          (if_then_else
6417            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6418                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6419            (const_int 8)
6420            (const_int 10)))))]
6421 )
6422
6423 (define_insn "*bicsi3_cbranch_scratch"
6424   [(set (pc)
6425         (if_then_else
6426          (match_operator 4 "equality_operator"
6427           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6428                    (match_operand:SI 1 "s_register_operand" "0"))
6429            (const_int 0)])
6430          (label_ref (match_operand 3 "" ""))
6431          (pc)))
6432    (clobber (match_scratch:SI 0 "=l"))]
6433   "TARGET_THUMB"
6434   "*
6435   {
6436   output_asm_insn (\"bic\\t%0, %2\", operands);
6437   switch (get_attr_length (insn))
6438     {
6439     case 4:  return \"b%d4\\t%l3\";
6440     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6441     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6442     }
6443   }"
6444   [(set (attr "far_jump")
6445         (if_then_else
6446             (eq_attr "length" "8")
6447             (const_string "yes")
6448             (const_string "no")))
6449    (set (attr "length") 
6450         (if_then_else
6451             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6452                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6453             (const_int 4)
6454             (if_then_else
6455                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6456                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6457                 (const_int 6)
6458                 (const_int 8))))]
6459 )
6460   
6461 (define_insn "*bicsi3_cbranch"
6462   [(set (pc)
6463         (if_then_else
6464          (match_operator 5 "equality_operator"
6465           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6466                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6467            (const_int 0)])
6468          (label_ref (match_operand 4 "" ""))
6469          (pc)))
6470    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6471         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6472    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6473   "TARGET_THUMB"
6474   "*
6475   {
6476   if (which_alternative == 0)
6477     output_asm_insn (\"bic\\t%0, %3\", operands);
6478   else if (which_alternative <= 2)
6479     {
6480       output_asm_insn (\"bic\\t%1, %3\", operands);
6481       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6482          conditions again, since we're only testing for equality.  */
6483       output_asm_insn (\"mov\\t%0, %1\", operands);
6484     }
6485   else
6486     {
6487       output_asm_insn (\"bic\\t%1, %3\", operands);
6488       output_asm_insn (\"str\\t%1, %0\", operands);
6489     }
6490
6491   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6492     {
6493     case 4:  return \"b%d5\\t%l4\";
6494     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6495     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6496     }
6497   }"
6498   [(set (attr "far_jump")
6499         (if_then_else
6500             (ior (and (eq (symbol_ref ("which_alternative"))
6501                           (const_int 0))
6502                       (eq_attr "length" "8"))
6503                  (eq_attr "length" "10"))
6504             (const_string "yes")
6505             (const_string "no")))
6506    (set (attr "length")
6507      (if_then_else
6508        (eq (symbol_ref ("which_alternative"))
6509                        (const_int 0))
6510        (if_then_else
6511          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6512               (le (minus (match_dup 4) (pc)) (const_int 256)))
6513          (const_int 4)
6514          (if_then_else
6515            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6516                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6517            (const_int 6)
6518            (const_int 8)))
6519        (if_then_else
6520          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6521               (le (minus (match_dup 4) (pc)) (const_int 256)))
6522          (const_int 6)
6523          (if_then_else
6524            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6525                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6526            (const_int 8)
6527            (const_int 10)))))]
6528 )
6529
6530 (define_insn "*cbranchne_decr1"
6531   [(set (pc)
6532         (if_then_else (match_operator 3 "equality_operator"
6533                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6534                         (const_int 0)])
6535                       (label_ref (match_operand 4 "" ""))
6536                       (pc)))
6537    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6538         (plus:SI (match_dup 2) (const_int -1)))
6539    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6540   "TARGET_THUMB"
6541   "*
6542    {
6543      rtx cond[2];
6544      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6545                                 ? GEU : LTU),
6546                                VOIDmode, operands[2], const1_rtx);
6547      cond[1] = operands[4];
6548
6549      if (which_alternative == 0)
6550        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6551      else if (which_alternative == 1)
6552        {
6553          /* We must provide an alternative for a hi reg because reload 
6554             cannot handle output reloads on a jump instruction, but we
6555             can't subtract into that.  Fortunately a mov from lo to hi
6556             does not clobber the condition codes.  */
6557          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6558          output_asm_insn (\"mov\\t%0, %1\", operands);
6559        }
6560      else
6561        {
6562          /* Similarly, but the target is memory.  */
6563          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6564          output_asm_insn (\"str\\t%1, %0\", operands);
6565        }
6566
6567      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6568        {
6569          case 4:
6570            output_asm_insn (\"b%d0\\t%l1\", cond);
6571            return \"\";
6572          case 6:
6573            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6574            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6575          default:
6576            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6577            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6578        }
6579    }
6580   "
6581   [(set (attr "far_jump")
6582         (if_then_else
6583             (ior (and (eq (symbol_ref ("which_alternative"))
6584                           (const_int 0))
6585                       (eq_attr "length" "8"))
6586                  (eq_attr "length" "10"))
6587             (const_string "yes")
6588             (const_string "no")))
6589    (set_attr_alternative "length"
6590       [
6591        ;; Alternative 0
6592        (if_then_else
6593          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6594               (le (minus (match_dup 4) (pc)) (const_int 256)))
6595          (const_int 4)
6596          (if_then_else
6597            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6598                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6599            (const_int 6)
6600            (const_int 8)))
6601        ;; Alternative 1
6602        (if_then_else
6603          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6604               (le (minus (match_dup 4) (pc)) (const_int 256)))
6605          (const_int 6)
6606          (if_then_else
6607            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6608                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6609            (const_int 8)
6610            (const_int 10)))
6611        ;; Alternative 2
6612        (if_then_else
6613          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6614               (le (minus (match_dup 4) (pc)) (const_int 256)))
6615          (const_int 6)
6616          (if_then_else
6617            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6618                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6619            (const_int 8)
6620            (const_int 10)))
6621        ;; Alternative 3
6622        (if_then_else
6623          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6624               (le (minus (match_dup 4) (pc)) (const_int 256)))
6625          (const_int 6)
6626          (if_then_else
6627            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6628                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6629            (const_int 8)
6630            (const_int 10)))])]
6631 )
6632
6633 (define_insn "*addsi3_cbranch"
6634   [(set (pc)
6635         (if_then_else
6636          (match_operator 4 "comparison_operator"
6637           [(plus:SI
6638             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6639             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6640            (const_int 0)])
6641          (label_ref (match_operand 5 "" ""))
6642          (pc)))
6643    (set
6644     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6645     (plus:SI (match_dup 2) (match_dup 3)))
6646    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6647   "TARGET_THUMB
6648    && (GET_CODE (operands[4]) == EQ
6649        || GET_CODE (operands[4]) == NE
6650        || GET_CODE (operands[4]) == GE
6651        || GET_CODE (operands[4]) == LT)"
6652   "*
6653    {
6654      rtx cond[3];
6655
6656      
6657      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6658      cond[1] = operands[2];
6659      cond[2] = operands[3];
6660
6661      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6662        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6663      else
6664        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6665
6666      if (which_alternative >= 3
6667          && which_alternative < 4)
6668        output_asm_insn (\"mov\\t%0, %1\", operands);
6669      else if (which_alternative >= 4)
6670        output_asm_insn (\"str\\t%1, %0\", operands);
6671
6672      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6673        {
6674          case 4:
6675            return \"b%d4\\t%l5\";
6676          case 6:
6677            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6678          default:
6679            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6680        }
6681    }
6682   "
6683   [(set (attr "far_jump")
6684         (if_then_else
6685             (ior (and (lt (symbol_ref ("which_alternative"))
6686                           (const_int 3))
6687                       (eq_attr "length" "8"))
6688                  (eq_attr "length" "10"))
6689             (const_string "yes")
6690             (const_string "no")))
6691    (set (attr "length")
6692      (if_then_else
6693        (lt (symbol_ref ("which_alternative"))
6694                        (const_int 3))
6695        (if_then_else
6696          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6697               (le (minus (match_dup 5) (pc)) (const_int 256)))
6698          (const_int 4)
6699          (if_then_else
6700            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6701                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6702            (const_int 6)
6703            (const_int 8)))
6704        (if_then_else
6705          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6706               (le (minus (match_dup 5) (pc)) (const_int 256)))
6707          (const_int 6)
6708          (if_then_else
6709            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6710                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6711            (const_int 8)
6712            (const_int 10)))))]
6713 )
6714
6715 (define_insn "*addsi3_cbranch_scratch"
6716   [(set (pc)
6717         (if_then_else
6718          (match_operator 3 "comparison_operator"
6719           [(plus:SI
6720             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6721             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6722            (const_int 0)])
6723          (label_ref (match_operand 4 "" ""))
6724          (pc)))
6725    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6726   "TARGET_THUMB
6727    && (GET_CODE (operands[3]) == EQ
6728        || GET_CODE (operands[3]) == NE
6729        || GET_CODE (operands[3]) == GE
6730        || GET_CODE (operands[3]) == LT)"
6731   "*
6732    {
6733      switch (which_alternative)
6734        {
6735        case 0:
6736          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6737          break;
6738        case 1:
6739          output_asm_insn (\"cmn\t%1, %2\", operands);
6740          break;
6741        case 2:
6742          if (INTVAL (operands[2]) < 0)
6743            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6744          else
6745            output_asm_insn (\"add\t%0, %1, %2\", operands);
6746          break;
6747        case 3:
6748          if (INTVAL (operands[2]) < 0)
6749            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6750          else
6751            output_asm_insn (\"add\t%0, %0, %2\", operands);
6752          break;
6753        }
6754
6755      switch (get_attr_length (insn))
6756        {
6757          case 4:
6758            return \"b%d3\\t%l4\";
6759          case 6:
6760            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6761          default:
6762            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6763        }
6764    }
6765   "
6766   [(set (attr "far_jump")
6767         (if_then_else
6768             (eq_attr "length" "8")
6769             (const_string "yes")
6770             (const_string "no")))
6771    (set (attr "length")
6772        (if_then_else
6773          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6774               (le (minus (match_dup 4) (pc)) (const_int 256)))
6775          (const_int 4)
6776          (if_then_else
6777            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6778                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6779            (const_int 6)
6780            (const_int 8))))]
6781 )
6782
6783 (define_insn "*subsi3_cbranch"
6784   [(set (pc)
6785         (if_then_else
6786          (match_operator 4 "comparison_operator"
6787           [(minus:SI
6788             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6789             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6790            (const_int 0)])
6791          (label_ref (match_operand 5 "" ""))
6792          (pc)))
6793    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6794         (minus:SI (match_dup 2) (match_dup 3)))
6795    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6796   "TARGET_THUMB
6797    && (GET_CODE (operands[4]) == EQ
6798        || GET_CODE (operands[4]) == NE
6799        || GET_CODE (operands[4]) == GE
6800        || GET_CODE (operands[4]) == LT)"
6801   "*
6802    {
6803      if (which_alternative == 0)
6804        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6805      else if (which_alternative == 1)
6806        {
6807          /* We must provide an alternative for a hi reg because reload 
6808             cannot handle output reloads on a jump instruction, but we
6809             can't subtract into that.  Fortunately a mov from lo to hi
6810             does not clobber the condition codes.  */
6811          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6812          output_asm_insn (\"mov\\t%0, %1\", operands);
6813        }
6814      else
6815        {
6816          /* Similarly, but the target is memory.  */
6817          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6818          output_asm_insn (\"str\\t%1, %0\", operands);
6819        }
6820
6821      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6822        {
6823          case 4:
6824            return \"b%d4\\t%l5\";
6825          case 6:
6826            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6827          default:
6828            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6829        }
6830    }
6831   "
6832   [(set (attr "far_jump")
6833         (if_then_else
6834             (ior (and (eq (symbol_ref ("which_alternative"))
6835                           (const_int 0))
6836                       (eq_attr "length" "8"))
6837                  (eq_attr "length" "10"))
6838             (const_string "yes")
6839             (const_string "no")))
6840    (set (attr "length")
6841      (if_then_else
6842        (eq (symbol_ref ("which_alternative"))
6843                        (const_int 0))
6844        (if_then_else
6845          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6846               (le (minus (match_dup 5) (pc)) (const_int 256)))
6847          (const_int 4)
6848          (if_then_else
6849            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6850                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6851            (const_int 6)
6852            (const_int 8)))
6853        (if_then_else
6854          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6855               (le (minus (match_dup 5) (pc)) (const_int 256)))
6856          (const_int 6)
6857          (if_then_else
6858            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6859                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6860            (const_int 8)
6861            (const_int 10)))))]
6862 )
6863
6864 (define_insn "*subsi3_cbranch_scratch"
6865   [(set (pc)
6866         (if_then_else
6867          (match_operator 0 "arm_comparison_operator"
6868           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6869                      (match_operand:SI 2 "nonmemory_operand" "l"))
6870            (const_int 0)])
6871          (label_ref (match_operand 3 "" ""))
6872          (pc)))]
6873   "TARGET_THUMB
6874    && (GET_CODE (operands[0]) == EQ
6875        || GET_CODE (operands[0]) == NE
6876        || GET_CODE (operands[0]) == GE
6877        || GET_CODE (operands[0]) == LT)"
6878   "*
6879   output_asm_insn (\"cmp\\t%1, %2\", operands);
6880   switch (get_attr_length (insn))
6881     {
6882     case 4:  return \"b%d0\\t%l3\";
6883     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6884     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6885     }
6886   "
6887   [(set (attr "far_jump")
6888         (if_then_else
6889             (eq_attr "length" "8")
6890             (const_string "yes")
6891             (const_string "no")))
6892    (set (attr "length") 
6893         (if_then_else
6894             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6895                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6896             (const_int 4)
6897             (if_then_else
6898                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6899                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6900                 (const_int 6)
6901                 (const_int 8))))]
6902 )
6903
6904 ;; Comparison and test insns
6905
6906 (define_expand "cmpsi"
6907   [(match_operand:SI 0 "s_register_operand" "")
6908    (match_operand:SI 1 "arm_add_operand" "")]
6909   "TARGET_ARM"
6910   "{
6911     arm_compare_op0 = operands[0];
6912     arm_compare_op1 = operands[1];
6913     DONE;
6914   }"
6915 )
6916
6917 (define_expand "cmpsf"
6918   [(match_operand:SF 0 "s_register_operand" "")
6919    (match_operand:SF 1 "arm_float_compare_operand" "")]
6920   "TARGET_ARM && TARGET_HARD_FLOAT"
6921   "
6922   arm_compare_op0 = operands[0];
6923   arm_compare_op1 = operands[1];
6924   DONE;
6925   "
6926 )
6927
6928 (define_expand "cmpdf"
6929   [(match_operand:DF 0 "s_register_operand" "")
6930    (match_operand:DF 1 "arm_float_compare_operand" "")]
6931   "TARGET_ARM && TARGET_HARD_FLOAT"
6932   "
6933   arm_compare_op0 = operands[0];
6934   arm_compare_op1 = operands[1];
6935   DONE;
6936   "
6937 )
6938
6939 (define_insn "*arm_cmpsi_insn"
6940   [(set (reg:CC CC_REGNUM)
6941         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6942                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6943   "TARGET_ARM"
6944   "@
6945    cmp%?\\t%0, %1
6946    cmn%?\\t%0, #%n1"
6947   [(set_attr "conds" "set")]
6948 )
6949
6950 (define_insn "*cmpsi_shiftsi"
6951   [(set (reg:CC CC_REGNUM)
6952         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6953                     (match_operator:SI  3 "shift_operator"
6954                      [(match_operand:SI 1 "s_register_operand" "r")
6955                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6956   "TARGET_ARM"
6957   "cmp%?\\t%0, %1%S3"
6958   [(set_attr "conds" "set")
6959    (set_attr "shift" "1")
6960    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6961                       (const_string "alu_shift")
6962                       (const_string "alu_shift_reg")))]
6963 )
6964
6965 (define_insn "*cmpsi_shiftsi_swp"
6966   [(set (reg:CC_SWP CC_REGNUM)
6967         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6968                          [(match_operand:SI 1 "s_register_operand" "r")
6969                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6970                         (match_operand:SI 0 "s_register_operand" "r")))]
6971   "TARGET_ARM"
6972   "cmp%?\\t%0, %1%S3"
6973   [(set_attr "conds" "set")
6974    (set_attr "shift" "1")
6975    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6976                       (const_string "alu_shift")
6977                       (const_string "alu_shift_reg")))]
6978 )
6979
6980 (define_insn "*cmpsi_negshiftsi_si"
6981   [(set (reg:CC_Z CC_REGNUM)
6982         (compare:CC_Z
6983          (neg:SI (match_operator:SI 1 "shift_operator"
6984                     [(match_operand:SI 2 "s_register_operand" "r")
6985                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6986          (match_operand:SI 0 "s_register_operand" "r")))]
6987   "TARGET_ARM"
6988   "cmn%?\\t%0, %2%S1"
6989   [(set_attr "conds" "set")
6990    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6991                                     (const_string "alu_shift")
6992                                     (const_string "alu_shift_reg")))]
6993 )
6994
6995 ;; Cirrus SF compare instruction
6996 (define_insn "*cirrus_cmpsf"
6997   [(set (reg:CCFP CC_REGNUM)
6998         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6999                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
7000   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7001   "cfcmps%?\\tr15, %V0, %V1"
7002   [(set_attr "type"   "mav_farith")
7003    (set_attr "cirrus" "compare")]
7004 )
7005
7006 ;; Cirrus DF compare instruction
7007 (define_insn "*cirrus_cmpdf"
7008   [(set (reg:CCFP CC_REGNUM)
7009         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7010                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
7011   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7012   "cfcmpd%?\\tr15, %V0, %V1"
7013   [(set_attr "type"   "mav_farith")
7014    (set_attr "cirrus" "compare")]
7015 )
7016
7017 ;; Cirrus DI compare instruction
7018 (define_expand "cmpdi"
7019   [(match_operand:DI 0 "cirrus_fp_register" "")
7020    (match_operand:DI 1 "cirrus_fp_register" "")]
7021   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7022   "{
7023      arm_compare_op0 = operands[0];
7024      arm_compare_op1 = operands[1];
7025      DONE;
7026    }")
7027
7028 (define_insn "*cirrus_cmpdi"
7029   [(set (reg:CC CC_REGNUM)
7030         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7031                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
7032   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7033   "cfcmp64%?\\tr15, %V0, %V1"
7034   [(set_attr "type"   "mav_farith")
7035    (set_attr "cirrus" "compare")]
7036 )
7037
7038 ; This insn allows redundant compares to be removed by cse, nothing should
7039 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7040 ; is deleted later on. The match_dup will match the mode here, so that
7041 ; mode changes of the condition codes aren't lost by this even though we don't
7042 ; specify what they are.
7043
7044 (define_insn "*deleted_compare"
7045   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7046   "TARGET_ARM"
7047   "\\t%@ deleted compare"
7048   [(set_attr "conds" "set")
7049    (set_attr "length" "0")]
7050 )
7051
7052 \f
7053 ;; Conditional branch insns
7054
7055 (define_expand "beq"
7056   [(set (pc)
7057         (if_then_else (eq (match_dup 1) (const_int 0))
7058                       (label_ref (match_operand 0 "" ""))
7059                       (pc)))]
7060   "TARGET_ARM"
7061   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7062 )
7063
7064 (define_expand "bne"
7065   [(set (pc)
7066         (if_then_else (ne (match_dup 1) (const_int 0))
7067                       (label_ref (match_operand 0 "" ""))
7068                       (pc)))]
7069   "TARGET_ARM"
7070   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7071 )
7072
7073 (define_expand "bgt"
7074   [(set (pc)
7075         (if_then_else (gt (match_dup 1) (const_int 0))
7076                       (label_ref (match_operand 0 "" ""))
7077                       (pc)))]
7078   "TARGET_ARM"
7079   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7080 )
7081
7082 (define_expand "ble"
7083   [(set (pc)
7084         (if_then_else (le (match_dup 1) (const_int 0))
7085                       (label_ref (match_operand 0 "" ""))
7086                       (pc)))]
7087   "TARGET_ARM"
7088   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7089 )
7090
7091 (define_expand "bge"
7092   [(set (pc)
7093         (if_then_else (ge (match_dup 1) (const_int 0))
7094                       (label_ref (match_operand 0 "" ""))
7095                       (pc)))]
7096   "TARGET_ARM"
7097   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7098 )
7099
7100 (define_expand "blt"
7101   [(set (pc)
7102         (if_then_else (lt (match_dup 1) (const_int 0))
7103                       (label_ref (match_operand 0 "" ""))
7104                       (pc)))]
7105   "TARGET_ARM"
7106   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7107 )
7108
7109 (define_expand "bgtu"
7110   [(set (pc)
7111         (if_then_else (gtu (match_dup 1) (const_int 0))
7112                       (label_ref (match_operand 0 "" ""))
7113                       (pc)))]
7114   "TARGET_ARM"
7115   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7116 )
7117
7118 (define_expand "bleu"
7119   [(set (pc)
7120         (if_then_else (leu (match_dup 1) (const_int 0))
7121                       (label_ref (match_operand 0 "" ""))
7122                       (pc)))]
7123   "TARGET_ARM"
7124   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7125 )
7126
7127 (define_expand "bgeu"
7128   [(set (pc)
7129         (if_then_else (geu (match_dup 1) (const_int 0))
7130                       (label_ref (match_operand 0 "" ""))
7131                       (pc)))]
7132   "TARGET_ARM"
7133   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7134 )
7135
7136 (define_expand "bltu"
7137   [(set (pc)
7138         (if_then_else (ltu (match_dup 1) (const_int 0))
7139                       (label_ref (match_operand 0 "" ""))
7140                       (pc)))]
7141   "TARGET_ARM"
7142   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7143 )
7144
7145 (define_expand "bunordered"
7146   [(set (pc)
7147         (if_then_else (unordered (match_dup 1) (const_int 0))
7148                       (label_ref (match_operand 0 "" ""))
7149                       (pc)))]
7150   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7151   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7152                                       arm_compare_op1);"
7153 )
7154
7155 (define_expand "bordered"
7156   [(set (pc)
7157         (if_then_else (ordered (match_dup 1) (const_int 0))
7158                       (label_ref (match_operand 0 "" ""))
7159                       (pc)))]
7160   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7161   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7162                                       arm_compare_op1);"
7163 )
7164
7165 (define_expand "bungt"
7166   [(set (pc)
7167         (if_then_else (ungt (match_dup 1) (const_int 0))
7168                       (label_ref (match_operand 0 "" ""))
7169                       (pc)))]
7170   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7171   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7172 )
7173
7174 (define_expand "bunlt"
7175   [(set (pc)
7176         (if_then_else (unlt (match_dup 1) (const_int 0))
7177                       (label_ref (match_operand 0 "" ""))
7178                       (pc)))]
7179   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7180   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7181 )
7182
7183 (define_expand "bunge"
7184   [(set (pc)
7185         (if_then_else (unge (match_dup 1) (const_int 0))
7186                       (label_ref (match_operand 0 "" ""))
7187                       (pc)))]
7188   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7189   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7190 )
7191
7192 (define_expand "bunle"
7193   [(set (pc)
7194         (if_then_else (unle (match_dup 1) (const_int 0))
7195                       (label_ref (match_operand 0 "" ""))
7196                       (pc)))]
7197   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7198   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7199 )
7200
7201 ;; The following two patterns need two branch instructions, since there is
7202 ;; no single instruction that will handle all cases.
7203 (define_expand "buneq"
7204   [(set (pc)
7205         (if_then_else (uneq (match_dup 1) (const_int 0))
7206                       (label_ref (match_operand 0 "" ""))
7207                       (pc)))]
7208   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7209   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7210 )
7211
7212 (define_expand "bltgt"
7213   [(set (pc)
7214         (if_then_else (ltgt (match_dup 1) (const_int 0))
7215                       (label_ref (match_operand 0 "" ""))
7216                       (pc)))]
7217   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7218   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7219 )
7220
7221 ;;
7222 ;; Patterns to match conditional branch insns.
7223 ;;
7224
7225 ; Special pattern to match UNEQ.
7226 (define_insn "*arm_buneq"
7227   [(set (pc)
7228         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7229                       (label_ref (match_operand 0 "" ""))
7230                       (pc)))]
7231   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7232   "*
7233   gcc_assert (!arm_ccfsm_state);
7234
7235   return \"bvs\\t%l0\;beq\\t%l0\";
7236   "
7237   [(set_attr "conds" "jump_clob")
7238    (set_attr "length" "8")]
7239 )
7240
7241 ; Special pattern to match LTGT.
7242 (define_insn "*arm_bltgt"
7243   [(set (pc)
7244         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7245                       (label_ref (match_operand 0 "" ""))
7246                       (pc)))]
7247   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7248   "*
7249   gcc_assert (!arm_ccfsm_state);
7250
7251   return \"bmi\\t%l0\;bgt\\t%l0\";
7252   "
7253   [(set_attr "conds" "jump_clob")
7254    (set_attr "length" "8")]
7255 )
7256
7257 (define_insn "*arm_cond_branch"
7258   [(set (pc)
7259         (if_then_else (match_operator 1 "arm_comparison_operator"
7260                        [(match_operand 2 "cc_register" "") (const_int 0)])
7261                       (label_ref (match_operand 0 "" ""))
7262                       (pc)))]
7263   "TARGET_ARM"
7264   "*
7265   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7266     {
7267       arm_ccfsm_state += 2;
7268       return \"\";
7269     }
7270   return \"b%d1\\t%l0\";
7271   "
7272   [(set_attr "conds" "use")
7273    (set_attr "type" "branch")]
7274 )
7275
7276 ; Special pattern to match reversed UNEQ.
7277 (define_insn "*arm_buneq_reversed"
7278   [(set (pc)
7279         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7280                       (pc)
7281                       (label_ref (match_operand 0 "" ""))))]
7282   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7283   "*
7284   gcc_assert (!arm_ccfsm_state);
7285
7286   return \"bmi\\t%l0\;bgt\\t%l0\";
7287   "
7288   [(set_attr "conds" "jump_clob")
7289    (set_attr "length" "8")]
7290 )
7291
7292 ; Special pattern to match reversed LTGT.
7293 (define_insn "*arm_bltgt_reversed"
7294   [(set (pc)
7295         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7296                       (pc)
7297                       (label_ref (match_operand 0 "" ""))))]
7298   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7299   "*
7300   gcc_assert (!arm_ccfsm_state);
7301
7302   return \"bvs\\t%l0\;beq\\t%l0\";
7303   "
7304   [(set_attr "conds" "jump_clob")
7305    (set_attr "length" "8")]
7306 )
7307
7308 (define_insn "*arm_cond_branch_reversed"
7309   [(set (pc)
7310         (if_then_else (match_operator 1 "arm_comparison_operator"
7311                        [(match_operand 2 "cc_register" "") (const_int 0)])
7312                       (pc)
7313                       (label_ref (match_operand 0 "" ""))))]
7314   "TARGET_ARM"
7315   "*
7316   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7317     {
7318       arm_ccfsm_state += 2;
7319       return \"\";
7320     }
7321   return \"b%D1\\t%l0\";
7322   "
7323   [(set_attr "conds" "use")
7324    (set_attr "type" "branch")]
7325 )
7326
7327 \f
7328
7329 ; scc insns
7330
7331 (define_expand "seq"
7332   [(set (match_operand:SI 0 "s_register_operand" "")
7333         (eq:SI (match_dup 1) (const_int 0)))]
7334   "TARGET_ARM"
7335   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7336 )
7337
7338 (define_expand "sne"
7339   [(set (match_operand:SI 0 "s_register_operand" "")
7340         (ne:SI (match_dup 1) (const_int 0)))]
7341   "TARGET_ARM"
7342   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7343 )
7344
7345 (define_expand "sgt"
7346   [(set (match_operand:SI 0 "s_register_operand" "")
7347         (gt:SI (match_dup 1) (const_int 0)))]
7348   "TARGET_ARM"
7349   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7350 )
7351
7352 (define_expand "sle"
7353   [(set (match_operand:SI 0 "s_register_operand" "")
7354         (le:SI (match_dup 1) (const_int 0)))]
7355   "TARGET_ARM"
7356   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7357 )
7358
7359 (define_expand "sge"
7360   [(set (match_operand:SI 0 "s_register_operand" "")
7361         (ge:SI (match_dup 1) (const_int 0)))]
7362   "TARGET_ARM"
7363   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7364 )
7365
7366 (define_expand "slt"
7367   [(set (match_operand:SI 0 "s_register_operand" "")
7368         (lt:SI (match_dup 1) (const_int 0)))]
7369   "TARGET_ARM"
7370   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7371 )
7372
7373 (define_expand "sgtu"
7374   [(set (match_operand:SI 0 "s_register_operand" "")
7375         (gtu:SI (match_dup 1) (const_int 0)))]
7376   "TARGET_ARM"
7377   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7378 )
7379
7380 (define_expand "sleu"
7381   [(set (match_operand:SI 0 "s_register_operand" "")
7382         (leu:SI (match_dup 1) (const_int 0)))]
7383   "TARGET_ARM"
7384   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7385 )
7386
7387 (define_expand "sgeu"
7388   [(set (match_operand:SI 0 "s_register_operand" "")
7389         (geu:SI (match_dup 1) (const_int 0)))]
7390   "TARGET_ARM"
7391   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7392 )
7393
7394 (define_expand "sltu"
7395   [(set (match_operand:SI 0 "s_register_operand" "")
7396         (ltu:SI (match_dup 1) (const_int 0)))]
7397   "TARGET_ARM"
7398   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7399 )
7400
7401 (define_expand "sunordered"
7402   [(set (match_operand:SI 0 "s_register_operand" "")
7403         (unordered:SI (match_dup 1) (const_int 0)))]
7404   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7405   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7406                                       arm_compare_op1);"
7407 )
7408
7409 (define_expand "sordered"
7410   [(set (match_operand:SI 0 "s_register_operand" "")
7411         (ordered:SI (match_dup 1) (const_int 0)))]
7412   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7413   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7414                                       arm_compare_op1);"
7415 )
7416
7417 (define_expand "sungt"
7418   [(set (match_operand:SI 0 "s_register_operand" "")
7419         (ungt:SI (match_dup 1) (const_int 0)))]
7420   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7421   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7422                                       arm_compare_op1);"
7423 )
7424
7425 (define_expand "sunge"
7426   [(set (match_operand:SI 0 "s_register_operand" "")
7427         (unge:SI (match_dup 1) (const_int 0)))]
7428   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7429   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7430                                       arm_compare_op1);"
7431 )
7432
7433 (define_expand "sunlt"
7434   [(set (match_operand:SI 0 "s_register_operand" "")
7435         (unlt:SI (match_dup 1) (const_int 0)))]
7436   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7437   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7438                                       arm_compare_op1);"
7439 )
7440
7441 (define_expand "sunle"
7442   [(set (match_operand:SI 0 "s_register_operand" "")
7443         (unle:SI (match_dup 1) (const_int 0)))]
7444   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7445   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7446                                       arm_compare_op1);"
7447 )
7448
7449 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7450 ;;; simple ARM instructions. 
7451 ;
7452 ; (define_expand "suneq"
7453 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7454 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7455 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7456 ;   "gcc_unreachable ();"
7457 ; )
7458 ;
7459 ; (define_expand "sltgt"
7460 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7461 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7462 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7463 ;   "gcc_unreachable ();"
7464 ; )
7465
7466 (define_insn "*mov_scc"
7467   [(set (match_operand:SI 0 "s_register_operand" "=r")
7468         (match_operator:SI 1 "arm_comparison_operator"
7469          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7470   "TARGET_ARM"
7471   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7472   [(set_attr "conds" "use")
7473    (set_attr "length" "8")]
7474 )
7475
7476 (define_insn "*mov_negscc"
7477   [(set (match_operand:SI 0 "s_register_operand" "=r")
7478         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7479                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7480   "TARGET_ARM"
7481   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7482   [(set_attr "conds" "use")
7483    (set_attr "length" "8")]
7484 )
7485
7486 (define_insn "*mov_notscc"
7487   [(set (match_operand:SI 0 "s_register_operand" "=r")
7488         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7489                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7490   "TARGET_ARM"
7491   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7492   [(set_attr "conds" "use")
7493    (set_attr "length" "8")]
7494 )
7495
7496 (define_expand "cstoresi4"
7497   [(set (match_operand:SI 0 "s_register_operand" "")
7498         (match_operator:SI 1 "arm_comparison_operator"
7499          [(match_operand:SI 2 "s_register_operand" "")
7500           (match_operand:SI 3 "reg_or_int_operand" "")]))]
7501   "TARGET_THUMB"
7502   "{
7503   rtx op3, scratch, scratch2;
7504
7505   if (operands[3] == const0_rtx)
7506     {
7507       switch (GET_CODE (operands[1]))
7508         {
7509         case EQ:
7510           emit_insn (gen_cstoresi_eq0_thumb (operands[0], operands[2]));
7511           break;
7512
7513         case NE:
7514           emit_insn (gen_cstoresi_ne0_thumb (operands[0], operands[2]));
7515           break;
7516
7517         case LE:
7518           scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7519                                   NULL_RTX, 0, OPTAB_WIDEN);
7520           scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7521                                   NULL_RTX, 0, OPTAB_WIDEN);
7522           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7523                         operands[0], 1, OPTAB_WIDEN);
7524           break;
7525
7526         case GE:
7527           scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7528                                  NULL_RTX, 1);
7529           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7530                         NULL_RTX, 1, OPTAB_WIDEN);
7531           break;
7532
7533         case GT:
7534           scratch = expand_binop (SImode, ashr_optab, operands[2],
7535                                   GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7536           scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7537                                   NULL_RTX, 0, OPTAB_WIDEN);
7538           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7539                         0, OPTAB_WIDEN);
7540           break;
7541
7542         /* LT is handled by generic code.  No need for unsigned with 0.  */
7543         default:
7544           FAIL;
7545         }
7546       DONE;
7547     }
7548
7549   switch (GET_CODE (operands[1]))
7550     {
7551     case EQ:
7552       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7553                               NULL_RTX, 0, OPTAB_WIDEN);
7554       emit_insn (gen_cstoresi_eq0_thumb (operands[0], scratch));
7555       break;
7556
7557     case NE:
7558       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7559                               NULL_RTX, 0, OPTAB_WIDEN);
7560       emit_insn (gen_cstoresi_ne0_thumb (operands[0], scratch));
7561       break;
7562
7563     case LE:
7564       op3 = force_reg (SImode, operands[3]);
7565
7566       scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7567                               NULL_RTX, 1, OPTAB_WIDEN);
7568       scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7569                               NULL_RTX, 0, OPTAB_WIDEN);
7570       emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch2,
7571                                           op3, operands[2]));
7572       break;
7573
7574     case GE:
7575       op3 = operands[3];
7576       if (!thumb_cmp_operand (op3, SImode))
7577         op3 = force_reg (SImode, op3);
7578       scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7579                               NULL_RTX, 0, OPTAB_WIDEN);
7580       scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7581                                NULL_RTX, 1, OPTAB_WIDEN);
7582       emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch2,
7583                                           operands[2], op3));
7584       break;
7585
7586     case LEU:
7587       op3 = force_reg (SImode, operands[3]);
7588       scratch = force_reg (SImode, const0_rtx);
7589       emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch,
7590                                           op3, operands[2]));
7591       break;
7592
7593     case GEU:
7594       op3 = operands[3];
7595       if (!thumb_cmp_operand (op3, SImode))
7596         op3 = force_reg (SImode, op3);
7597       scratch = force_reg (SImode, const0_rtx);
7598       emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch,
7599                                           operands[2], op3));
7600       break;
7601
7602     case LTU:
7603       op3 = operands[3];
7604       if (!thumb_cmp_operand (op3, SImode))
7605         op3 = force_reg (SImode, op3);
7606       scratch = gen_reg_rtx (SImode);
7607       emit_insn (gen_cstoresi_nltu_thumb (scratch, operands[2], op3));
7608       emit_insn (gen_negsi2 (operands[0], scratch));
7609       break;
7610
7611     case GTU:
7612       op3 = force_reg (SImode, operands[3]);
7613       scratch = gen_reg_rtx (SImode);
7614       emit_insn (gen_cstoresi_nltu_thumb (scratch, op3, operands[2]));
7615       emit_insn (gen_negsi2 (operands[0], scratch));
7616       break;
7617
7618     /* No good sequences for GT, LT.  */
7619     default:
7620       FAIL;
7621     }
7622   DONE;
7623 }")
7624
7625 (define_expand "cstoresi_eq0_thumb"
7626   [(parallel
7627     [(set (match_operand:SI 0 "s_register_operand" "")
7628           (eq:SI (match_operand:SI 1 "s_register_operand" "")
7629                  (const_int 0)))
7630      (clobber (match_dup:SI 2))])]
7631   "TARGET_THUMB"
7632   "operands[2] = gen_reg_rtx (SImode);"
7633 )
7634
7635 (define_expand "cstoresi_ne0_thumb"
7636   [(parallel
7637     [(set (match_operand:SI 0 "s_register_operand" "")
7638           (ne:SI (match_operand:SI 1 "s_register_operand" "")
7639                  (const_int 0)))
7640      (clobber (match_dup:SI 2))])]
7641   "TARGET_THUMB"
7642   "operands[2] = gen_reg_rtx (SImode);"
7643 )
7644
7645 (define_insn "*cstoresi_eq0_thumb_insn"
7646   [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7647         (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7648                (const_int 0)))
7649    (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
7650   "TARGET_THUMB"
7651   "@
7652    neg\\t%0, %1\;adc\\t%0, %0, %1
7653    neg\\t%2, %1\;adc\\t%0, %1, %2"
7654   [(set_attr "length" "4")]
7655 )
7656
7657 (define_insn "*cstoresi_ne0_thumb_insn"
7658   [(set (match_operand:SI 0 "s_register_operand" "=l")
7659         (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7660                (const_int 0)))
7661    (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
7662   "TARGET_THUMB"
7663   "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7664   [(set_attr "length" "4")]
7665 )
7666
7667 (define_insn "cstoresi_nltu_thumb"
7668   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7669         (neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7670                         (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r"))))]
7671   "TARGET_THUMB"
7672   "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7673   [(set_attr "length" "4")]
7674 )
7675
7676 ;; Used as part of the expansion of thumb les sequence.
7677 (define_insn "thumb_addsi3_addgeu"
7678   [(set (match_operand:SI 0 "s_register_operand" "=l")
7679         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7680                           (match_operand:SI 2 "s_register_operand" "l"))
7681                  (geu:SI (match_operand:SI 3 "s_register_operand" "l")
7682                          (match_operand:SI 4 "thumb_cmp_operand" "lI"))))]
7683   "TARGET_THUMB"
7684   "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7685   [(set_attr "length" "4")]
7686 )
7687
7688 \f
7689 ;; Conditional move insns
7690
7691 (define_expand "movsicc"
7692   [(set (match_operand:SI 0 "s_register_operand" "")
7693         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7694                          (match_operand:SI 2 "arm_not_operand" "")
7695                          (match_operand:SI 3 "arm_not_operand" "")))]
7696   "TARGET_ARM"
7697   "
7698   {
7699     enum rtx_code code = GET_CODE (operands[1]);
7700     rtx ccreg;
7701
7702     if (code == UNEQ || code == LTGT)
7703       FAIL;
7704
7705     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7706     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7707   }"
7708 )
7709
7710 (define_expand "movsfcc"
7711   [(set (match_operand:SF 0 "s_register_operand" "")
7712         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7713                          (match_operand:SF 2 "s_register_operand" "")
7714                          (match_operand:SF 3 "nonmemory_operand" "")))]
7715   "TARGET_ARM"
7716   "
7717   {
7718     enum rtx_code code = GET_CODE (operands[1]);
7719     rtx ccreg;
7720
7721     if (code == UNEQ || code == LTGT)
7722       FAIL;
7723
7724     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7725        Otherwise, ensure it is a valid FP add operand */
7726     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7727         || (!arm_float_add_operand (operands[3], SFmode)))
7728       operands[3] = force_reg (SFmode, operands[3]);
7729
7730     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7731     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7732   }"
7733 )
7734
7735 (define_expand "movdfcc"
7736   [(set (match_operand:DF 0 "s_register_operand" "")
7737         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7738                          (match_operand:DF 2 "s_register_operand" "")
7739                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7740   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7741   "
7742   {
7743     enum rtx_code code = GET_CODE (operands[1]);
7744     rtx ccreg;
7745
7746     if (code == UNEQ || code == LTGT)
7747       FAIL;
7748
7749     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7750     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7751   }"
7752 )
7753
7754 (define_insn "*movsicc_insn"
7755   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7756         (if_then_else:SI
7757          (match_operator 3 "arm_comparison_operator"
7758           [(match_operand 4 "cc_register" "") (const_int 0)])
7759          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7760          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7761   "TARGET_ARM"
7762   "@
7763    mov%D3\\t%0, %2
7764    mvn%D3\\t%0, #%B2
7765    mov%d3\\t%0, %1
7766    mvn%d3\\t%0, #%B1
7767    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7768    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7769    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7770    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7771   [(set_attr "length" "4,4,4,4,8,8,8,8")
7772    (set_attr "conds" "use")]
7773 )
7774
7775 (define_insn "*movsfcc_soft_insn"
7776   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7777         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7778                           [(match_operand 4 "cc_register" "") (const_int 0)])
7779                          (match_operand:SF 1 "s_register_operand" "0,r")
7780                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7781   "TARGET_ARM && TARGET_SOFT_FLOAT"
7782   "@
7783    mov%D3\\t%0, %2
7784    mov%d3\\t%0, %1"
7785   [(set_attr "conds" "use")]
7786 )
7787
7788 \f
7789 ;; Jump and linkage insns
7790
7791 (define_expand "jump"
7792   [(set (pc)
7793         (label_ref (match_operand 0 "" "")))]
7794   "TARGET_EITHER"
7795   ""
7796 )
7797
7798 (define_insn "*arm_jump"
7799   [(set (pc)
7800         (label_ref (match_operand 0 "" "")))]
7801   "TARGET_ARM"
7802   "*
7803   {
7804     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7805       {
7806         arm_ccfsm_state += 2;
7807         return \"\";
7808       }
7809     return \"b%?\\t%l0\";
7810   }
7811   "
7812   [(set_attr "predicable" "yes")]
7813 )
7814
7815 (define_insn "*thumb_jump"
7816   [(set (pc)
7817         (label_ref (match_operand 0 "" "")))]
7818   "TARGET_THUMB"
7819   "*
7820   if (get_attr_length (insn) == 2)
7821     return \"b\\t%l0\";
7822   return \"bl\\t%l0\\t%@ far jump\";
7823   "
7824   [(set (attr "far_jump")
7825         (if_then_else
7826             (eq_attr "length" "4")
7827             (const_string "yes")
7828             (const_string "no")))
7829    (set (attr "length") 
7830         (if_then_else
7831             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7832                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7833             (const_int 2)
7834             (const_int 4)))]
7835 )
7836
7837 (define_expand "call"
7838   [(parallel [(call (match_operand 0 "memory_operand" "")
7839                     (match_operand 1 "general_operand" ""))
7840               (use (match_operand 2 "" ""))
7841               (clobber (reg:SI LR_REGNUM))])]
7842   "TARGET_EITHER"
7843   "
7844   {
7845     rtx callee;
7846     
7847     /* In an untyped call, we can get NULL for operand 2.  */
7848     if (operands[2] == NULL_RTX)
7849       operands[2] = const0_rtx;
7850       
7851     /* This is to decide if we should generate indirect calls by loading the
7852        32 bit address of the callee into a register before performing the
7853        branch and link.  operand[2] encodes the long_call/short_call
7854        attribute of the function being called.  This attribute is set whenever
7855        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7856        is used, and the short_call attribute can also be set if function is
7857        declared as static or if it has already been defined in the current
7858        compilation unit.  See arm.c and arm.h for info about this.  The third
7859        parameter to arm_is_longcall_p is used to tell it which pattern
7860        invoked it.  */
7861     callee  = XEXP (operands[0], 0);
7862     
7863     if ((GET_CODE (callee) == SYMBOL_REF
7864          && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7865         || (GET_CODE (callee) != SYMBOL_REF
7866             && GET_CODE (callee) != REG))
7867       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7868   }"
7869 )
7870
7871 (define_insn "*call_reg_armv5"
7872   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7873          (match_operand 1 "" ""))
7874    (use (match_operand 2 "" ""))
7875    (clobber (reg:SI LR_REGNUM))]
7876   "TARGET_ARM && arm_arch5"
7877   "blx%?\\t%0"
7878   [(set_attr "type" "call")]
7879 )
7880
7881 (define_insn "*call_reg_arm"
7882   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7883          (match_operand 1 "" ""))
7884    (use (match_operand 2 "" ""))
7885    (clobber (reg:SI LR_REGNUM))]
7886   "TARGET_ARM && !arm_arch5"
7887   "*
7888   return output_call (operands);
7889   "
7890   ;; length is worst case, normally it is only two
7891   [(set_attr "length" "12")
7892    (set_attr "type" "call")]
7893 )
7894
7895 (define_insn "*call_mem"
7896   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
7897          (match_operand 1 "" ""))
7898    (use (match_operand 2 "" ""))
7899    (clobber (reg:SI LR_REGNUM))]
7900   "TARGET_ARM"
7901   "*
7902   return output_call_mem (operands);
7903   "
7904   [(set_attr "length" "12")
7905    (set_attr "type" "call")]
7906 )
7907
7908 (define_insn "*call_reg_thumb_v5"
7909   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7910          (match_operand 1 "" ""))
7911    (use (match_operand 2 "" ""))
7912    (clobber (reg:SI LR_REGNUM))]
7913   "TARGET_THUMB && arm_arch5"
7914   "blx\\t%0"
7915   [(set_attr "length" "2")
7916    (set_attr "type" "call")]
7917 )
7918
7919 (define_insn "*call_reg_thumb"
7920   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7921          (match_operand 1 "" ""))
7922    (use (match_operand 2 "" ""))
7923    (clobber (reg:SI LR_REGNUM))]
7924   "TARGET_THUMB && !arm_arch5"
7925   "*
7926   {
7927     if (!TARGET_CALLER_INTERWORKING)
7928       return thumb_call_via_reg (operands[0]);
7929     else if (operands[1] == const0_rtx)
7930       return \"bl\\t%__interwork_call_via_%0\";
7931     else if (frame_pointer_needed)
7932       return \"bl\\t%__interwork_r7_call_via_%0\";
7933     else
7934       return \"bl\\t%__interwork_r11_call_via_%0\";
7935   }"
7936   [(set_attr "type" "call")]
7937 )
7938
7939 (define_expand "call_value"
7940   [(parallel [(set (match_operand       0 "" "")
7941                    (call (match_operand 1 "memory_operand" "")
7942                          (match_operand 2 "general_operand" "")))
7943               (use (match_operand 3 "" ""))
7944               (clobber (reg:SI LR_REGNUM))])]
7945   "TARGET_EITHER"
7946   "
7947   {
7948     rtx callee = XEXP (operands[1], 0);
7949     
7950     /* In an untyped call, we can get NULL for operand 2.  */
7951     if (operands[3] == 0)
7952       operands[3] = const0_rtx;
7953       
7954     /* See the comment in define_expand \"call\".  */
7955     if ((GET_CODE (callee) == SYMBOL_REF
7956          && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7957         || (GET_CODE (callee) != SYMBOL_REF
7958             && GET_CODE (callee) != REG))
7959       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7960   }"
7961 )
7962
7963 (define_insn "*call_value_reg_armv5"
7964   [(set (match_operand 0 "" "")
7965         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7966               (match_operand 2 "" "")))
7967    (use (match_operand 3 "" ""))
7968    (clobber (reg:SI LR_REGNUM))]
7969   "TARGET_ARM && arm_arch5"
7970   "blx%?\\t%1"
7971   [(set_attr "type" "call")]
7972 )
7973
7974 (define_insn "*call_value_reg_arm"
7975   [(set (match_operand 0 "" "")
7976         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7977               (match_operand 2 "" "")))
7978    (use (match_operand 3 "" ""))
7979    (clobber (reg:SI LR_REGNUM))]
7980   "TARGET_ARM && !arm_arch5"
7981   "*
7982   return output_call (&operands[1]);
7983   "
7984   [(set_attr "length" "12")
7985    (set_attr "type" "call")]
7986 )
7987
7988 (define_insn "*call_value_mem"
7989   [(set (match_operand 0 "" "")
7990         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
7991               (match_operand 2 "" "")))
7992    (use (match_operand 3 "" ""))
7993    (clobber (reg:SI LR_REGNUM))]
7994   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7995   "*
7996   return output_call_mem (&operands[1]);
7997   "
7998   [(set_attr "length" "12")
7999    (set_attr "type" "call")]
8000 )
8001
8002 (define_insn "*call_value_reg_thumb_v5"
8003   [(set (match_operand 0 "" "")
8004         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8005               (match_operand 2 "" "")))
8006    (use (match_operand 3 "" ""))
8007    (clobber (reg:SI LR_REGNUM))]
8008   "TARGET_THUMB && arm_arch5"
8009   "blx\\t%1"
8010   [(set_attr "length" "2")
8011    (set_attr "type" "call")]
8012 )
8013
8014 (define_insn "*call_value_reg_thumb"
8015   [(set (match_operand 0 "" "")
8016         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8017               (match_operand 2 "" "")))
8018    (use (match_operand 3 "" ""))
8019    (clobber (reg:SI LR_REGNUM))]
8020   "TARGET_THUMB && !arm_arch5"
8021   "*
8022   {
8023     if (!TARGET_CALLER_INTERWORKING)
8024       return thumb_call_via_reg (operands[1]);
8025     else if (operands[2] == const0_rtx)
8026       return \"bl\\t%__interwork_call_via_%1\";
8027     else if (frame_pointer_needed)
8028       return \"bl\\t%__interwork_r7_call_via_%1\";
8029     else
8030       return \"bl\\t%__interwork_r11_call_via_%1\";
8031   }"
8032   [(set_attr "type" "call")]
8033 )
8034
8035 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8036 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8037
8038 (define_insn "*call_symbol"
8039   [(call (mem:SI (match_operand:SI 0 "" ""))
8040          (match_operand 1 "" ""))
8041    (use (match_operand 2 "" ""))
8042    (clobber (reg:SI LR_REGNUM))]
8043   "TARGET_ARM
8044    && (GET_CODE (operands[0]) == SYMBOL_REF)
8045    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
8046   "*
8047   {
8048     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8049   }"
8050   [(set_attr "type" "call")]
8051 )
8052
8053 (define_insn "*call_value_symbol"
8054   [(set (match_operand 0 "" "")
8055         (call (mem:SI (match_operand:SI 1 "" ""))
8056         (match_operand:SI 2 "" "")))
8057    (use (match_operand 3 "" ""))
8058    (clobber (reg:SI LR_REGNUM))]
8059   "TARGET_ARM
8060    && (GET_CODE (operands[1]) == SYMBOL_REF)
8061    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
8062   "*
8063   {
8064     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8065   }"
8066   [(set_attr "type" "call")]
8067 )
8068
8069 (define_insn "*call_insn"
8070   [(call (mem:SI (match_operand:SI 0 "" ""))
8071          (match_operand:SI 1 "" ""))
8072    (use (match_operand 2 "" ""))
8073    (clobber (reg:SI LR_REGNUM))]
8074   "TARGET_THUMB
8075    && GET_CODE (operands[0]) == SYMBOL_REF
8076    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
8077   "bl\\t%a0"
8078   [(set_attr "length" "4")
8079    (set_attr "type" "call")]
8080 )
8081
8082 (define_insn "*call_value_insn"
8083   [(set (match_operand 0 "" "")
8084         (call (mem:SI (match_operand 1 "" ""))
8085               (match_operand 2 "" "")))
8086    (use (match_operand 3 "" ""))
8087    (clobber (reg:SI LR_REGNUM))]
8088   "TARGET_THUMB
8089    && GET_CODE (operands[1]) == SYMBOL_REF
8090    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
8091   "bl\\t%a1"
8092   [(set_attr "length" "4")
8093    (set_attr "type" "call")]
8094 )
8095
8096 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8097 (define_expand "sibcall"
8098   [(parallel [(call (match_operand 0 "memory_operand" "")
8099                     (match_operand 1 "general_operand" ""))
8100               (return)
8101               (use (match_operand 2 "" ""))])]
8102   "TARGET_ARM"
8103   "
8104   {
8105     if (operands[2] == NULL_RTX)
8106       operands[2] = const0_rtx;
8107   }"
8108 )
8109
8110 (define_expand "sibcall_value"
8111   [(parallel [(set (match_operand 0 "" "")
8112                    (call (match_operand 1 "memory_operand" "")
8113                          (match_operand 2 "general_operand" "")))
8114               (return)
8115               (use (match_operand 3 "" ""))])]
8116   "TARGET_ARM"
8117   "
8118   {
8119     if (operands[3] == NULL_RTX)
8120       operands[3] = const0_rtx;
8121   }"
8122 )
8123
8124 (define_insn "*sibcall_insn"
8125  [(call (mem:SI (match_operand:SI 0 "" "X"))
8126         (match_operand 1 "" ""))
8127   (return)
8128   (use (match_operand 2 "" ""))]
8129   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8130   "*
8131   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8132   "
8133   [(set_attr "type" "call")]
8134 )
8135
8136 (define_insn "*sibcall_value_insn"
8137  [(set (match_operand 0 "" "")
8138        (call (mem:SI (match_operand:SI 1 "" "X"))
8139              (match_operand 2 "" "")))
8140   (return)
8141   (use (match_operand 3 "" ""))]
8142   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8143   "*
8144   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8145   "
8146   [(set_attr "type" "call")]
8147 )
8148
8149 ;; Often the return insn will be the same as loading from memory, so set attr
8150 (define_insn "return"
8151   [(return)]
8152   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8153   "*
8154   {
8155     if (arm_ccfsm_state == 2)
8156       {
8157         arm_ccfsm_state += 2;
8158         return \"\";
8159       }
8160     return output_return_instruction (const_true_rtx, TRUE, FALSE);
8161   }"
8162   [(set_attr "type" "load1")
8163    (set_attr "length" "12")
8164    (set_attr "predicable" "yes")]
8165 )
8166
8167 (define_insn "*cond_return"
8168   [(set (pc)
8169         (if_then_else (match_operator 0 "arm_comparison_operator"
8170                        [(match_operand 1 "cc_register" "") (const_int 0)])
8171                       (return)
8172                       (pc)))]
8173   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8174   "*
8175   {
8176     if (arm_ccfsm_state == 2)
8177       {
8178         arm_ccfsm_state += 2;
8179         return \"\";
8180       }
8181     return output_return_instruction (operands[0], TRUE, FALSE);
8182   }"
8183   [(set_attr "conds" "use")
8184    (set_attr "length" "12")
8185    (set_attr "type" "load1")]
8186 )
8187
8188 (define_insn "*cond_return_inverted"
8189   [(set (pc)
8190         (if_then_else (match_operator 0 "arm_comparison_operator"
8191                        [(match_operand 1 "cc_register" "") (const_int 0)])
8192                       (pc)
8193                       (return)))]
8194   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8195   "*
8196   {
8197     if (arm_ccfsm_state == 2)
8198       {
8199         arm_ccfsm_state += 2;
8200         return \"\";
8201       }
8202     return output_return_instruction (operands[0], TRUE, TRUE);
8203   }"
8204   [(set_attr "conds" "use")
8205    (set_attr "length" "12")
8206    (set_attr "type" "load1")]
8207 )
8208
8209 ;; Generate a sequence of instructions to determine if the processor is
8210 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8211 ;; mask.
8212
8213 (define_expand "return_addr_mask"
8214   [(set (match_dup 1)
8215       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8216                        (const_int 0)))
8217    (set (match_operand:SI 0 "s_register_operand" "")
8218       (if_then_else:SI (eq (match_dup 1) (const_int 0))
8219                        (const_int -1)
8220                        (const_int 67108860)))] ; 0x03fffffc
8221   "TARGET_ARM"
8222   "
8223   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8224   ")
8225
8226 (define_insn "*check_arch2"
8227   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8228       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8229                        (const_int 0)))]
8230   "TARGET_ARM"
8231   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8232   [(set_attr "length" "8")
8233    (set_attr "conds" "set")]
8234 )
8235
8236 ;; Call subroutine returning any type.
8237
8238 (define_expand "untyped_call"
8239   [(parallel [(call (match_operand 0 "" "")
8240                     (const_int 0))
8241               (match_operand 1 "" "")
8242               (match_operand 2 "" "")])]
8243   "TARGET_EITHER"
8244   "
8245   {
8246     int i;
8247     rtx par = gen_rtx_PARALLEL (VOIDmode,
8248                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8249     rtx addr = gen_reg_rtx (Pmode);
8250     rtx mem;
8251     int size = 0;
8252
8253     emit_move_insn (addr, XEXP (operands[1], 0));
8254     mem = change_address (operands[1], BLKmode, addr);
8255
8256     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8257       {
8258         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8259
8260         /* Default code only uses r0 as a return value, but we could
8261            be using anything up to 4 registers.  */
8262         if (REGNO (src) == R0_REGNUM)
8263           src = gen_rtx_REG (TImode, R0_REGNUM);
8264
8265         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8266                                                  GEN_INT (size));
8267         size += GET_MODE_SIZE (GET_MODE (src));
8268       }
8269
8270     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8271                                     const0_rtx));
8272
8273     size = 0;
8274
8275     for (i = 0; i < XVECLEN (par, 0); i++)
8276       {
8277         HOST_WIDE_INT offset = 0;
8278         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8279
8280         if (size != 0)
8281           emit_move_insn (addr, plus_constant (addr, size));
8282
8283         mem = change_address (mem, GET_MODE (reg), NULL);
8284         if (REGNO (reg) == R0_REGNUM)
8285           {
8286             /* On thumb we have to use a write-back instruction.  */
8287             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8288                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8289             size = TARGET_ARM ? 16 : 0;
8290           }
8291         else
8292           {
8293             emit_move_insn (mem, reg);
8294             size = GET_MODE_SIZE (GET_MODE (reg));
8295           }
8296       }
8297
8298     /* The optimizer does not know that the call sets the function value
8299        registers we stored in the result block.  We avoid problems by
8300        claiming that all hard registers are used and clobbered at this
8301        point.  */
8302     emit_insn (gen_blockage ());
8303
8304     DONE;
8305   }"
8306 )
8307
8308 (define_expand "untyped_return"
8309   [(match_operand:BLK 0 "memory_operand" "")
8310    (match_operand 1 "" "")]
8311   "TARGET_EITHER"
8312   "
8313   {
8314     int i;
8315     rtx addr = gen_reg_rtx (Pmode);
8316     rtx mem;
8317     int size = 0;
8318
8319     emit_move_insn (addr, XEXP (operands[0], 0));
8320     mem = change_address (operands[0], BLKmode, addr);
8321
8322     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8323       {
8324         HOST_WIDE_INT offset = 0;
8325         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8326
8327         if (size != 0)
8328           emit_move_insn (addr, plus_constant (addr, size));
8329
8330         mem = change_address (mem, GET_MODE (reg), NULL);
8331         if (REGNO (reg) == R0_REGNUM)
8332           {
8333             /* On thumb we have to use a write-back instruction.  */
8334             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8335                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8336             size = TARGET_ARM ? 16 : 0;
8337           }
8338         else
8339           {
8340             emit_move_insn (reg, mem);
8341             size = GET_MODE_SIZE (GET_MODE (reg));
8342           }
8343       }
8344
8345     /* Emit USE insns before the return.  */
8346     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8347       emit_insn (gen_rtx_USE (VOIDmode,
8348                               SET_DEST (XVECEXP (operands[1], 0, i))));
8349
8350     /* Construct the return.  */
8351     expand_naked_return ();
8352
8353     DONE;
8354   }"
8355 )
8356
8357 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8358 ;; all of memory.  This blocks insns from being moved across this point.
8359
8360 (define_insn "blockage"
8361   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8362   "TARGET_EITHER"
8363   ""
8364   [(set_attr "length" "0")
8365    (set_attr "type" "block")]
8366 )
8367
8368 (define_expand "casesi"
8369   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8370    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8371    (match_operand:SI 2 "const_int_operand" "")  ; total range
8372    (match_operand:SI 3 "" "")                   ; table label
8373    (match_operand:SI 4 "" "")]                  ; Out of range label
8374   "TARGET_ARM"
8375   "
8376   {
8377     rtx reg;
8378     if (operands[1] != const0_rtx)
8379       {
8380         reg = gen_reg_rtx (SImode);
8381
8382         emit_insn (gen_addsi3 (reg, operands[0],
8383                                GEN_INT (-INTVAL (operands[1]))));
8384         operands[0] = reg;
8385       }
8386
8387     if (!const_ok_for_arm (INTVAL (operands[2])))
8388       operands[2] = force_reg (SImode, operands[2]);
8389
8390     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8391                                          operands[4]));
8392     DONE;
8393   }"
8394 )
8395
8396 ;; The USE in this pattern is needed to tell flow analysis that this is
8397 ;; a CASESI insn.  It has no other purpose.
8398 (define_insn "casesi_internal"
8399   [(parallel [(set (pc)
8400                (if_then_else
8401                 (leu (match_operand:SI 0 "s_register_operand" "r")
8402                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8403                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8404                                  (label_ref (match_operand 2 "" ""))))
8405                 (label_ref (match_operand 3 "" ""))))
8406               (clobber (reg:CC CC_REGNUM))
8407               (use (label_ref (match_dup 2)))])]
8408   "TARGET_ARM"
8409   "*
8410     if (flag_pic)
8411       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8412     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8413   "
8414   [(set_attr "conds" "clob")
8415    (set_attr "length" "12")]
8416 )
8417
8418 (define_expand "indirect_jump"
8419   [(set (pc)
8420         (match_operand:SI 0 "s_register_operand" ""))]
8421   "TARGET_EITHER"
8422   ""
8423 )
8424
8425 ;; NB Never uses BX.
8426 (define_insn "*arm_indirect_jump"
8427   [(set (pc)
8428         (match_operand:SI 0 "s_register_operand" "r"))]
8429   "TARGET_ARM"
8430   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8431   [(set_attr "predicable" "yes")]
8432 )
8433
8434 (define_insn "*load_indirect_jump"
8435   [(set (pc)
8436         (match_operand:SI 0 "memory_operand" "m"))]
8437   "TARGET_ARM"
8438   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8439   [(set_attr "type" "load1")
8440    (set_attr "pool_range" "4096")
8441    (set_attr "neg_pool_range" "4084")
8442    (set_attr "predicable" "yes")]
8443 )
8444
8445 ;; NB Never uses BX.
8446 (define_insn "*thumb_indirect_jump"
8447   [(set (pc)
8448         (match_operand:SI 0 "register_operand" "l*r"))]
8449   "TARGET_THUMB"
8450   "mov\\tpc, %0"
8451   [(set_attr "conds" "clob")
8452    (set_attr "length" "2")]
8453 )
8454
8455 \f
8456 ;; Misc insns
8457
8458 (define_insn "nop"
8459   [(const_int 0)]
8460   "TARGET_EITHER"
8461   "*
8462   if (TARGET_ARM)
8463     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8464   return  \"mov\\tr8, r8\";
8465   "
8466   [(set (attr "length")
8467         (if_then_else (eq_attr "is_thumb" "yes")
8468                       (const_int 2)
8469                       (const_int 4)))]
8470 )
8471
8472 \f
8473 ;; Patterns to allow combination of arithmetic, cond code and shifts
8474
8475 (define_insn "*arith_shiftsi"
8476   [(set (match_operand:SI 0 "s_register_operand" "=r")
8477         (match_operator:SI 1 "shiftable_operator"
8478           [(match_operator:SI 3 "shift_operator"
8479              [(match_operand:SI 4 "s_register_operand" "r")
8480               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8481            (match_operand:SI 2 "s_register_operand" "r")]))]
8482   "TARGET_ARM"
8483   "%i1%?\\t%0, %2, %4%S3"
8484   [(set_attr "predicable" "yes")
8485    (set_attr "shift" "4")
8486    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8487                       (const_string "alu_shift")
8488                       (const_string "alu_shift_reg")))]
8489 )
8490
8491 (define_split
8492   [(set (match_operand:SI 0 "s_register_operand" "")
8493         (match_operator:SI 1 "shiftable_operator"
8494          [(match_operator:SI 2 "shiftable_operator"
8495            [(match_operator:SI 3 "shift_operator"
8496              [(match_operand:SI 4 "s_register_operand" "")
8497               (match_operand:SI 5 "reg_or_int_operand" "")])
8498             (match_operand:SI 6 "s_register_operand" "")])
8499           (match_operand:SI 7 "arm_rhs_operand" "")]))
8500    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8501   "TARGET_ARM"
8502   [(set (match_dup 8)
8503         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8504                          (match_dup 6)]))
8505    (set (match_dup 0)
8506         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8507   "")
8508
8509 (define_insn "*arith_shiftsi_compare0"
8510   [(set (reg:CC_NOOV CC_REGNUM)
8511         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8512                           [(match_operator:SI 3 "shift_operator"
8513                             [(match_operand:SI 4 "s_register_operand" "r")
8514                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8515                            (match_operand:SI 2 "s_register_operand" "r")])
8516                          (const_int 0)))
8517    (set (match_operand:SI 0 "s_register_operand" "=r")
8518         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8519                          (match_dup 2)]))]
8520   "TARGET_ARM"
8521   "%i1%?s\\t%0, %2, %4%S3"
8522   [(set_attr "conds" "set")
8523    (set_attr "shift" "4")
8524    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8525                       (const_string "alu_shift")
8526                       (const_string "alu_shift_reg")))]
8527 )
8528
8529 (define_insn "*arith_shiftsi_compare0_scratch"
8530   [(set (reg:CC_NOOV CC_REGNUM)
8531         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8532                           [(match_operator:SI 3 "shift_operator"
8533                             [(match_operand:SI 4 "s_register_operand" "r")
8534                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8535                            (match_operand:SI 2 "s_register_operand" "r")])
8536                          (const_int 0)))
8537    (clobber (match_scratch:SI 0 "=r"))]
8538   "TARGET_ARM"
8539   "%i1%?s\\t%0, %2, %4%S3"
8540   [(set_attr "conds" "set")
8541    (set_attr "shift" "4")
8542    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8543                       (const_string "alu_shift")
8544                       (const_string "alu_shift_reg")))]
8545 )
8546
8547 (define_insn "*sub_shiftsi"
8548   [(set (match_operand:SI 0 "s_register_operand" "=r")
8549         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8550                   (match_operator:SI 2 "shift_operator"
8551                    [(match_operand:SI 3 "s_register_operand" "r")
8552                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8553   "TARGET_ARM"
8554   "sub%?\\t%0, %1, %3%S2"
8555   [(set_attr "predicable" "yes")
8556    (set_attr "shift" "3")
8557    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8558                       (const_string "alu_shift")
8559                       (const_string "alu_shift_reg")))]
8560 )
8561
8562 (define_insn "*sub_shiftsi_compare0"
8563   [(set (reg:CC_NOOV CC_REGNUM)
8564         (compare:CC_NOOV
8565          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8566                    (match_operator:SI 2 "shift_operator"
8567                     [(match_operand:SI 3 "s_register_operand" "r")
8568                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8569          (const_int 0)))
8570    (set (match_operand:SI 0 "s_register_operand" "=r")
8571         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8572                                                  (match_dup 4)])))]
8573   "TARGET_ARM"
8574   "sub%?s\\t%0, %1, %3%S2"
8575   [(set_attr "conds" "set")
8576    (set_attr "shift" "3")
8577    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8578                       (const_string "alu_shift")
8579                       (const_string "alu_shift_reg")))]
8580 )
8581
8582 (define_insn "*sub_shiftsi_compare0_scratch"
8583   [(set (reg:CC_NOOV CC_REGNUM)
8584         (compare:CC_NOOV
8585          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8586                    (match_operator:SI 2 "shift_operator"
8587                     [(match_operand:SI 3 "s_register_operand" "r")
8588                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8589          (const_int 0)))
8590    (clobber (match_scratch:SI 0 "=r"))]
8591   "TARGET_ARM"
8592   "sub%?s\\t%0, %1, %3%S2"
8593   [(set_attr "conds" "set")
8594    (set_attr "shift" "3")
8595    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8596                       (const_string "alu_shift")
8597                       (const_string "alu_shift_reg")))]
8598 )
8599
8600 \f
8601
8602 (define_insn "*and_scc"
8603   [(set (match_operand:SI 0 "s_register_operand" "=r")
8604         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8605                  [(match_operand 3 "cc_register" "") (const_int 0)])
8606                 (match_operand:SI 2 "s_register_operand" "r")))]
8607   "TARGET_ARM"
8608   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8609   [(set_attr "conds" "use")
8610    (set_attr "length" "8")]
8611 )
8612
8613 (define_insn "*ior_scc"
8614   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8615         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8616                  [(match_operand 3 "cc_register" "") (const_int 0)])
8617                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8618   "TARGET_ARM"
8619   "@
8620    orr%d2\\t%0, %1, #1
8621    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8622   [(set_attr "conds" "use")
8623    (set_attr "length" "4,8")]
8624 )
8625
8626 (define_insn "*compare_scc"
8627   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8628         (match_operator:SI 1 "arm_comparison_operator"
8629          [(match_operand:SI 2 "s_register_operand" "r,r")
8630           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8631    (clobber (reg:CC CC_REGNUM))]
8632   "TARGET_ARM"
8633   "*
8634     if (operands[3] == const0_rtx)
8635       {
8636         if (GET_CODE (operands[1]) == LT)
8637           return \"mov\\t%0, %2, lsr #31\";
8638
8639         if (GET_CODE (operands[1]) == GE)
8640           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8641
8642         if (GET_CODE (operands[1]) == EQ)
8643           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8644       }
8645
8646     if (GET_CODE (operands[1]) == NE)
8647       {
8648         if (which_alternative == 1)
8649           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8650         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8651       }
8652     if (which_alternative == 1)
8653       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8654     else
8655       output_asm_insn (\"cmp\\t%2, %3\", operands);
8656     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8657   "
8658   [(set_attr "conds" "clob")
8659    (set_attr "length" "12")]
8660 )
8661
8662 (define_insn "*cond_move"
8663   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8664         (if_then_else:SI (match_operator 3 "equality_operator"
8665                           [(match_operator 4 "arm_comparison_operator"
8666                             [(match_operand 5 "cc_register" "") (const_int 0)])
8667                            (const_int 0)])
8668                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8669                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8670   "TARGET_ARM"
8671   "*
8672     if (GET_CODE (operands[3]) == NE)
8673       {
8674         if (which_alternative != 1)
8675           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8676         if (which_alternative != 0)
8677           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8678         return \"\";
8679       }
8680     if (which_alternative != 0)
8681       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8682     if (which_alternative != 1)
8683       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8684     return \"\";
8685   "
8686   [(set_attr "conds" "use")
8687    (set_attr "length" "4,4,8")]
8688 )
8689
8690 (define_insn "*cond_arith"
8691   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8692         (match_operator:SI 5 "shiftable_operator" 
8693          [(match_operator:SI 4 "arm_comparison_operator"
8694            [(match_operand:SI 2 "s_register_operand" "r,r")
8695             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8696           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8697    (clobber (reg:CC CC_REGNUM))]
8698   "TARGET_ARM"
8699   "*
8700     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8701       return \"%i5\\t%0, %1, %2, lsr #31\";
8702
8703     output_asm_insn (\"cmp\\t%2, %3\", operands);
8704     if (GET_CODE (operands[5]) == AND)
8705       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8706     else if (GET_CODE (operands[5]) == MINUS)
8707       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8708     else if (which_alternative != 0)
8709       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8710     return \"%i5%d4\\t%0, %1, #1\";
8711   "
8712   [(set_attr "conds" "clob")
8713    (set_attr "length" "12")]
8714 )
8715
8716 (define_insn "*cond_sub"
8717   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8718         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8719                   (match_operator:SI 4 "arm_comparison_operator"
8720                    [(match_operand:SI 2 "s_register_operand" "r,r")
8721                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8722    (clobber (reg:CC CC_REGNUM))]
8723   "TARGET_ARM"
8724   "*
8725     output_asm_insn (\"cmp\\t%2, %3\", operands);
8726     if (which_alternative != 0)
8727       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8728     return \"sub%d4\\t%0, %1, #1\";
8729   "
8730   [(set_attr "conds" "clob")
8731    (set_attr "length" "8,12")]
8732 )
8733
8734 (define_insn "*cmp_ite0"
8735   [(set (match_operand 6 "dominant_cc_register" "")
8736         (compare
8737          (if_then_else:SI
8738           (match_operator 4 "arm_comparison_operator"
8739            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8740             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8741           (match_operator:SI 5 "arm_comparison_operator"
8742            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8743             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8744           (const_int 0))
8745          (const_int 0)))]
8746   "TARGET_ARM"
8747   "*
8748   {
8749     static const char * const opcodes[4][2] =
8750     {
8751       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8752        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8753       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8754        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8755       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8756        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8757       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8758        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8759     };
8760     int swap =
8761       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8762
8763     return opcodes[which_alternative][swap];
8764   }"
8765   [(set_attr "conds" "set")
8766    (set_attr "length" "8")]
8767 )
8768
8769 (define_insn "*cmp_ite1"
8770   [(set (match_operand 6 "dominant_cc_register" "")
8771         (compare
8772          (if_then_else:SI
8773           (match_operator 4 "arm_comparison_operator"
8774            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8775             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8776           (match_operator:SI 5 "arm_comparison_operator"
8777            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8778             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8779           (const_int 1))
8780          (const_int 0)))]
8781   "TARGET_ARM"
8782   "*
8783   {
8784     static const char * const opcodes[4][2] =
8785     {
8786       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8787        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8788       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8789        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8790       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8791        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8792       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8793        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8794     };
8795     int swap =
8796       comparison_dominates_p (GET_CODE (operands[5]),
8797                               reverse_condition (GET_CODE (operands[4])));
8798
8799     return opcodes[which_alternative][swap];
8800   }"
8801   [(set_attr "conds" "set")
8802    (set_attr "length" "8")]
8803 )
8804
8805 (define_insn "*cmp_and"
8806   [(set (match_operand 6 "dominant_cc_register" "")
8807         (compare
8808          (and:SI
8809           (match_operator 4 "arm_comparison_operator"
8810            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8811             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8812           (match_operator:SI 5 "arm_comparison_operator"
8813            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8814             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8815          (const_int 0)))]
8816   "TARGET_ARM"
8817   "*
8818   {
8819     static const char *const opcodes[4][2] =
8820     {
8821       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8822        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8823       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8824        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8825       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8826        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8827       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8828        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8829     };
8830     int swap =
8831       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8832
8833     return opcodes[which_alternative][swap];
8834   }"
8835   [(set_attr "conds" "set")
8836    (set_attr "predicable" "no")
8837    (set_attr "length" "8")]
8838 )
8839
8840 (define_insn "*cmp_ior"
8841   [(set (match_operand 6 "dominant_cc_register" "")
8842         (compare
8843          (ior:SI
8844           (match_operator 4 "arm_comparison_operator"
8845            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8846             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8847           (match_operator:SI 5 "arm_comparison_operator"
8848            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8849             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8850          (const_int 0)))]
8851   "TARGET_ARM"
8852   "*
8853 {
8854   static const char *const opcodes[4][2] =
8855   {
8856     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8857      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8858     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8859      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8860     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8861      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8862     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8863      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8864   };
8865   int swap =
8866     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8867
8868   return opcodes[which_alternative][swap];
8869 }
8870 "
8871   [(set_attr "conds" "set")
8872    (set_attr "length" "8")]
8873 )
8874
8875 (define_insn_and_split "*ior_scc_scc"
8876   [(set (match_operand:SI 0 "s_register_operand" "=r")
8877         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8878                  [(match_operand:SI 1 "s_register_operand" "r")
8879                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8880                 (match_operator:SI 6 "arm_comparison_operator"
8881                  [(match_operand:SI 4 "s_register_operand" "r")
8882                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8883    (clobber (reg:CC CC_REGNUM))]
8884   "TARGET_ARM
8885    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8886        != CCmode)"
8887   "#"
8888   "TARGET_ARM && reload_completed"
8889   [(set (match_dup 7)
8890         (compare
8891          (ior:SI
8892           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8893           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8894          (const_int 0)))
8895    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8896   "operands[7]
8897      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8898                                                   DOM_CC_X_OR_Y),
8899                     CC_REGNUM);"
8900   [(set_attr "conds" "clob")
8901    (set_attr "length" "16")])
8902
8903 ; If the above pattern is followed by a CMP insn, then the compare is 
8904 ; redundant, since we can rework the conditional instruction that follows.
8905 (define_insn_and_split "*ior_scc_scc_cmp"
8906   [(set (match_operand 0 "dominant_cc_register" "")
8907         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8908                           [(match_operand:SI 1 "s_register_operand" "r")
8909                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8910                          (match_operator:SI 6 "arm_comparison_operator"
8911                           [(match_operand:SI 4 "s_register_operand" "r")
8912                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8913                  (const_int 0)))
8914    (set (match_operand:SI 7 "s_register_operand" "=r")
8915         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8916                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8917   "TARGET_ARM"
8918   "#"
8919   "TARGET_ARM && reload_completed"
8920   [(set (match_dup 0)
8921         (compare
8922          (ior:SI
8923           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8924           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8925          (const_int 0)))
8926    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8927   ""
8928   [(set_attr "conds" "set")
8929    (set_attr "length" "16")])
8930
8931 (define_insn_and_split "*and_scc_scc"
8932   [(set (match_operand:SI 0 "s_register_operand" "=r")
8933         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8934                  [(match_operand:SI 1 "s_register_operand" "r")
8935                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8936                 (match_operator:SI 6 "arm_comparison_operator"
8937                  [(match_operand:SI 4 "s_register_operand" "r")
8938                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8939    (clobber (reg:CC CC_REGNUM))]
8940   "TARGET_ARM
8941    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8942        != CCmode)"
8943   "#"
8944   "TARGET_ARM && reload_completed
8945    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8946        != CCmode)"
8947   [(set (match_dup 7)
8948         (compare
8949          (and:SI
8950           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8951           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8952          (const_int 0)))
8953    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8954   "operands[7]
8955      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8956                                                   DOM_CC_X_AND_Y),
8957                     CC_REGNUM);"
8958   [(set_attr "conds" "clob")
8959    (set_attr "length" "16")])
8960
8961 ; If the above pattern is followed by a CMP insn, then the compare is 
8962 ; redundant, since we can rework the conditional instruction that follows.
8963 (define_insn_and_split "*and_scc_scc_cmp"
8964   [(set (match_operand 0 "dominant_cc_register" "")
8965         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8966                           [(match_operand:SI 1 "s_register_operand" "r")
8967                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8968                          (match_operator:SI 6 "arm_comparison_operator"
8969                           [(match_operand:SI 4 "s_register_operand" "r")
8970                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8971                  (const_int 0)))
8972    (set (match_operand:SI 7 "s_register_operand" "=r")
8973         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8974                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8975   "TARGET_ARM"
8976   "#"
8977   "TARGET_ARM && reload_completed"
8978   [(set (match_dup 0)
8979         (compare
8980          (and:SI
8981           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8982           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8983          (const_int 0)))
8984    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8985   ""
8986   [(set_attr "conds" "set")
8987    (set_attr "length" "16")])
8988
8989 ;; If there is no dominance in the comparison, then we can still save an
8990 ;; instruction in the AND case, since we can know that the second compare
8991 ;; need only zero the value if false (if true, then the value is already
8992 ;; correct).
8993 (define_insn_and_split "*and_scc_scc_nodom"
8994   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8995         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8996                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8997                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8998                 (match_operator:SI 6 "arm_comparison_operator"
8999                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
9000                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9001    (clobber (reg:CC CC_REGNUM))]
9002   "TARGET_ARM
9003    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9004        == CCmode)"
9005   "#"
9006   "TARGET_ARM && reload_completed"
9007   [(parallel [(set (match_dup 0)
9008                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9009               (clobber (reg:CC CC_REGNUM))])
9010    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9011    (set (match_dup 0)
9012         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9013                          (match_dup 0)
9014                          (const_int 0)))]
9015   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9016                                               operands[4], operands[5]),
9017                               CC_REGNUM);
9018    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9019                                   operands[5]);"
9020   [(set_attr "conds" "clob")
9021    (set_attr "length" "20")])
9022
9023 (define_split
9024   [(set (reg:CC_NOOV CC_REGNUM)
9025         (compare:CC_NOOV (ior:SI
9026                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9027                                   (const_int 1))
9028                           (match_operator:SI 1 "comparison_operator"
9029                            [(match_operand:SI 2 "s_register_operand" "")
9030                             (match_operand:SI 3 "arm_add_operand" "")]))
9031                          (const_int 0)))
9032    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9033   "TARGET_ARM"
9034   [(set (match_dup 4)
9035         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9036                 (match_dup 0)))
9037    (set (reg:CC_NOOV CC_REGNUM)
9038         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9039                          (const_int 0)))]
9040   "")
9041
9042 (define_split
9043   [(set (reg:CC_NOOV CC_REGNUM)
9044         (compare:CC_NOOV (ior:SI
9045                           (match_operator:SI 1 "comparison_operator"
9046                            [(match_operand:SI 2 "s_register_operand" "")
9047                             (match_operand:SI 3 "arm_add_operand" "")])
9048                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9049                                   (const_int 1)))
9050                          (const_int 0)))
9051    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9052   "TARGET_ARM"
9053   [(set (match_dup 4)
9054         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9055                 (match_dup 0)))
9056    (set (reg:CC_NOOV CC_REGNUM)
9057         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9058                          (const_int 0)))]
9059   "")
9060
9061 (define_insn "*negscc"
9062   [(set (match_operand:SI 0 "s_register_operand" "=r")
9063         (neg:SI (match_operator 3 "arm_comparison_operator"
9064                  [(match_operand:SI 1 "s_register_operand" "r")
9065                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9066    (clobber (reg:CC CC_REGNUM))]
9067   "TARGET_ARM"
9068   "*
9069   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
9070     return \"mov\\t%0, %1, asr #31\";
9071
9072   if (GET_CODE (operands[3]) == NE)
9073     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9074
9075   if (GET_CODE (operands[3]) == GT)
9076     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
9077
9078   output_asm_insn (\"cmp\\t%1, %2\", operands);
9079   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9080   return \"mvn%d3\\t%0, #0\";
9081   "
9082   [(set_attr "conds" "clob")
9083    (set_attr "length" "12")]
9084 )
9085
9086 (define_insn "movcond"
9087   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9088         (if_then_else:SI
9089          (match_operator 5 "arm_comparison_operator"
9090           [(match_operand:SI 3 "s_register_operand" "r,r,r")
9091            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9092          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9093          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9094    (clobber (reg:CC CC_REGNUM))]
9095   "TARGET_ARM"
9096   "*
9097   if (GET_CODE (operands[5]) == LT
9098       && (operands[4] == const0_rtx))
9099     {
9100       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9101         {
9102           if (operands[2] == const0_rtx)
9103             return \"and\\t%0, %1, %3, asr #31\";
9104           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9105         }
9106       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9107         {
9108           if (operands[1] == const0_rtx)
9109             return \"bic\\t%0, %2, %3, asr #31\";
9110           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9111         }
9112       /* The only case that falls through to here is when both ops 1 & 2
9113          are constants.  */
9114     }
9115
9116   if (GET_CODE (operands[5]) == GE
9117       && (operands[4] == const0_rtx))
9118     {
9119       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9120         {
9121           if (operands[2] == const0_rtx)
9122             return \"bic\\t%0, %1, %3, asr #31\";
9123           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9124         }
9125       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9126         {
9127           if (operands[1] == const0_rtx)
9128             return \"and\\t%0, %2, %3, asr #31\";
9129           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9130         }
9131       /* The only case that falls through to here is when both ops 1 & 2
9132          are constants.  */
9133     }
9134   if (GET_CODE (operands[4]) == CONST_INT
9135       && !const_ok_for_arm (INTVAL (operands[4])))
9136     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9137   else
9138     output_asm_insn (\"cmp\\t%3, %4\", operands);
9139   if (which_alternative != 0)
9140     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9141   if (which_alternative != 1)
9142     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9143   return \"\";
9144   "
9145   [(set_attr "conds" "clob")
9146    (set_attr "length" "8,8,12")]
9147 )
9148
9149 (define_insn "*ifcompare_plus_move"
9150   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9151         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9152                           [(match_operand:SI 4 "s_register_operand" "r,r")
9153                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9154                          (plus:SI
9155                           (match_operand:SI 2 "s_register_operand" "r,r")
9156                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9157                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9158    (clobber (reg:CC CC_REGNUM))]
9159   "TARGET_ARM"
9160   "#"
9161   [(set_attr "conds" "clob")
9162    (set_attr "length" "8,12")]
9163 )
9164
9165 (define_insn "*if_plus_move"
9166   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9167         (if_then_else:SI
9168          (match_operator 4 "arm_comparison_operator"
9169           [(match_operand 5 "cc_register" "") (const_int 0)])
9170          (plus:SI
9171           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9172           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9173          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9174   "TARGET_ARM"
9175   "@
9176    add%d4\\t%0, %2, %3
9177    sub%d4\\t%0, %2, #%n3
9178    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9179    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9180   [(set_attr "conds" "use")
9181    (set_attr "length" "4,4,8,8")
9182    (set_attr "type" "*,*,*,*")]
9183 )
9184
9185 (define_insn "*ifcompare_move_plus"
9186   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9187         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9188                           [(match_operand:SI 4 "s_register_operand" "r,r")
9189                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9190                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9191                          (plus:SI
9192                           (match_operand:SI 2 "s_register_operand" "r,r")
9193                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9194    (clobber (reg:CC CC_REGNUM))]
9195   "TARGET_ARM"
9196   "#"
9197   [(set_attr "conds" "clob")
9198    (set_attr "length" "8,12")]
9199 )
9200
9201 (define_insn "*if_move_plus"
9202   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9203         (if_then_else:SI
9204          (match_operator 4 "arm_comparison_operator"
9205           [(match_operand 5 "cc_register" "") (const_int 0)])
9206          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9207          (plus:SI
9208           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9209           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9210   "TARGET_ARM"
9211   "@
9212    add%D4\\t%0, %2, %3
9213    sub%D4\\t%0, %2, #%n3
9214    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9215    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9216   [(set_attr "conds" "use")
9217    (set_attr "length" "4,4,8,8")
9218    (set_attr "type" "*,*,*,*")]
9219 )
9220
9221 (define_insn "*ifcompare_arith_arith"
9222   [(set (match_operand:SI 0 "s_register_operand" "=r")
9223         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9224                           [(match_operand:SI 5 "s_register_operand" "r")
9225                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9226                          (match_operator:SI 8 "shiftable_operator"
9227                           [(match_operand:SI 1 "s_register_operand" "r")
9228                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9229                          (match_operator:SI 7 "shiftable_operator"
9230                           [(match_operand:SI 3 "s_register_operand" "r")
9231                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9232    (clobber (reg:CC CC_REGNUM))]
9233   "TARGET_ARM"
9234   "#"
9235   [(set_attr "conds" "clob")
9236    (set_attr "length" "12")]
9237 )
9238
9239 (define_insn "*if_arith_arith"
9240   [(set (match_operand:SI 0 "s_register_operand" "=r")
9241         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9242                           [(match_operand 8 "cc_register" "") (const_int 0)])
9243                          (match_operator:SI 6 "shiftable_operator"
9244                           [(match_operand:SI 1 "s_register_operand" "r")
9245                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9246                          (match_operator:SI 7 "shiftable_operator"
9247                           [(match_operand:SI 3 "s_register_operand" "r")
9248                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9249   "TARGET_ARM"
9250   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9251   [(set_attr "conds" "use")
9252    (set_attr "length" "8")]
9253 )
9254
9255 (define_insn "*ifcompare_arith_move"
9256   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9257         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9258                           [(match_operand:SI 2 "s_register_operand" "r,r")
9259                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9260                          (match_operator:SI 7 "shiftable_operator"
9261                           [(match_operand:SI 4 "s_register_operand" "r,r")
9262                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9263                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9264    (clobber (reg:CC CC_REGNUM))]
9265   "TARGET_ARM"
9266   "*
9267   /* If we have an operation where (op x 0) is the identity operation and
9268      the conditional operator is LT or GE and we are comparing against zero and
9269      everything is in registers then we can do this in two instructions.  */
9270   if (operands[3] == const0_rtx
9271       && GET_CODE (operands[7]) != AND
9272       && GET_CODE (operands[5]) == REG
9273       && GET_CODE (operands[1]) == REG 
9274       && REGNO (operands[1]) == REGNO (operands[4])
9275       && REGNO (operands[4]) != REGNO (operands[0]))
9276     {
9277       if (GET_CODE (operands[6]) == LT)
9278         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9279       else if (GET_CODE (operands[6]) == GE)
9280         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9281     }
9282   if (GET_CODE (operands[3]) == CONST_INT
9283       && !const_ok_for_arm (INTVAL (operands[3])))
9284     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9285   else
9286     output_asm_insn (\"cmp\\t%2, %3\", operands);
9287   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9288   if (which_alternative != 0)
9289     return \"mov%D6\\t%0, %1\";
9290   return \"\";
9291   "
9292   [(set_attr "conds" "clob")
9293    (set_attr "length" "8,12")]
9294 )
9295
9296 (define_insn "*if_arith_move"
9297   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9298         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9299                           [(match_operand 6 "cc_register" "") (const_int 0)])
9300                          (match_operator:SI 5 "shiftable_operator"
9301                           [(match_operand:SI 2 "s_register_operand" "r,r")
9302                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9303                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9304   "TARGET_ARM"
9305   "@
9306    %I5%d4\\t%0, %2, %3
9307    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9308   [(set_attr "conds" "use")
9309    (set_attr "length" "4,8")
9310    (set_attr "type" "*,*")]
9311 )
9312
9313 (define_insn "*ifcompare_move_arith"
9314   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9315         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9316                           [(match_operand:SI 4 "s_register_operand" "r,r")
9317                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9318                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9319                          (match_operator:SI 7 "shiftable_operator"
9320                           [(match_operand:SI 2 "s_register_operand" "r,r")
9321                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9322    (clobber (reg:CC CC_REGNUM))]
9323   "TARGET_ARM"
9324   "*
9325   /* If we have an operation where (op x 0) is the identity operation and
9326      the conditional operator is LT or GE and we are comparing against zero and
9327      everything is in registers then we can do this in two instructions */
9328   if (operands[5] == const0_rtx
9329       && GET_CODE (operands[7]) != AND
9330       && GET_CODE (operands[3]) == REG
9331       && GET_CODE (operands[1]) == REG 
9332       && REGNO (operands[1]) == REGNO (operands[2])
9333       && REGNO (operands[2]) != REGNO (operands[0]))
9334     {
9335       if (GET_CODE (operands[6]) == GE)
9336         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9337       else if (GET_CODE (operands[6]) == LT)
9338         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9339     }
9340
9341   if (GET_CODE (operands[5]) == CONST_INT
9342       && !const_ok_for_arm (INTVAL (operands[5])))
9343     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9344   else
9345     output_asm_insn (\"cmp\\t%4, %5\", operands);
9346
9347   if (which_alternative != 0)
9348     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9349   return \"%I7%D6\\t%0, %2, %3\";
9350   "
9351   [(set_attr "conds" "clob")
9352    (set_attr "length" "8,12")]
9353 )
9354
9355 (define_insn "*if_move_arith"
9356   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9357         (if_then_else:SI
9358          (match_operator 4 "arm_comparison_operator"
9359           [(match_operand 6 "cc_register" "") (const_int 0)])
9360          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9361          (match_operator:SI 5 "shiftable_operator"
9362           [(match_operand:SI 2 "s_register_operand" "r,r")
9363            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9364   "TARGET_ARM"
9365   "@
9366    %I5%D4\\t%0, %2, %3
9367    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9368   [(set_attr "conds" "use")
9369    (set_attr "length" "4,8")
9370    (set_attr "type" "*,*")]
9371 )
9372
9373 (define_insn "*ifcompare_move_not"
9374   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9375         (if_then_else:SI
9376          (match_operator 5 "arm_comparison_operator"
9377           [(match_operand:SI 3 "s_register_operand" "r,r")
9378            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9379          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9380          (not:SI
9381           (match_operand:SI 2 "s_register_operand" "r,r"))))
9382    (clobber (reg:CC CC_REGNUM))]
9383   "TARGET_ARM"
9384   "#"
9385   [(set_attr "conds" "clob")
9386    (set_attr "length" "8,12")]
9387 )
9388
9389 (define_insn "*if_move_not"
9390   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9391         (if_then_else:SI
9392          (match_operator 4 "arm_comparison_operator"
9393           [(match_operand 3 "cc_register" "") (const_int 0)])
9394          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9395          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9396   "TARGET_ARM"
9397   "@
9398    mvn%D4\\t%0, %2
9399    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9400    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9401   [(set_attr "conds" "use")
9402    (set_attr "length" "4,8,8")]
9403 )
9404
9405 (define_insn "*ifcompare_not_move"
9406   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9407         (if_then_else:SI 
9408          (match_operator 5 "arm_comparison_operator"
9409           [(match_operand:SI 3 "s_register_operand" "r,r")
9410            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9411          (not:SI
9412           (match_operand:SI 2 "s_register_operand" "r,r"))
9413          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9414    (clobber (reg:CC CC_REGNUM))]
9415   "TARGET_ARM"
9416   "#"
9417   [(set_attr "conds" "clob")
9418    (set_attr "length" "8,12")]
9419 )
9420
9421 (define_insn "*if_not_move"
9422   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9423         (if_then_else:SI
9424          (match_operator 4 "arm_comparison_operator"
9425           [(match_operand 3 "cc_register" "") (const_int 0)])
9426          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9427          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9428   "TARGET_ARM"
9429   "@
9430    mvn%d4\\t%0, %2
9431    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9432    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9433   [(set_attr "conds" "use")
9434    (set_attr "length" "4,8,8")]
9435 )
9436
9437 (define_insn "*ifcompare_shift_move"
9438   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9439         (if_then_else:SI
9440          (match_operator 6 "arm_comparison_operator"
9441           [(match_operand:SI 4 "s_register_operand" "r,r")
9442            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9443          (match_operator:SI 7 "shift_operator"
9444           [(match_operand:SI 2 "s_register_operand" "r,r")
9445            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9446          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9447    (clobber (reg:CC CC_REGNUM))]
9448   "TARGET_ARM"
9449   "#"
9450   [(set_attr "conds" "clob")
9451    (set_attr "length" "8,12")]
9452 )
9453
9454 (define_insn "*if_shift_move"
9455   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9456         (if_then_else:SI
9457          (match_operator 5 "arm_comparison_operator"
9458           [(match_operand 6 "cc_register" "") (const_int 0)])
9459          (match_operator:SI 4 "shift_operator"
9460           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9461            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9462          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9463   "TARGET_ARM"
9464   "@
9465    mov%d5\\t%0, %2%S4
9466    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9467    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9468   [(set_attr "conds" "use")
9469    (set_attr "shift" "2")
9470    (set_attr "length" "4,8,8")
9471    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9472                       (const_string "alu_shift")
9473                       (const_string "alu_shift_reg")))]
9474 )
9475
9476 (define_insn "*ifcompare_move_shift"
9477   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9478         (if_then_else:SI
9479          (match_operator 6 "arm_comparison_operator"
9480           [(match_operand:SI 4 "s_register_operand" "r,r")
9481            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9482          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9483          (match_operator:SI 7 "shift_operator"
9484           [(match_operand:SI 2 "s_register_operand" "r,r")
9485            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9486    (clobber (reg:CC CC_REGNUM))]
9487   "TARGET_ARM"
9488   "#"
9489   [(set_attr "conds" "clob")
9490    (set_attr "length" "8,12")]
9491 )
9492
9493 (define_insn "*if_move_shift"
9494   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9495         (if_then_else:SI
9496          (match_operator 5 "arm_comparison_operator"
9497           [(match_operand 6 "cc_register" "") (const_int 0)])
9498          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9499          (match_operator:SI 4 "shift_operator"
9500           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9501            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9502   "TARGET_ARM"
9503   "@
9504    mov%D5\\t%0, %2%S4
9505    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9506    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9507   [(set_attr "conds" "use")
9508    (set_attr "shift" "2")
9509    (set_attr "length" "4,8,8")
9510    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9511                       (const_string "alu_shift")
9512                       (const_string "alu_shift_reg")))]
9513 )
9514
9515 (define_insn "*ifcompare_shift_shift"
9516   [(set (match_operand:SI 0 "s_register_operand" "=r")
9517         (if_then_else:SI
9518          (match_operator 7 "arm_comparison_operator"
9519           [(match_operand:SI 5 "s_register_operand" "r")
9520            (match_operand:SI 6 "arm_add_operand" "rIL")])
9521          (match_operator:SI 8 "shift_operator"
9522           [(match_operand:SI 1 "s_register_operand" "r")
9523            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9524          (match_operator:SI 9 "shift_operator"
9525           [(match_operand:SI 3 "s_register_operand" "r")
9526            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9527    (clobber (reg:CC CC_REGNUM))]
9528   "TARGET_ARM"
9529   "#"
9530   [(set_attr "conds" "clob")
9531    (set_attr "length" "12")]
9532 )
9533
9534 (define_insn "*if_shift_shift"
9535   [(set (match_operand:SI 0 "s_register_operand" "=r")
9536         (if_then_else:SI
9537          (match_operator 5 "arm_comparison_operator"
9538           [(match_operand 8 "cc_register" "") (const_int 0)])
9539          (match_operator:SI 6 "shift_operator"
9540           [(match_operand:SI 1 "s_register_operand" "r")
9541            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9542          (match_operator:SI 7 "shift_operator"
9543           [(match_operand:SI 3 "s_register_operand" "r")
9544            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9545   "TARGET_ARM"
9546   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9547   [(set_attr "conds" "use")
9548    (set_attr "shift" "1")
9549    (set_attr "length" "8")
9550    (set (attr "type") (if_then_else
9551                         (and (match_operand 2 "const_int_operand" "")
9552                              (match_operand 4 "const_int_operand" ""))
9553                       (const_string "alu_shift")
9554                       (const_string "alu_shift_reg")))]
9555 )
9556
9557 (define_insn "*ifcompare_not_arith"
9558   [(set (match_operand:SI 0 "s_register_operand" "=r")
9559         (if_then_else:SI
9560          (match_operator 6 "arm_comparison_operator"
9561           [(match_operand:SI 4 "s_register_operand" "r")
9562            (match_operand:SI 5 "arm_add_operand" "rIL")])
9563          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9564          (match_operator:SI 7 "shiftable_operator"
9565           [(match_operand:SI 2 "s_register_operand" "r")
9566            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9567    (clobber (reg:CC CC_REGNUM))]
9568   "TARGET_ARM"
9569   "#"
9570   [(set_attr "conds" "clob")
9571    (set_attr "length" "12")]
9572 )
9573
9574 (define_insn "*if_not_arith"
9575   [(set (match_operand:SI 0 "s_register_operand" "=r")
9576         (if_then_else:SI
9577          (match_operator 5 "arm_comparison_operator"
9578           [(match_operand 4 "cc_register" "") (const_int 0)])
9579          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9580          (match_operator:SI 6 "shiftable_operator"
9581           [(match_operand:SI 2 "s_register_operand" "r")
9582            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9583   "TARGET_ARM"
9584   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9585   [(set_attr "conds" "use")
9586    (set_attr "length" "8")]
9587 )
9588
9589 (define_insn "*ifcompare_arith_not"
9590   [(set (match_operand:SI 0 "s_register_operand" "=r")
9591         (if_then_else:SI
9592          (match_operator 6 "arm_comparison_operator"
9593           [(match_operand:SI 4 "s_register_operand" "r")
9594            (match_operand:SI 5 "arm_add_operand" "rIL")])
9595          (match_operator:SI 7 "shiftable_operator"
9596           [(match_operand:SI 2 "s_register_operand" "r")
9597            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9598          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9599    (clobber (reg:CC CC_REGNUM))]
9600   "TARGET_ARM"
9601   "#"
9602   [(set_attr "conds" "clob")
9603    (set_attr "length" "12")]
9604 )
9605
9606 (define_insn "*if_arith_not"
9607   [(set (match_operand:SI 0 "s_register_operand" "=r")
9608         (if_then_else:SI
9609          (match_operator 5 "arm_comparison_operator"
9610           [(match_operand 4 "cc_register" "") (const_int 0)])
9611          (match_operator:SI 6 "shiftable_operator"
9612           [(match_operand:SI 2 "s_register_operand" "r")
9613            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9614          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9615   "TARGET_ARM"
9616   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9617   [(set_attr "conds" "use")
9618    (set_attr "length" "8")]
9619 )
9620
9621 (define_insn "*ifcompare_neg_move"
9622   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9623         (if_then_else:SI
9624          (match_operator 5 "arm_comparison_operator"
9625           [(match_operand:SI 3 "s_register_operand" "r,r")
9626            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9627          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9628          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9629    (clobber (reg:CC CC_REGNUM))]
9630   "TARGET_ARM"
9631   "#"
9632   [(set_attr "conds" "clob")
9633    (set_attr "length" "8,12")]
9634 )
9635
9636 (define_insn "*if_neg_move"
9637   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9638         (if_then_else:SI
9639          (match_operator 4 "arm_comparison_operator"
9640           [(match_operand 3 "cc_register" "") (const_int 0)])
9641          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9642          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9643   "TARGET_ARM"
9644   "@
9645    rsb%d4\\t%0, %2, #0
9646    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9647    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9648   [(set_attr "conds" "use")
9649    (set_attr "length" "4,8,8")]
9650 )
9651
9652 (define_insn "*ifcompare_move_neg"
9653   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9654         (if_then_else:SI
9655          (match_operator 5 "arm_comparison_operator"
9656           [(match_operand:SI 3 "s_register_operand" "r,r")
9657            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9658          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9659          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9660    (clobber (reg:CC CC_REGNUM))]
9661   "TARGET_ARM"
9662   "#"
9663   [(set_attr "conds" "clob")
9664    (set_attr "length" "8,12")]
9665 )
9666
9667 (define_insn "*if_move_neg"
9668   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9669         (if_then_else:SI
9670          (match_operator 4 "arm_comparison_operator"
9671           [(match_operand 3 "cc_register" "") (const_int 0)])
9672          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9673          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9674   "TARGET_ARM"
9675   "@
9676    rsb%D4\\t%0, %2, #0
9677    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9678    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9679   [(set_attr "conds" "use")
9680    (set_attr "length" "4,8,8")]
9681 )
9682
9683 (define_insn "*arith_adjacentmem"
9684   [(set (match_operand:SI 0 "s_register_operand" "=r")
9685         (match_operator:SI 1 "shiftable_operator"
9686          [(match_operand:SI 2 "memory_operand" "m")
9687           (match_operand:SI 3 "memory_operand" "m")]))
9688    (clobber (match_scratch:SI 4 "=r"))]
9689   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9690   "*
9691   {
9692     rtx ldm[3];
9693     rtx arith[4];
9694     rtx base_reg;
9695     HOST_WIDE_INT val1 = 0, val2 = 0;
9696
9697     if (REGNO (operands[0]) > REGNO (operands[4]))
9698       {
9699         ldm[1] = operands[4];
9700         ldm[2] = operands[0];
9701       }
9702     else
9703       {
9704         ldm[1] = operands[0];
9705         ldm[2] = operands[4];
9706       }
9707
9708     base_reg = XEXP (operands[2], 0);
9709
9710     if (!REG_P (base_reg))
9711       {
9712         val1 = INTVAL (XEXP (base_reg, 1));
9713         base_reg = XEXP (base_reg, 0);
9714       }
9715
9716     if (!REG_P (XEXP (operands[3], 0)))
9717       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9718
9719     arith[0] = operands[0];
9720     arith[3] = operands[1];
9721
9722     if (val1 < val2)
9723       {
9724         arith[1] = ldm[1];
9725         arith[2] = ldm[2];
9726       }
9727     else
9728       {
9729         arith[1] = ldm[2];
9730         arith[2] = ldm[1];
9731       }
9732
9733     ldm[0] = base_reg;
9734     if (val1 !=0 && val2 != 0)
9735       {
9736         rtx ops[3];
9737
9738         if (val1 == 4 || val2 == 4)
9739           /* Other val must be 8, since we know they are adjacent and neither
9740              is zero.  */
9741           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9742         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
9743           {
9744             ldm[0] = ops[0] = operands[4];
9745             ops[1] = base_reg;
9746             ops[2] = GEN_INT (val1);
9747             output_add_immediate (ops);
9748             if (val1 < val2)
9749               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9750             else
9751               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9752           }
9753         else
9754           {
9755             /* Offset is out of range for a single add, so use two ldr.  */
9756             ops[0] = ldm[1];
9757             ops[1] = base_reg;
9758             ops[2] = GEN_INT (val1);
9759             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9760             ops[0] = ldm[2];
9761             ops[2] = GEN_INT (val2);
9762             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9763           }
9764       }
9765     else if (val1 != 0)
9766       {
9767         if (val1 < val2)
9768           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9769         else
9770           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9771       }
9772     else
9773       {
9774         if (val1 < val2)
9775           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9776         else
9777           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9778       }
9779     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9780     return \"\";
9781   }"
9782   [(set_attr "length" "12")
9783    (set_attr "predicable" "yes")
9784    (set_attr "type" "load1")]
9785 )
9786
9787 ; This pattern is never tried by combine, so do it as a peephole
9788
9789 (define_peephole2
9790   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9791         (match_operand:SI 1 "arm_general_register_operand" ""))
9792    (set (reg:CC CC_REGNUM)
9793         (compare:CC (match_dup 1) (const_int 0)))]
9794   "TARGET_ARM"
9795   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9796               (set (match_dup 0) (match_dup 1))])]
9797   ""
9798 )
9799
9800 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9801 ; reversed, check that the memory references aren't volatile.
9802
9803 (define_peephole
9804   [(set (match_operand:SI 0 "s_register_operand" "=r")
9805         (match_operand:SI 4 "memory_operand" "m"))
9806    (set (match_operand:SI 1 "s_register_operand" "=r")
9807         (match_operand:SI 5 "memory_operand" "m"))
9808    (set (match_operand:SI 2 "s_register_operand" "=r")
9809         (match_operand:SI 6 "memory_operand" "m"))
9810    (set (match_operand:SI 3 "s_register_operand" "=r")
9811         (match_operand:SI 7 "memory_operand" "m"))]
9812   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9813   "*
9814   return emit_ldm_seq (operands, 4);
9815   "
9816 )
9817
9818 (define_peephole
9819   [(set (match_operand:SI 0 "s_register_operand" "=r")
9820         (match_operand:SI 3 "memory_operand" "m"))
9821    (set (match_operand:SI 1 "s_register_operand" "=r")
9822         (match_operand:SI 4 "memory_operand" "m"))
9823    (set (match_operand:SI 2 "s_register_operand" "=r")
9824         (match_operand:SI 5 "memory_operand" "m"))]
9825   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9826   "*
9827   return emit_ldm_seq (operands, 3);
9828   "
9829 )
9830
9831 (define_peephole
9832   [(set (match_operand:SI 0 "s_register_operand" "=r")
9833         (match_operand:SI 2 "memory_operand" "m"))
9834    (set (match_operand:SI 1 "s_register_operand" "=r")
9835         (match_operand:SI 3 "memory_operand" "m"))]
9836   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9837   "*
9838   return emit_ldm_seq (operands, 2);
9839   "
9840 )
9841
9842 (define_peephole
9843   [(set (match_operand:SI 4 "memory_operand" "=m")
9844         (match_operand:SI 0 "s_register_operand" "r"))
9845    (set (match_operand:SI 5 "memory_operand" "=m")
9846         (match_operand:SI 1 "s_register_operand" "r"))
9847    (set (match_operand:SI 6 "memory_operand" "=m")
9848         (match_operand:SI 2 "s_register_operand" "r"))
9849    (set (match_operand:SI 7 "memory_operand" "=m")
9850         (match_operand:SI 3 "s_register_operand" "r"))]
9851   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9852   "*
9853   return emit_stm_seq (operands, 4);
9854   "
9855 )
9856
9857 (define_peephole
9858   [(set (match_operand:SI 3 "memory_operand" "=m")
9859         (match_operand:SI 0 "s_register_operand" "r"))
9860    (set (match_operand:SI 4 "memory_operand" "=m")
9861         (match_operand:SI 1 "s_register_operand" "r"))
9862    (set (match_operand:SI 5 "memory_operand" "=m")
9863         (match_operand:SI 2 "s_register_operand" "r"))]
9864   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9865   "*
9866   return emit_stm_seq (operands, 3);
9867   "
9868 )
9869
9870 (define_peephole
9871   [(set (match_operand:SI 2 "memory_operand" "=m")
9872         (match_operand:SI 0 "s_register_operand" "r"))
9873    (set (match_operand:SI 3 "memory_operand" "=m")
9874         (match_operand:SI 1 "s_register_operand" "r"))]
9875   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9876   "*
9877   return emit_stm_seq (operands, 2);
9878   "
9879 )
9880
9881 (define_split
9882   [(set (match_operand:SI 0 "s_register_operand" "")
9883         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9884                        (const_int 0))
9885                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9886                          [(match_operand:SI 3 "s_register_operand" "")
9887                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9888    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9889   "TARGET_ARM"
9890   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9891    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9892                               (match_dup 5)))]
9893   ""
9894 )
9895
9896 ;; This split can be used because CC_Z mode implies that the following
9897 ;; branch will be an equality, or an unsigned inequality, so the sign
9898 ;; extension is not needed.
9899
9900 (define_split
9901   [(set (reg:CC_Z CC_REGNUM)
9902         (compare:CC_Z
9903          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9904                     (const_int 24))
9905          (match_operand 1 "const_int_operand" "")))
9906    (clobber (match_scratch:SI 2 ""))]
9907   "TARGET_ARM
9908    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9909        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9910   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9911    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9912   "
9913   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9914   "
9915 )
9916
9917 (define_expand "prologue"
9918   [(clobber (const_int 0))]
9919   "TARGET_EITHER"
9920   "if (TARGET_ARM)
9921      arm_expand_prologue ();
9922    else
9923      thumb_expand_prologue ();
9924   DONE;
9925   "
9926 )
9927
9928 (define_expand "epilogue"
9929   [(clobber (const_int 0))]
9930   "TARGET_EITHER"
9931   "
9932   if (current_function_calls_eh_return)
9933     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9934   if (TARGET_THUMB)
9935     thumb_expand_epilogue ();
9936   else if (USE_RETURN_INSN (FALSE))
9937     {
9938       emit_jump_insn (gen_return ());
9939       DONE;
9940     }
9941   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9942         gen_rtvec (1,
9943                 gen_rtx_RETURN (VOIDmode)),
9944         VUNSPEC_EPILOGUE));
9945   DONE;
9946   "
9947 )
9948
9949 ;; Note - although unspec_volatile's USE all hard registers,
9950 ;; USEs are ignored after relaod has completed.  Thus we need
9951 ;; to add an unspec of the link register to ensure that flow
9952 ;; does not think that it is unused by the sibcall branch that
9953 ;; will replace the standard function epilogue.
9954 (define_insn "sibcall_epilogue"
9955   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9956               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9957   "TARGET_ARM"
9958   "*
9959   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9960     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9961   return arm_output_epilogue (next_nonnote_insn (insn));
9962   "
9963 ;; Length is absolute worst case
9964   [(set_attr "length" "44")
9965    (set_attr "type" "block")
9966    ;; We don't clobber the conditions, but the potential length of this
9967    ;; operation is sufficient to make conditionalizing the sequence 
9968    ;; unlikely to be profitable.
9969    (set_attr "conds" "clob")]
9970 )
9971
9972 (define_insn "*epilogue_insns"
9973   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9974   "TARGET_EITHER"
9975   "*
9976   if (TARGET_ARM)
9977     return arm_output_epilogue (NULL);
9978   else /* TARGET_THUMB */
9979     return thumb_unexpanded_epilogue ();
9980   "
9981   ; Length is absolute worst case
9982   [(set_attr "length" "44")
9983    (set_attr "type" "block")
9984    ;; We don't clobber the conditions, but the potential length of this
9985    ;; operation is sufficient to make conditionalizing the sequence 
9986    ;; unlikely to be profitable.
9987    (set_attr "conds" "clob")]
9988 )
9989
9990 (define_expand "eh_epilogue"
9991   [(use (match_operand:SI 0 "register_operand" ""))
9992    (use (match_operand:SI 1 "register_operand" ""))
9993    (use (match_operand:SI 2 "register_operand" ""))]
9994   "TARGET_EITHER"
9995   "
9996   {
9997     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9998     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9999       {
10000         rtx ra = gen_rtx_REG (Pmode, 2);
10001
10002         emit_move_insn (ra, operands[2]);
10003         operands[2] = ra;
10004       }
10005     /* This is a hack -- we may have crystalized the function type too
10006        early.  */
10007     cfun->machine->func_type = 0;
10008   }"
10009 )
10010
10011 ;; This split is only used during output to reduce the number of patterns
10012 ;; that need assembler instructions adding to them.  We allowed the setting
10013 ;; of the conditions to be implicit during rtl generation so that
10014 ;; the conditional compare patterns would work.  However this conflicts to
10015 ;; some extent with the conditional data operations, so we have to split them
10016 ;; up again here.
10017
10018 (define_split
10019   [(set (match_operand:SI 0 "s_register_operand" "")
10020         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10021                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10022                          (match_dup 0)
10023                          (match_operand 4 "" "")))
10024    (clobber (reg:CC CC_REGNUM))]
10025   "TARGET_ARM && reload_completed"
10026   [(set (match_dup 5) (match_dup 6))
10027    (cond_exec (match_dup 7)
10028               (set (match_dup 0) (match_dup 4)))]
10029   "
10030   {
10031     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10032                                              operands[2], operands[3]);
10033     enum rtx_code rc = GET_CODE (operands[1]);
10034
10035     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10036     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10037     if (mode == CCFPmode || mode == CCFPEmode)
10038       rc = reverse_condition_maybe_unordered (rc);
10039     else
10040       rc = reverse_condition (rc);
10041
10042     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10043   }"
10044 )
10045
10046 (define_split
10047   [(set (match_operand:SI 0 "s_register_operand" "")
10048         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10049                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10050                          (match_operand 4 "" "")
10051                          (match_dup 0)))
10052    (clobber (reg:CC CC_REGNUM))]
10053   "TARGET_ARM && reload_completed"
10054   [(set (match_dup 5) (match_dup 6))
10055    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10056               (set (match_dup 0) (match_dup 4)))]
10057   "
10058   {
10059     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10060                                              operands[2], operands[3]);
10061
10062     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10063     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10064   }"
10065 )
10066
10067 (define_split
10068   [(set (match_operand:SI 0 "s_register_operand" "")
10069         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10070                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10071                          (match_operand 4 "" "")
10072                          (match_operand 5 "" "")))
10073    (clobber (reg:CC CC_REGNUM))]
10074   "TARGET_ARM && reload_completed"
10075   [(set (match_dup 6) (match_dup 7))
10076    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10077               (set (match_dup 0) (match_dup 4)))
10078    (cond_exec (match_dup 8)
10079               (set (match_dup 0) (match_dup 5)))]
10080   "
10081   {
10082     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10083                                              operands[2], operands[3]);
10084     enum rtx_code rc = GET_CODE (operands[1]);
10085
10086     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10087     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10088     if (mode == CCFPmode || mode == CCFPEmode)
10089       rc = reverse_condition_maybe_unordered (rc);
10090     else
10091       rc = reverse_condition (rc);
10092
10093     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10094   }"
10095 )
10096
10097 (define_split
10098   [(set (match_operand:SI 0 "s_register_operand" "")
10099         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10100                           [(match_operand:SI 2 "s_register_operand" "")
10101                            (match_operand:SI 3 "arm_add_operand" "")])
10102                          (match_operand:SI 4 "arm_rhs_operand" "")
10103                          (not:SI
10104                           (match_operand:SI 5 "s_register_operand" ""))))
10105    (clobber (reg:CC CC_REGNUM))]
10106   "TARGET_ARM && reload_completed"
10107   [(set (match_dup 6) (match_dup 7))
10108    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10109               (set (match_dup 0) (match_dup 4)))
10110    (cond_exec (match_dup 8)
10111               (set (match_dup 0) (not:SI (match_dup 5))))]
10112   "
10113   {
10114     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10115                                              operands[2], operands[3]);
10116     enum rtx_code rc = GET_CODE (operands[1]);
10117
10118     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10119     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10120     if (mode == CCFPmode || mode == CCFPEmode)
10121       rc = reverse_condition_maybe_unordered (rc);
10122     else
10123       rc = reverse_condition (rc);
10124
10125     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10126   }"
10127 )
10128
10129 (define_insn "*cond_move_not"
10130   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10131         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10132                           [(match_operand 3 "cc_register" "") (const_int 0)])
10133                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10134                          (not:SI
10135                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10136   "TARGET_ARM"
10137   "@
10138    mvn%D4\\t%0, %2
10139    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10140   [(set_attr "conds" "use")
10141    (set_attr "length" "4,8")]
10142 )
10143
10144 ;; The next two patterns occur when an AND operation is followed by a
10145 ;; scc insn sequence 
10146
10147 (define_insn "*sign_extract_onebit"
10148   [(set (match_operand:SI 0 "s_register_operand" "=r")
10149         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10150                          (const_int 1)
10151                          (match_operand:SI 2 "const_int_operand" "n")))
10152     (clobber (reg:CC CC_REGNUM))]
10153   "TARGET_ARM"
10154   "*
10155     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10156     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10157     return \"mvnne\\t%0, #0\";
10158   "
10159   [(set_attr "conds" "clob")
10160    (set_attr "length" "8")]
10161 )
10162
10163 (define_insn "*not_signextract_onebit"
10164   [(set (match_operand:SI 0 "s_register_operand" "=r")
10165         (not:SI
10166          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10167                           (const_int 1)
10168                           (match_operand:SI 2 "const_int_operand" "n"))))
10169    (clobber (reg:CC CC_REGNUM))]
10170   "TARGET_ARM"
10171   "*
10172     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10173     output_asm_insn (\"tst\\t%1, %2\", operands);
10174     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10175     return \"movne\\t%0, #0\";
10176   "
10177   [(set_attr "conds" "clob")
10178    (set_attr "length" "12")]
10179 )
10180
10181 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10182 ;; expressions.  For simplicity, the first register is also in the unspec
10183 ;; part.
10184 (define_insn "*push_multi"
10185   [(match_parallel 2 "multi_register_push"
10186     [(set (match_operand:BLK 0 "memory_operand" "=m")
10187           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10188                       UNSPEC_PUSH_MULT))])]
10189   "TARGET_ARM"
10190   "*
10191   {
10192     int num_saves = XVECLEN (operands[2], 0);
10193      
10194     /* For the StrongARM at least it is faster to
10195        use STR to store only a single register.  */
10196     if (num_saves == 1)
10197       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10198     else
10199       {
10200         int i;
10201         char pattern[100];
10202
10203         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10204
10205         for (i = 1; i < num_saves; i++)
10206           {
10207             strcat (pattern, \", %|\");
10208             strcat (pattern,
10209                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10210           }
10211
10212         strcat (pattern, \"}\");
10213         output_asm_insn (pattern, operands);
10214       }
10215
10216     return \"\";
10217   }"
10218   [(set_attr "type" "store4")]
10219 )
10220
10221 (define_insn "stack_tie"
10222   [(set (mem:BLK (scratch))
10223         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10224                      (match_operand:SI 1 "s_register_operand" "r")]
10225                     UNSPEC_PRLG_STK))]
10226   ""
10227   ""
10228   [(set_attr "length" "0")]
10229 )
10230
10231 ;; Similarly for the floating point registers
10232 (define_insn "*push_fp_multi"
10233   [(match_parallel 2 "multi_register_push"
10234     [(set (match_operand:BLK 0 "memory_operand" "=m")
10235           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10236                       UNSPEC_PUSH_MULT))])]
10237   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10238   "*
10239   {
10240     char pattern[100];
10241
10242     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10243     output_asm_insn (pattern, operands);
10244     return \"\";
10245   }"
10246   [(set_attr "type" "f_store")]
10247 )
10248
10249 ;; Special patterns for dealing with the constant pool
10250
10251 (define_insn "align_4"
10252   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10253   "TARGET_EITHER"
10254   "*
10255   assemble_align (32);
10256   return \"\";
10257   "
10258 )
10259
10260 (define_insn "align_8"
10261   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10262   "TARGET_EITHER"
10263   "*
10264   assemble_align (64);
10265   return \"\";
10266   "
10267 )
10268
10269 (define_insn "consttable_end"
10270   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10271   "TARGET_EITHER"
10272   "*
10273   making_const_table = FALSE;
10274   return \"\";
10275   "
10276 )
10277
10278 (define_insn "consttable_1"
10279   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10280   "TARGET_THUMB"
10281   "*
10282   making_const_table = TRUE;
10283   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10284   assemble_zeros (3);
10285   return \"\";
10286   "
10287   [(set_attr "length" "4")]
10288 )
10289
10290 (define_insn "consttable_2"
10291   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10292   "TARGET_THUMB"
10293   "*
10294   making_const_table = TRUE;
10295   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10296   assemble_zeros (2);
10297   return \"\";
10298   "
10299   [(set_attr "length" "4")]
10300 )
10301
10302 (define_insn "consttable_4"
10303   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10304   "TARGET_EITHER"
10305   "*
10306   {
10307     making_const_table = TRUE;
10308     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10309       {
10310       case MODE_FLOAT:
10311       {
10312         REAL_VALUE_TYPE r;
10313         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10314         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10315         break;
10316       }
10317       default:
10318         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10319         break;
10320       }
10321     return \"\";
10322   }"
10323   [(set_attr "length" "4")]
10324 )
10325
10326 (define_insn "consttable_8"
10327   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10328   "TARGET_EITHER"
10329   "*
10330   {
10331     making_const_table = TRUE;
10332     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10333       {
10334        case MODE_FLOAT:
10335         {
10336           REAL_VALUE_TYPE r;
10337           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10338           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10339           break;
10340         }
10341       default:
10342         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10343         break;
10344       }
10345     return \"\";
10346   }"
10347   [(set_attr "length" "8")]
10348 )
10349
10350 ;; Miscellaneous Thumb patterns
10351
10352 (define_expand "tablejump"
10353   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10354               (use (label_ref (match_operand 1 "" "")))])]
10355   "TARGET_THUMB"
10356   "
10357   if (flag_pic)
10358     {
10359       /* Hopefully, CSE will eliminate this copy.  */
10360       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10361       rtx reg2 = gen_reg_rtx (SImode);
10362
10363       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10364       operands[0] = reg2;
10365     }
10366   "
10367 )
10368
10369 ;; NB never uses BX.
10370 (define_insn "*thumb_tablejump"
10371   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10372    (use (label_ref (match_operand 1 "" "")))]
10373   "TARGET_THUMB"
10374   "mov\\t%|pc, %0"
10375   [(set_attr "length" "2")]
10376 )
10377
10378 ;; V5 Instructions,
10379
10380 (define_insn "clzsi2"
10381   [(set (match_operand:SI 0 "s_register_operand" "=r")
10382         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10383   "TARGET_ARM && arm_arch5"
10384   "clz%?\\t%0, %1"
10385   [(set_attr "predicable" "yes")])
10386
10387 (define_expand "ffssi2"
10388   [(set (match_operand:SI 0 "s_register_operand" "")
10389         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10390   "TARGET_ARM && arm_arch5"
10391   "
10392   {
10393     rtx t1, t2, t3;
10394
10395     t1 = gen_reg_rtx (SImode);
10396     t2 = gen_reg_rtx (SImode);
10397     t3 = gen_reg_rtx (SImode);
10398
10399     emit_insn (gen_negsi2 (t1, operands[1]));
10400     emit_insn (gen_andsi3 (t2, operands[1], t1));
10401     emit_insn (gen_clzsi2 (t3, t2));
10402     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10403     DONE;
10404   }"
10405 )
10406
10407 (define_expand "ctzsi2"
10408   [(set (match_operand:SI 0 "s_register_operand" "")
10409         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10410   "TARGET_ARM && arm_arch5"
10411   "
10412   {
10413     rtx t1, t2, t3;
10414
10415     t1 = gen_reg_rtx (SImode);
10416     t2 = gen_reg_rtx (SImode);
10417     t3 = gen_reg_rtx (SImode);
10418
10419     emit_insn (gen_negsi2 (t1, operands[1]));
10420     emit_insn (gen_andsi3 (t2, operands[1], t1));
10421     emit_insn (gen_clzsi2 (t3, t2));
10422     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10423     DONE;
10424   }"
10425 )
10426
10427 ;; V5E instructions.
10428
10429 (define_insn "prefetch"
10430   [(prefetch (match_operand:SI 0 "address_operand" "p")
10431              (match_operand:SI 1 "" "")
10432              (match_operand:SI 2 "" ""))]
10433   "TARGET_ARM && arm_arch5e"
10434   "pld\\t%a0")
10435
10436 ;; General predication pattern
10437
10438 (define_cond_exec
10439   [(match_operator 0 "arm_comparison_operator"
10440     [(match_operand 1 "cc_register" "")
10441      (const_int 0)])]
10442   "TARGET_ARM"
10443   ""
10444 )
10445
10446 (define_insn "prologue_use"
10447   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10448   ""
10449   "%@ %0 needed for prologue"
10450 )
10451
10452
10453 ;; Patterns for exception handling
10454
10455 (define_expand "eh_return"
10456   [(use (match_operand 0 "general_operand" ""))]
10457   "TARGET_EITHER"
10458   "
10459   {
10460     if (TARGET_ARM)
10461       emit_insn (gen_arm_eh_return (operands[0]));
10462     else
10463       emit_insn (gen_thumb_eh_return (operands[0]));
10464     DONE;
10465   }"
10466 )
10467                                    
10468 ;; We can't expand this before we know where the link register is stored.
10469 (define_insn_and_split "arm_eh_return"
10470   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10471                     VUNSPEC_EH_RETURN)
10472    (clobber (match_scratch:SI 1 "=&r"))]
10473   "TARGET_ARM"
10474   "#"
10475   "&& reload_completed"
10476   [(const_int 0)]
10477   "
10478   {
10479     arm_set_return_address (operands[0], operands[1]);
10480     DONE;
10481   }"
10482 )
10483
10484 (define_insn_and_split "thumb_eh_return"
10485   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10486                     VUNSPEC_EH_RETURN)
10487    (clobber (match_scratch:SI 1 "=&l"))]
10488   "TARGET_THUMB"
10489   "#"
10490   "&& reload_completed"
10491   [(const_int 0)]
10492   "
10493   {
10494     thumb_set_return_address (operands[0], operands[1]);
10495     DONE;
10496   }"
10497 )
10498
10499 \f
10500 ;; TLS support
10501
10502 (define_insn "load_tp_hard"
10503   [(set (match_operand:SI 0 "register_operand" "=r")
10504         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10505   "TARGET_HARD_TP"
10506   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10507   [(set_attr "predicable" "yes")]
10508 )
10509
10510 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
10511 (define_insn "load_tp_soft"
10512   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10513    (clobber (reg:SI LR_REGNUM))
10514    (clobber (reg:SI IP_REGNUM))
10515    (clobber (reg:CC CC_REGNUM))]
10516   "TARGET_SOFT_TP"
10517   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10518   [(set_attr "conds" "clob")]
10519 )
10520
10521 ;; Load the FPA co-processor patterns
10522 (include "fpa.md")
10523 ;; Load the Maverick co-processor patterns
10524 (include "cirrus.md")
10525 ;; Load the Intel Wireless Multimedia Extension patterns
10526 (include "iwmmxt.md")
10527 ;; Load the VFP co-processor patterns
10528 (include "vfp.md")
10529