OSDN Git Service

2007-01-03 Paul Brook <paul@codesourcery.com>
[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, 2007  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    (UNSPEC_STACK_ALIGN 20) ; Doubleword aligned stack pointer.  Used to
97                            ; generate correct unwind information.
98   ]
99 )
100
101 ;; UNSPEC_VOLATILE Usage:
102
103 (define_constants
104   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
105                         ;   insn in the code.
106    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
107                         ;   instruction epilogue sequence that isn't expanded
108                         ;   into normal RTL.  Used for both normal and sibcall
109                         ;   epilogues.
110    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
111                         ;   for inlined constants.
112    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
113                         ;   table.
114    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
115                         ;   an 8-bit object.
116    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
117                         ;   a 16-bit object.
118    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
119                         ;   a 32-bit object.
120    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
121                         ;   a 64-bit object.
122    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
123    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
124    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
125    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
126    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
127    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
128    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
129                          ; handling.
130   ]
131 )
132 \f
133 ;;---------------------------------------------------------------------------
134 ;; Attributes
135
136 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
137 ; generating ARM code.  This is used to control the length of some insn
138 ; patterns that share the same RTL in both ARM and Thumb code.
139 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
140
141 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
142 ; scheduling decisions for the load unit and the multiplier.
143 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
144
145 ; IS_XSCALE is set to 'yes' when compiling for XScale.
146 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
147
148 ;; Operand number of an input operand that is shifted.  Zero if the
149 ;; given instruction does not shift one of its input operands.
150 (define_attr "shift" "" (const_int 0))
151
152 ; Floating Point Unit.  If we only have floating point emulation, then there
153 ; is no point in scheduling the floating point insns.  (Well, for best
154 ; performance we should try and group them together).
155 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
156   (const (symbol_ref "arm_fpu_attr")))
157
158 ; LENGTH of an instruction (in bytes)
159 (define_attr "length" "" (const_int 4))
160
161 ; POOL_RANGE is how far away from a constant pool entry that this insn
162 ; can be placed.  If the distance is zero, then this insn will never
163 ; reference the pool.
164 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
165 ; before its address.
166 (define_attr "pool_range" "" (const_int 0))
167 (define_attr "neg_pool_range" "" (const_int 0))
168
169 ; An assembler sequence may clobber the condition codes without us knowing.
170 ; If such an insn references the pool, then we have no way of knowing how,
171 ; so use the most conservative value for pool_range.
172 (define_asm_attributes
173  [(set_attr "conds" "clob")
174   (set_attr "length" "4")
175   (set_attr "pool_range" "250")])
176
177 ;; The instruction used to implement a particular pattern.  This
178 ;; information is used by pipeline descriptions to provide accurate
179 ;; scheduling information.
180
181 (define_attr "insn"
182         "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"
183         (const_string "other"))
184
185 ; TYPE attribute is used to detect floating point instructions which, if
186 ; running on a co-processor can run in parallel with other, basic instructions
187 ; If write-buffer scheduling is enabled then it can also be used in the
188 ; scheduling of writes.
189
190 ; Classification of each insn
191 ; alu           any alu  instruction that doesn't hit memory or fp
192 ;               regs or have a shifted source operand
193 ; alu_shift     any data instruction that doesn't hit memory or fp
194 ;               regs, but has a source operand shifted by a constant
195 ; alu_shift_reg any data instruction that doesn't hit memory or fp
196 ;               regs, but has a source operand shifted by a register value
197 ; mult          a multiply instruction
198 ; block         blockage insn, this blocks all functional units
199 ; float         a floating point arithmetic operation (subject to expansion)
200 ; fdivd         DFmode floating point division
201 ; fdivs         SFmode floating point division
202 ; fmul          Floating point multiply
203 ; ffmul         Fast floating point multiply
204 ; farith        Floating point arithmetic (4 cycle)
205 ; ffarith       Fast floating point arithmetic (2 cycle)
206 ; float_em      a floating point arithmetic operation that is normally emulated
207 ;               even on a machine with an fpa.
208 ; f_load        a floating point load from memory
209 ; f_store       a floating point store to memory
210 ; f_load[sd]    single/double load from memory
211 ; f_store[sd]   single/double store to memory
212 ; f_flag        a transfer of co-processor flags to the CPSR
213 ; f_mem_r       a transfer of a floating point register to a real reg via mem
214 ; r_mem_f       the reverse of f_mem_r
215 ; f_2_r         fast transfer float to arm (no memory needed)
216 ; r_2_f         fast transfer arm to float
217 ; f_cvt         convert floating<->integral
218 ; branch        a branch
219 ; call          a subroutine call
220 ; load_byte     load byte(s) from memory to arm registers
221 ; load1         load 1 word from memory to arm registers
222 ; load2         load 2 words from memory to arm registers
223 ; load3         load 3 words from memory to arm registers
224 ; load4         load 4 words from memory to arm registers
225 ; store         store 1 word to memory from arm registers
226 ; store2        store 2 words
227 ; store3        store 3 words
228 ; store4        store 4 (or more) words
229 ;  Additions for Cirrus Maverick co-processor:
230 ; mav_farith    Floating point arithmetic (4 cycle)
231 ; mav_dmult     Double multiplies (7 cycle)
232 ;
233 (define_attr "type"
234         "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" 
235         (if_then_else 
236          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
237          (const_string "mult")
238          (const_string "alu")))
239
240 ; Load scheduling, set from the arm_ld_sched variable
241 ; initialized by arm_override_options() 
242 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
243
244 ; condition codes: this one is used by final_prescan_insn to speed up
245 ; conditionalizing instructions.  It saves having to scan the rtl to see if
246 ; it uses or alters the condition codes.
247
248 ; USE means that the condition codes are used by the insn in the process of
249 ;   outputting code, this means (at present) that we can't use the insn in
250 ;   inlined branches
251 ;
252 ; SET means that the purpose of the insn is to set the condition codes in a
253 ;   well defined manner.
254 ;
255 ; CLOB means that the condition codes are altered in an undefined manner, if
256 ;   they are altered at all
257 ;
258 ; JUMP_CLOB is used when the condition cannot be represented by a single
259 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
260 ;
261 ; NOCOND means that the condition codes are neither altered nor affect the
262 ;   output of this insn
263
264 (define_attr "conds" "use,set,clob,jump_clob,nocond"
265         (if_then_else (eq_attr "type" "call")
266          (const_string "clob")
267          (const_string "nocond")))
268
269 ; Predicable means that the insn can be conditionally executed based on
270 ; an automatically added predicate (additional patterns are generated by 
271 ; gen...).  We default to 'no' because no Thumb patterns match this rule
272 ; and not all ARM patterns do.
273 (define_attr "predicable" "no,yes" (const_string "no"))
274
275 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
276 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
277 ; suffer blockages enough to warrant modelling this (and it can adversely
278 ; affect the schedule).
279 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
280
281 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
282 ; to stall the processor.  Used with model_wbuf above.
283 (define_attr "write_conflict" "no,yes"
284   (if_then_else (eq_attr "type"
285                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
286                 (const_string "yes")
287                 (const_string "no")))
288
289 ; Classify the insns into those that take one cycle and those that take more
290 ; than one on the main cpu execution unit.
291 (define_attr "core_cycles" "single,multi"
292   (if_then_else (eq_attr "type"
293                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
294                 (const_string "single")
295                 (const_string "multi")))
296
297 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
298 ;; distant label.  Only applicable to Thumb code.
299 (define_attr "far_jump" "yes,no" (const_string "no"))
300
301
302 ;; The number of machine instructions this pattern expands to.
303 ;; Used for Thumb-2 conditional execution.
304 (define_attr "ce_count" "" (const_int 1))
305
306 ;;---------------------------------------------------------------------------
307 ;; Mode macros
308
309 ; A list of modes that are exactly 64 bits in size.  We use this to expand
310 ; some splits that are the same for all modes when operating on ARM 
311 ; registers.
312 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
313
314 ;;---------------------------------------------------------------------------
315 ;; Predicates
316
317 (include "predicates.md")
318 (include "constraints.md")
319
320 ;;---------------------------------------------------------------------------
321 ;; Pipeline descriptions
322
323 ;; Processor type.  This is created automatically from arm-cores.def.
324 (include "arm-tune.md")
325
326 ;; True if the generic scheduling description should be used.
327
328 (define_attr "generic_sched" "yes,no"
329   (const (if_then_else 
330           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 
331           (const_string "no")
332           (const_string "yes"))))
333
334 (define_attr "generic_vfp" "yes,no"
335   (const (if_then_else
336           (and (eq_attr "fpu" "vfp")
337                (eq_attr "tune" "!arm1020e,arm1022e"))
338           (const_string "yes")
339           (const_string "no"))))
340
341 (include "arm-generic.md")
342 (include "arm926ejs.md")
343 (include "arm1020e.md")
344 (include "arm1026ejs.md")
345 (include "arm1136jfs.md")
346
347 \f
348 ;;---------------------------------------------------------------------------
349 ;; Insn patterns
350 ;;
351 ;; Addition insns.
352
353 ;; Note: For DImode insns, there is normally no reason why operands should
354 ;; not be in the same register, what we don't want is for something being
355 ;; written to partially overlap something that is an input.
356 ;; Cirrus 64bit additions should not be split because we have a native
357 ;; 64bit addition instructions.
358
359 (define_expand "adddi3"
360  [(parallel
361    [(set (match_operand:DI           0 "s_register_operand" "")
362           (plus:DI (match_operand:DI 1 "s_register_operand" "")
363                    (match_operand:DI 2 "s_register_operand" "")))
364     (clobber (reg:CC CC_REGNUM))])]
365   "TARGET_EITHER"
366   "
367   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
368     {
369       if (!cirrus_fp_register (operands[0], DImode))
370         operands[0] = force_reg (DImode, operands[0]);
371       if (!cirrus_fp_register (operands[1], DImode))
372         operands[1] = force_reg (DImode, operands[1]);
373       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
374       DONE;
375     }
376
377   if (TARGET_THUMB1)
378     {
379       if (GET_CODE (operands[1]) != REG)
380         operands[1] = force_reg (SImode, operands[1]);
381       if (GET_CODE (operands[2]) != REG)
382         operands[2] = force_reg (SImode, operands[2]);
383      }
384   "
385 )
386
387 (define_insn "*thumb1_adddi3"
388   [(set (match_operand:DI          0 "register_operand" "=l")
389         (plus:DI (match_operand:DI 1 "register_operand" "%0")
390                  (match_operand:DI 2 "register_operand" "l")))
391    (clobber (reg:CC CC_REGNUM))
392   ]
393   "TARGET_THUMB1"
394   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
395   [(set_attr "length" "4")]
396 )
397
398 (define_insn_and_split "*arm_adddi3"
399   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
400         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
401                  (match_operand:DI 2 "s_register_operand" "r,  0")))
402    (clobber (reg:CC CC_REGNUM))]
403   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
404   "#"
405   "TARGET_32BIT && reload_completed"
406   [(parallel [(set (reg:CC_C CC_REGNUM)
407                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
408                                  (match_dup 1)))
409               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
410    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
411                                (plus:SI (match_dup 4) (match_dup 5))))]
412   "
413   {
414     operands[3] = gen_highpart (SImode, operands[0]);
415     operands[0] = gen_lowpart (SImode, operands[0]);
416     operands[4] = gen_highpart (SImode, operands[1]);
417     operands[1] = gen_lowpart (SImode, operands[1]);
418     operands[5] = gen_highpart (SImode, operands[2]);
419     operands[2] = gen_lowpart (SImode, operands[2]);
420   }"
421   [(set_attr "conds" "clob")
422    (set_attr "length" "8")]
423 )
424
425 (define_insn_and_split "*adddi_sesidi_di"
426   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
427         (plus:DI (sign_extend:DI
428                   (match_operand:SI 2 "s_register_operand" "r,r"))
429                  (match_operand:DI 1 "s_register_operand" "r,0")))
430    (clobber (reg:CC CC_REGNUM))]
431   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
432   "#"
433   "TARGET_32BIT && reload_completed"
434   [(parallel [(set (reg:CC_C CC_REGNUM)
435                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
436                                  (match_dup 1)))
437               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
438    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
439                                (plus:SI (ashiftrt:SI (match_dup 2)
440                                                      (const_int 31))
441                                         (match_dup 4))))]
442   "
443   {
444     operands[3] = gen_highpart (SImode, operands[0]);
445     operands[0] = gen_lowpart (SImode, operands[0]);
446     operands[4] = gen_highpart (SImode, operands[1]);
447     operands[1] = gen_lowpart (SImode, operands[1]);
448     operands[2] = gen_lowpart (SImode, operands[2]);
449   }"
450   [(set_attr "conds" "clob")
451    (set_attr "length" "8")]
452 )
453
454 (define_insn_and_split "*adddi_zesidi_di"
455   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
456         (plus:DI (zero_extend:DI
457                   (match_operand:SI 2 "s_register_operand" "r,r"))
458                  (match_operand:DI 1 "s_register_operand" "r,0")))
459    (clobber (reg:CC CC_REGNUM))]
460   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
461   "#"
462   "TARGET_32BIT && reload_completed"
463   [(parallel [(set (reg:CC_C CC_REGNUM)
464                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
465                                  (match_dup 1)))
466               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
467    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
468                                (plus:SI (match_dup 4) (const_int 0))))]
469   "
470   {
471     operands[3] = gen_highpart (SImode, operands[0]);
472     operands[0] = gen_lowpart (SImode, operands[0]);
473     operands[4] = gen_highpart (SImode, operands[1]);
474     operands[1] = gen_lowpart (SImode, operands[1]);
475     operands[2] = gen_lowpart (SImode, operands[2]);
476   }"
477   [(set_attr "conds" "clob")
478    (set_attr "length" "8")]
479 )
480
481 (define_expand "addsi3"
482   [(set (match_operand:SI          0 "s_register_operand" "")
483         (plus:SI (match_operand:SI 1 "s_register_operand" "")
484                  (match_operand:SI 2 "reg_or_int_operand" "")))]
485   "TARGET_EITHER"
486   "
487   if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
488     {
489       arm_split_constant (PLUS, SImode, NULL_RTX,
490                           INTVAL (operands[2]), operands[0], operands[1],
491                           optimize && !no_new_pseudos);
492       DONE;
493     }
494   "
495 )
496
497 ; If there is a scratch available, this will be faster than synthesizing the
498 ; addition.
499 (define_peephole2
500   [(match_scratch:SI 3 "r")
501    (set (match_operand:SI          0 "arm_general_register_operand" "")
502         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
503                  (match_operand:SI 2 "const_int_operand"  "")))]
504   "TARGET_32BIT &&
505    !(const_ok_for_arm (INTVAL (operands[2]))
506      || const_ok_for_arm (-INTVAL (operands[2])))
507     && const_ok_for_arm (~INTVAL (operands[2]))"
508   [(set (match_dup 3) (match_dup 2))
509    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
510   ""
511 )
512
513 (define_insn_and_split "*arm_addsi3"
514   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
515         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
516                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
517   "TARGET_32BIT"
518   "@
519    add%?\\t%0, %1, %2
520    sub%?\\t%0, %1, #%n2
521    #"
522   "TARGET_32BIT &&
523    GET_CODE (operands[2]) == CONST_INT
524    && !(const_ok_for_arm (INTVAL (operands[2]))
525         || const_ok_for_arm (-INTVAL (operands[2])))"
526   [(clobber (const_int 0))]
527   "
528   arm_split_constant (PLUS, SImode, curr_insn,
529                       INTVAL (operands[2]), operands[0],
530                       operands[1], 0);
531   DONE;
532   "
533   [(set_attr "length" "4,4,16")
534    (set_attr "predicable" "yes")]
535 )
536
537 ;; Register group 'k' is a single register group containing only the stack
538 ;; register.  Trying to reload it will always fail catastrophically,
539 ;; so never allow those alternatives to match if reloading is needed.
540
541 (define_insn "*thumb1_addsi3"
542   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
543         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
544                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
545   "TARGET_THUMB1"
546   "*
547    static const char * const asms[] = 
548    {
549      \"add\\t%0, %0, %2\",
550      \"sub\\t%0, %0, #%n2\",
551      \"add\\t%0, %1, %2\",
552      \"add\\t%0, %0, %2\",
553      \"add\\t%0, %0, %2\",
554      \"add\\t%0, %1, %2\",
555      \"add\\t%0, %1, %2\"
556    };
557    if ((which_alternative == 2 || which_alternative == 6)
558        && GET_CODE (operands[2]) == CONST_INT
559        && INTVAL (operands[2]) < 0)
560      return \"sub\\t%0, %1, #%n2\";
561    return asms[which_alternative];
562   "
563   [(set_attr "length" "2")]
564 )
565
566 ;; Reloading and elimination of the frame pointer can
567 ;; sometimes cause this optimization to be missed.
568 (define_peephole2
569   [(set (match_operand:SI 0 "arm_general_register_operand" "")
570         (match_operand:SI 1 "const_int_operand" ""))
571    (set (match_dup 0)
572         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
573   "TARGET_THUMB1
574    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
575    && (INTVAL (operands[1]) & 3) == 0"
576   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
577   ""
578 )
579
580 ;; ??? Make Thumb-2 variants which prefer low regs
581 (define_insn "*addsi3_compare0"
582   [(set (reg:CC_NOOV CC_REGNUM)
583         (compare:CC_NOOV
584          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
585                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
586          (const_int 0)))
587    (set (match_operand:SI 0 "s_register_operand" "=r,r")
588         (plus:SI (match_dup 1) (match_dup 2)))]
589   "TARGET_32BIT"
590   "@
591    add%.\\t%0, %1, %2
592    sub%.\\t%0, %1, #%n2"
593   [(set_attr "conds" "set")]
594 )
595
596 (define_insn "*addsi3_compare0_scratch"
597   [(set (reg:CC_NOOV CC_REGNUM)
598         (compare:CC_NOOV
599          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
600                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
601          (const_int 0)))]
602   "TARGET_32BIT"
603   "@
604    cmn%?\\t%0, %1
605    cmp%?\\t%0, #%n1"
606   [(set_attr "conds" "set")]
607 )
608
609 (define_insn "*compare_negsi_si"
610   [(set (reg:CC_Z CC_REGNUM)
611         (compare:CC_Z
612          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
613          (match_operand:SI 1 "s_register_operand" "r")))]
614   "TARGET_32BIT"
615   "cmn%?\\t%1, %0"
616   [(set_attr "conds" "set")]
617 )
618
619 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
620 ;; addend is a constant.
621 (define_insn "*cmpsi2_addneg"
622   [(set (reg:CC CC_REGNUM)
623         (compare:CC
624          (match_operand:SI 1 "s_register_operand" "r,r")
625          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
626    (set (match_operand:SI 0 "s_register_operand" "=r,r")
627         (plus:SI (match_dup 1)
628                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
629   "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
630   "@
631    sub%.\\t%0, %1, %2
632    add%.\\t%0, %1, #%n2"
633   [(set_attr "conds" "set")]
634 )
635
636 ;; Convert the sequence
637 ;;  sub  rd, rn, #1
638 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
639 ;;  bne  dest
640 ;; into
641 ;;  subs rd, rn, #1
642 ;;  bcs  dest   ((unsigned)rn >= 1)
643 ;; similarly for the beq variant using bcc.
644 ;; This is a common looping idiom (while (n--))
645 (define_peephole2
646   [(set (match_operand:SI 0 "arm_general_register_operand" "")
647         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
648                  (const_int -1)))
649    (set (match_operand 2 "cc_register" "")
650         (compare (match_dup 0) (const_int -1)))
651    (set (pc)
652         (if_then_else (match_operator 3 "equality_operator"
653                        [(match_dup 2) (const_int 0)])
654                       (match_operand 4 "" "")
655                       (match_operand 5 "" "")))]
656   "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
657   [(parallel[
658     (set (match_dup 2)
659          (compare:CC
660           (match_dup 1) (const_int 1)))
661     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
662    (set (pc)
663         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
664                       (match_dup 4)
665                       (match_dup 5)))]
666   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
667    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
668                                   ? GEU : LTU),
669                                  VOIDmode, 
670                                  operands[2], const0_rtx);"
671 )
672
673 ;; The next four insns work because they compare the result with one of
674 ;; the operands, and we know that the use of the condition code is
675 ;; either GEU or LTU, so we can use the carry flag from the addition
676 ;; instead of doing the compare a second time.
677 (define_insn "*addsi3_compare_op1"
678   [(set (reg:CC_C CC_REGNUM)
679         (compare:CC_C
680          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
681                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
682          (match_dup 1)))
683    (set (match_operand:SI 0 "s_register_operand" "=r,r")
684         (plus:SI (match_dup 1) (match_dup 2)))]
685   "TARGET_32BIT"
686   "@
687    add%.\\t%0, %1, %2
688    sub%.\\t%0, %1, #%n2"
689   [(set_attr "conds" "set")]
690 )
691
692 (define_insn "*addsi3_compare_op2"
693   [(set (reg:CC_C CC_REGNUM)
694         (compare:CC_C
695          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
696                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
697          (match_dup 2)))
698    (set (match_operand:SI 0 "s_register_operand" "=r,r")
699         (plus:SI (match_dup 1) (match_dup 2)))]
700   "TARGET_32BIT"
701   "@
702    add%.\\t%0, %1, %2
703    sub%.\\t%0, %1, #%n2"
704   [(set_attr "conds" "set")]
705 )
706
707 (define_insn "*compare_addsi2_op0"
708   [(set (reg:CC_C CC_REGNUM)
709         (compare:CC_C
710          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
711                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
712          (match_dup 0)))]
713   "TARGET_32BIT"
714   "@
715    cmn%?\\t%0, %1
716    cmp%?\\t%0, #%n1"
717   [(set_attr "conds" "set")]
718 )
719
720 (define_insn "*compare_addsi2_op1"
721   [(set (reg:CC_C CC_REGNUM)
722         (compare:CC_C
723          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
724                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
725          (match_dup 1)))]
726   "TARGET_32BIT"
727   "@
728    cmn%?\\t%0, %1
729    cmp%?\\t%0, #%n1"
730   [(set_attr "conds" "set")]
731 )
732
733 (define_insn "*addsi3_carryin"
734   [(set (match_operand:SI 0 "s_register_operand" "=r")
735         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
736                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
737                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
738   "TARGET_32BIT"
739   "adc%?\\t%0, %1, %2"
740   [(set_attr "conds" "use")]
741 )
742
743 (define_insn "*addsi3_carryin_shift"
744   [(set (match_operand:SI 0 "s_register_operand" "=r")
745         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
746                  (plus:SI
747                    (match_operator:SI 2 "shift_operator"
748                       [(match_operand:SI 3 "s_register_operand" "r")
749                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
750                     (match_operand:SI 1 "s_register_operand" "r"))))]
751   "TARGET_32BIT"
752   "adc%?\\t%0, %1, %3%S2"
753   [(set_attr "conds" "use")
754    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
755                       (const_string "alu_shift")
756                       (const_string "alu_shift_reg")))]
757 )
758
759 (define_insn "*addsi3_carryin_alt1"
760   [(set (match_operand:SI 0 "s_register_operand" "=r")
761         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
762                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
763                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
764   "TARGET_32BIT"
765   "adc%?\\t%0, %1, %2"
766   [(set_attr "conds" "use")]
767 )
768
769 (define_insn "*addsi3_carryin_alt2"
770   [(set (match_operand:SI 0 "s_register_operand" "=r")
771         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
772                           (match_operand:SI 1 "s_register_operand" "r"))
773                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
774   "TARGET_32BIT"
775   "adc%?\\t%0, %1, %2"
776   [(set_attr "conds" "use")]
777 )
778
779 (define_insn "*addsi3_carryin_alt3"
780   [(set (match_operand:SI 0 "s_register_operand" "=r")
781         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
782                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
783                  (match_operand:SI 1 "s_register_operand" "r")))]
784   "TARGET_32BIT"
785   "adc%?\\t%0, %1, %2"
786   [(set_attr "conds" "use")]
787 )
788
789 (define_expand "incscc"
790   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
791         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
792                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
793                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
794   "TARGET_32BIT"
795   ""
796 )
797
798 (define_insn "*arm_incscc"
799   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
800         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
801                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
802                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
803   "TARGET_ARM"
804   "@
805   add%d2\\t%0, %1, #1
806   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
807   [(set_attr "conds" "use")
808    (set_attr "length" "4,8")]
809 )
810
811 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
812 (define_split
813   [(set (match_operand:SI 0 "s_register_operand" "")
814         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
815                             (match_operand:SI 2 "s_register_operand" ""))
816                  (const_int -1)))
817    (clobber (match_operand:SI 3 "s_register_operand" ""))]
818   "TARGET_32BIT"
819   [(set (match_dup 3) (match_dup 1))
820    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
821   "
822   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
823 ")
824
825 (define_expand "addsf3"
826   [(set (match_operand:SF          0 "s_register_operand" "")
827         (plus:SF (match_operand:SF 1 "s_register_operand" "")
828                  (match_operand:SF 2 "arm_float_add_operand" "")))]
829   "TARGET_32BIT && TARGET_HARD_FLOAT"
830   "
831   if (TARGET_MAVERICK
832       && !cirrus_fp_register (operands[2], SFmode))
833     operands[2] = force_reg (SFmode, operands[2]);
834 ")
835
836 (define_expand "adddf3"
837   [(set (match_operand:DF          0 "s_register_operand" "")
838         (plus:DF (match_operand:DF 1 "s_register_operand" "")
839                  (match_operand:DF 2 "arm_float_add_operand" "")))]
840   "TARGET_32BIT && TARGET_HARD_FLOAT"
841   "
842   if (TARGET_MAVERICK
843       && !cirrus_fp_register (operands[2], DFmode))
844     operands[2] = force_reg (DFmode, operands[2]);
845 ")
846
847 (define_expand "subdi3"
848  [(parallel
849    [(set (match_operand:DI            0 "s_register_operand" "")
850           (minus:DI (match_operand:DI 1 "s_register_operand" "")
851                     (match_operand:DI 2 "s_register_operand" "")))
852     (clobber (reg:CC CC_REGNUM))])]
853   "TARGET_EITHER"
854   "
855   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
856       && TARGET_32BIT
857       && cirrus_fp_register (operands[0], DImode)
858       && cirrus_fp_register (operands[1], DImode))
859     {
860       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
861       DONE;
862     }
863
864   if (TARGET_THUMB1)
865     {
866       if (GET_CODE (operands[1]) != REG)
867         operands[1] = force_reg (SImode, operands[1]);
868       if (GET_CODE (operands[2]) != REG)
869         operands[2] = force_reg (SImode, operands[2]);
870      }  
871   "
872 )
873
874 (define_insn "*arm_subdi3"
875   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
876         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
877                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
878    (clobber (reg:CC CC_REGNUM))]
879   "TARGET_32BIT"
880   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
881   [(set_attr "conds" "clob")
882    (set_attr "length" "8")]
883 )
884
885 (define_insn "*thumb_subdi3"
886   [(set (match_operand:DI           0 "register_operand" "=l")
887         (minus:DI (match_operand:DI 1 "register_operand"  "0")
888                   (match_operand:DI 2 "register_operand"  "l")))
889    (clobber (reg:CC CC_REGNUM))]
890   "TARGET_THUMB1"
891   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
892   [(set_attr "length" "4")]
893 )
894
895 (define_insn "*subdi_di_zesidi"
896   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
897         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
898                   (zero_extend:DI
899                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
900    (clobber (reg:CC CC_REGNUM))]
901   "TARGET_32BIT"
902   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
903   [(set_attr "conds" "clob")
904    (set_attr "length" "8")]
905 )
906
907 (define_insn "*subdi_di_sesidi"
908   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
909         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
910                   (sign_extend:DI
911                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
912    (clobber (reg:CC CC_REGNUM))]
913   "TARGET_32BIT"
914   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
915   [(set_attr "conds" "clob")
916    (set_attr "length" "8")]
917 )
918
919 (define_insn "*subdi_zesidi_di"
920   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
921         (minus:DI (zero_extend:DI
922                    (match_operand:SI 2 "s_register_operand"  "r,r"))
923                   (match_operand:DI  1 "s_register_operand" "?r,0")))
924    (clobber (reg:CC CC_REGNUM))]
925   "TARGET_ARM"
926   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
927   [(set_attr "conds" "clob")
928    (set_attr "length" "8")]
929 )
930
931 (define_insn "*subdi_sesidi_di"
932   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
933         (minus:DI (sign_extend:DI
934                    (match_operand:SI 2 "s_register_operand"   "r,r"))
935                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
936    (clobber (reg:CC CC_REGNUM))]
937   "TARGET_ARM"
938   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
939   [(set_attr "conds" "clob")
940    (set_attr "length" "8")]
941 )
942
943 (define_insn "*subdi_zesidi_zesidi"
944   [(set (match_operand:DI            0 "s_register_operand" "=r")
945         (minus:DI (zero_extend:DI
946                    (match_operand:SI 1 "s_register_operand"  "r"))
947                   (zero_extend:DI
948                    (match_operand:SI 2 "s_register_operand"  "r"))))
949    (clobber (reg:CC CC_REGNUM))]
950   "TARGET_32BIT"
951   "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
952   [(set_attr "conds" "clob")
953    (set_attr "length" "8")]
954 )
955
956 (define_expand "subsi3"
957   [(set (match_operand:SI           0 "s_register_operand" "")
958         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
959                   (match_operand:SI 2 "s_register_operand" "")))]
960   "TARGET_EITHER"
961   "
962   if (GET_CODE (operands[1]) == CONST_INT)
963     {
964       if (TARGET_32BIT)
965         {
966           arm_split_constant (MINUS, SImode, NULL_RTX,
967                               INTVAL (operands[1]), operands[0],
968                               operands[2], optimize && !no_new_pseudos);
969           DONE;
970         }
971       else /* TARGET_THUMB1 */
972         operands[1] = force_reg (SImode, operands[1]);
973     }
974   "
975 )
976
977 (define_insn "*thumb1_subsi3_insn"
978   [(set (match_operand:SI           0 "register_operand" "=l")
979         (minus:SI (match_operand:SI 1 "register_operand" "l")
980                   (match_operand:SI 2 "register_operand" "l")))]
981   "TARGET_THUMB1"
982   "sub\\t%0, %1, %2"
983   [(set_attr "length" "2")]
984 )
985
986 ; ??? Check Thumb-2 split length
987 (define_insn_and_split "*arm_subsi3_insn"
988   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
989         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
990                   (match_operand:SI 2 "s_register_operand" "r,r")))]
991   "TARGET_32BIT"
992   "@
993    rsb%?\\t%0, %2, %1
994    #"
995   "TARGET_32BIT
996    && GET_CODE (operands[1]) == CONST_INT
997    && !const_ok_for_arm (INTVAL (operands[1]))"
998   [(clobber (const_int 0))]
999   "
1000   arm_split_constant (MINUS, SImode, curr_insn,
1001                       INTVAL (operands[1]), operands[0], operands[2], 0);
1002   DONE;
1003   "
1004   [(set_attr "length" "4,16")
1005    (set_attr "predicable" "yes")]
1006 )
1007
1008 (define_peephole2
1009   [(match_scratch:SI 3 "r")
1010    (set (match_operand:SI 0 "arm_general_register_operand" "")
1011         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1012                   (match_operand:SI 2 "arm_general_register_operand" "")))]
1013   "TARGET_32BIT
1014    && !const_ok_for_arm (INTVAL (operands[1]))
1015    && const_ok_for_arm (~INTVAL (operands[1]))"
1016   [(set (match_dup 3) (match_dup 1))
1017    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1018   ""
1019 )
1020
1021 (define_insn "*subsi3_compare0"
1022   [(set (reg:CC_NOOV CC_REGNUM)
1023         (compare:CC_NOOV
1024          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1025                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1026          (const_int 0)))
1027    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1028         (minus:SI (match_dup 1) (match_dup 2)))]
1029   "TARGET_32BIT"
1030   "@
1031    sub%.\\t%0, %1, %2
1032    rsb%.\\t%0, %2, %1"
1033   [(set_attr "conds" "set")]
1034 )
1035
1036 (define_expand "decscc"
1037   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1038         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1039                   (match_operator:SI 2 "arm_comparison_operator"
1040                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1041   "TARGET_32BIT"
1042   ""
1043 )
1044
1045 (define_insn "*arm_decscc"
1046   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1047         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1048                   (match_operator:SI 2 "arm_comparison_operator"
1049                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1050   "TARGET_ARM"
1051   "@
1052    sub%d2\\t%0, %1, #1
1053    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1054   [(set_attr "conds" "use")
1055    (set_attr "length" "*,8")]
1056 )
1057
1058 (define_expand "subsf3"
1059   [(set (match_operand:SF           0 "s_register_operand" "")
1060         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1061                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1062   "TARGET_32BIT && TARGET_HARD_FLOAT"
1063   "
1064   if (TARGET_MAVERICK)
1065     {
1066       if (!cirrus_fp_register (operands[1], SFmode))
1067         operands[1] = force_reg (SFmode, operands[1]);
1068       if (!cirrus_fp_register (operands[2], SFmode))
1069         operands[2] = force_reg (SFmode, operands[2]);
1070     }
1071 ")
1072
1073 (define_expand "subdf3"
1074   [(set (match_operand:DF           0 "s_register_operand" "")
1075         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1076                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1077   "TARGET_32BIT && TARGET_HARD_FLOAT"
1078   "
1079   if (TARGET_MAVERICK)
1080     {
1081        if (!cirrus_fp_register (operands[1], DFmode))
1082          operands[1] = force_reg (DFmode, operands[1]);
1083        if (!cirrus_fp_register (operands[2], DFmode))
1084          operands[2] = force_reg (DFmode, operands[2]);
1085     }
1086 ")
1087
1088 \f
1089 ;; Multiplication insns
1090
1091 (define_expand "mulsi3"
1092   [(set (match_operand:SI          0 "s_register_operand" "")
1093         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1094                  (match_operand:SI 1 "s_register_operand" "")))]
1095   "TARGET_EITHER"
1096   ""
1097 )
1098
1099 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1100 (define_insn "*arm_mulsi3"
1101   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1102         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1103                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1104   "TARGET_32BIT"
1105   "mul%?\\t%0, %2, %1"
1106   [(set_attr "insn" "mul")
1107    (set_attr "predicable" "yes")]
1108 )
1109
1110 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1111 ; 1 and 2; are the same, because reload will make operand 0 match 
1112 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1113 ; this by adding another alternative to match this case, and then `reload' 
1114 ; it ourselves.  This alternative must come first.
1115 (define_insn "*thumb_mulsi3"
1116   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1117         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1118                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1119   "TARGET_THUMB1"
1120   "*
1121   if (which_alternative < 2)
1122     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1123   else
1124     return \"mul\\t%0, %2\";
1125   "
1126   [(set_attr "length" "4,4,2")
1127    (set_attr "insn" "mul")]
1128 )
1129
1130 (define_insn "*mulsi3_compare0"
1131   [(set (reg:CC_NOOV CC_REGNUM)
1132         (compare:CC_NOOV (mult:SI
1133                           (match_operand:SI 2 "s_register_operand" "r,r")
1134                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1135                          (const_int 0)))
1136    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1137         (mult:SI (match_dup 2) (match_dup 1)))]
1138   "TARGET_ARM"
1139   "mul%.\\t%0, %2, %1"
1140   [(set_attr "conds" "set")
1141    (set_attr "insn" "muls")]
1142 )
1143
1144 (define_insn "*mulsi_compare0_scratch"
1145   [(set (reg:CC_NOOV CC_REGNUM)
1146         (compare:CC_NOOV (mult:SI
1147                           (match_operand:SI 2 "s_register_operand" "r,r")
1148                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1149                          (const_int 0)))
1150    (clobber (match_scratch:SI 0 "=&r,&r"))]
1151   "TARGET_ARM"
1152   "mul%.\\t%0, %2, %1"
1153   [(set_attr "conds" "set")
1154    (set_attr "insn" "muls")]
1155 )
1156
1157 ;; Unnamed templates to match MLA instruction.
1158
1159 (define_insn "*mulsi3addsi"
1160   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1161         (plus:SI
1162           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1163                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1164           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1165   "TARGET_32BIT"
1166   "mla%?\\t%0, %2, %1, %3"
1167   [(set_attr "insn" "mla")
1168    (set_attr "predicable" "yes")]
1169 )
1170
1171 (define_insn "*mulsi3addsi_compare0"
1172   [(set (reg:CC_NOOV CC_REGNUM)
1173         (compare:CC_NOOV
1174          (plus:SI (mult:SI
1175                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1176                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1177                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1178          (const_int 0)))
1179    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1180         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1181                  (match_dup 3)))]
1182   "TARGET_ARM"
1183   "mla%.\\t%0, %2, %1, %3"
1184   [(set_attr "conds" "set")
1185    (set_attr "insn" "mlas")]
1186 )
1187
1188 (define_insn "*mulsi3addsi_compare0_scratch"
1189   [(set (reg:CC_NOOV CC_REGNUM)
1190         (compare:CC_NOOV
1191          (plus:SI (mult:SI
1192                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1193                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1194                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1195          (const_int 0)))
1196    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1197   "TARGET_ARM"
1198   "mla%.\\t%0, %2, %1, %3"
1199   [(set_attr "conds" "set")
1200    (set_attr "insn" "mlas")]
1201 )
1202
1203 ;; Unnamed template to match long long multiply-accumulate (smlal)
1204
1205 (define_insn "*mulsidi3adddi"
1206   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1207         (plus:DI
1208          (mult:DI
1209           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1210           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1211          (match_operand:DI 1 "s_register_operand" "0")))]
1212   "TARGET_32BIT && arm_arch3m"
1213   "smlal%?\\t%Q0, %R0, %3, %2"
1214   [(set_attr "insn" "smlal")
1215    (set_attr "predicable" "yes")]
1216 )
1217
1218 (define_insn "mulsidi3"
1219   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1220         (mult:DI
1221          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1222          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1223   "TARGET_32BIT && arm_arch3m"
1224   "smull%?\\t%Q0, %R0, %1, %2"
1225   [(set_attr "insn" "smull")
1226    (set_attr "predicable" "yes")]
1227 )
1228
1229 (define_insn "umulsidi3"
1230   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1231         (mult:DI
1232          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1233          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1234   "TARGET_32BIT && arm_arch3m"
1235   "umull%?\\t%Q0, %R0, %1, %2"
1236   [(set_attr "insn" "umull")
1237    (set_attr "predicable" "yes")]
1238 )
1239
1240 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1241
1242 (define_insn "*umulsidi3adddi"
1243   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1244         (plus:DI
1245          (mult:DI
1246           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1247           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1248          (match_operand:DI 1 "s_register_operand" "0")))]
1249   "TARGET_32BIT && arm_arch3m"
1250   "umlal%?\\t%Q0, %R0, %3, %2"
1251   [(set_attr "insn" "umlal")
1252    (set_attr "predicable" "yes")]
1253 )
1254
1255 (define_insn "smulsi3_highpart"
1256   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1257         (truncate:SI
1258          (lshiftrt:DI
1259           (mult:DI
1260            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1261            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1262           (const_int 32))))
1263    (clobber (match_scratch:SI 3 "=&r,&r"))]
1264   "TARGET_32BIT && arm_arch3m"
1265   "smull%?\\t%3, %0, %2, %1"
1266   [(set_attr "insn" "smull")
1267    (set_attr "predicable" "yes")]
1268 )
1269
1270 (define_insn "umulsi3_highpart"
1271   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1272         (truncate:SI
1273          (lshiftrt:DI
1274           (mult:DI
1275            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1276            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1277           (const_int 32))))
1278    (clobber (match_scratch:SI 3 "=&r,&r"))]
1279   "TARGET_32BIT && arm_arch3m"
1280   "umull%?\\t%3, %0, %2, %1"
1281   [(set_attr "insn" "umull")
1282    (set_attr "predicable" "yes")]
1283 )
1284
1285 (define_insn "mulhisi3"
1286   [(set (match_operand:SI 0 "s_register_operand" "=r")
1287         (mult:SI (sign_extend:SI
1288                   (match_operand:HI 1 "s_register_operand" "%r"))
1289                  (sign_extend:SI
1290                   (match_operand:HI 2 "s_register_operand" "r"))))]
1291   "TARGET_DSP_MULTIPLY"
1292   "smulbb%?\\t%0, %1, %2"
1293   [(set_attr "insn" "smulxy")
1294    (set_attr "predicable" "yes")]
1295 )
1296
1297 (define_insn "*mulhisi3tb"
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                  (sign_extend:SI
1303                   (match_operand:HI 2 "s_register_operand" "r"))))]
1304   "TARGET_DSP_MULTIPLY"
1305   "smultb%?\\t%0, %1, %2"
1306   [(set_attr "insn" "smulxy")
1307    (set_attr "predicable" "yes")]
1308 )
1309
1310 (define_insn "*mulhisi3bt"
1311   [(set (match_operand:SI 0 "s_register_operand" "=r")
1312         (mult:SI (sign_extend:SI
1313                   (match_operand:HI 1 "s_register_operand" "r"))
1314                  (ashiftrt:SI
1315                   (match_operand:SI 2 "s_register_operand" "r")
1316                   (const_int 16))))]
1317   "TARGET_DSP_MULTIPLY"
1318   "smulbt%?\\t%0, %1, %2"
1319   [(set_attr "insn" "smulxy")
1320    (set_attr "predicable" "yes")]
1321 )
1322
1323 (define_insn "*mulhisi3tt"
1324   [(set (match_operand:SI 0 "s_register_operand" "=r")
1325         (mult:SI (ashiftrt:SI
1326                   (match_operand:SI 1 "s_register_operand" "r")
1327                   (const_int 16))
1328                  (ashiftrt:SI
1329                   (match_operand:SI 2 "s_register_operand" "r")
1330                   (const_int 16))))]
1331   "TARGET_DSP_MULTIPLY"
1332   "smultt%?\\t%0, %1, %2"
1333   [(set_attr "insn" "smulxy")
1334    (set_attr "predicable" "yes")]
1335 )
1336
1337 (define_insn "*mulhisi3addsi"
1338   [(set (match_operand:SI 0 "s_register_operand" "=r")
1339         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1340                  (mult:SI (sign_extend:SI
1341                            (match_operand:HI 2 "s_register_operand" "%r"))
1342                           (sign_extend:SI
1343                            (match_operand:HI 3 "s_register_operand" "r")))))]
1344   "TARGET_DSP_MULTIPLY"
1345   "smlabb%?\\t%0, %2, %3, %1"
1346   [(set_attr "insn" "smlaxy")
1347    (set_attr "predicable" "yes")]
1348 )
1349
1350 (define_insn "*mulhidi3adddi"
1351   [(set (match_operand:DI 0 "s_register_operand" "=r")
1352         (plus:DI
1353           (match_operand:DI 1 "s_register_operand" "0")
1354           (mult:DI (sign_extend:DI
1355                     (match_operand:HI 2 "s_register_operand" "%r"))
1356                    (sign_extend:DI
1357                     (match_operand:HI 3 "s_register_operand" "r")))))]
1358   "TARGET_DSP_MULTIPLY"
1359   "smlalbb%?\\t%Q0, %R0, %2, %3"
1360   [(set_attr "insn" "smlalxy")
1361    (set_attr "predicable" "yes")])
1362
1363 (define_expand "mulsf3"
1364   [(set (match_operand:SF          0 "s_register_operand" "")
1365         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1366                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1367   "TARGET_32BIT && TARGET_HARD_FLOAT"
1368   "
1369   if (TARGET_MAVERICK
1370       && !cirrus_fp_register (operands[2], SFmode))
1371     operands[2] = force_reg (SFmode, operands[2]);
1372 ")
1373
1374 (define_expand "muldf3"
1375   [(set (match_operand:DF          0 "s_register_operand" "")
1376         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1377                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1378   "TARGET_32BIT && TARGET_HARD_FLOAT"
1379   "
1380   if (TARGET_MAVERICK
1381       && !cirrus_fp_register (operands[2], DFmode))
1382     operands[2] = force_reg (DFmode, operands[2]);
1383 ")
1384 \f
1385 ;; Division insns
1386
1387 (define_expand "divsf3"
1388   [(set (match_operand:SF 0 "s_register_operand" "")
1389         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1390                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1391   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1392   "")
1393
1394 (define_expand "divdf3"
1395   [(set (match_operand:DF 0 "s_register_operand" "")
1396         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1397                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1398   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1399   "")
1400 \f
1401 ;; Modulo insns
1402
1403 (define_expand "modsf3"
1404   [(set (match_operand:SF 0 "s_register_operand" "")
1405         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1406                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1407   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1408   "")
1409
1410 (define_expand "moddf3"
1411   [(set (match_operand:DF 0 "s_register_operand" "")
1412         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1413                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1414   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1415   "")
1416 \f
1417 ;; Boolean and,ior,xor insns
1418
1419 ;; Split up double word logical operations
1420
1421 ;; Split up simple DImode logical operations.  Simply perform the logical
1422 ;; operation on the upper and lower halves of the registers.
1423 (define_split
1424   [(set (match_operand:DI 0 "s_register_operand" "")
1425         (match_operator:DI 6 "logical_binary_operator"
1426           [(match_operand:DI 1 "s_register_operand" "")
1427            (match_operand:DI 2 "s_register_operand" "")]))]
1428   "TARGET_32BIT && reload_completed
1429    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1430   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1431    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1432   "
1433   {
1434     operands[3] = gen_highpart (SImode, operands[0]);
1435     operands[0] = gen_lowpart (SImode, operands[0]);
1436     operands[4] = gen_highpart (SImode, operands[1]);
1437     operands[1] = gen_lowpart (SImode, operands[1]);
1438     operands[5] = gen_highpart (SImode, operands[2]);
1439     operands[2] = gen_lowpart (SImode, operands[2]);
1440   }"
1441 )
1442
1443 (define_split
1444   [(set (match_operand:DI 0 "s_register_operand" "")
1445         (match_operator:DI 6 "logical_binary_operator"
1446           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1447            (match_operand:DI 1 "s_register_operand" "")]))]
1448   "TARGET_32BIT && reload_completed"
1449   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1450    (set (match_dup 3) (match_op_dup:SI 6
1451                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1452                          (match_dup 4)]))]
1453   "
1454   {
1455     operands[3] = gen_highpart (SImode, operands[0]);
1456     operands[0] = gen_lowpart (SImode, operands[0]);
1457     operands[4] = gen_highpart (SImode, operands[1]);
1458     operands[1] = gen_lowpart (SImode, operands[1]);
1459     operands[5] = gen_highpart (SImode, operands[2]);
1460     operands[2] = gen_lowpart (SImode, operands[2]);
1461   }"
1462 )
1463
1464 ;; The zero extend of operand 2 means we can just copy the high part of
1465 ;; operand1 into operand0.
1466 (define_split
1467   [(set (match_operand:DI 0 "s_register_operand" "")
1468         (ior:DI
1469           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1470           (match_operand:DI 1 "s_register_operand" "")))]
1471   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1472   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1473    (set (match_dup 3) (match_dup 4))]
1474   "
1475   {
1476     operands[4] = gen_highpart (SImode, operands[1]);
1477     operands[3] = gen_highpart (SImode, operands[0]);
1478     operands[0] = gen_lowpart (SImode, operands[0]);
1479     operands[1] = gen_lowpart (SImode, operands[1]);
1480   }"
1481 )
1482
1483 ;; The zero extend of operand 2 means we can just copy the high part of
1484 ;; operand1 into operand0.
1485 (define_split
1486   [(set (match_operand:DI 0 "s_register_operand" "")
1487         (xor:DI
1488           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1489           (match_operand:DI 1 "s_register_operand" "")))]
1490   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1491   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1492    (set (match_dup 3) (match_dup 4))]
1493   "
1494   {
1495     operands[4] = gen_highpart (SImode, operands[1]);
1496     operands[3] = gen_highpart (SImode, operands[0]);
1497     operands[0] = gen_lowpart (SImode, operands[0]);
1498     operands[1] = gen_lowpart (SImode, operands[1]);
1499   }"
1500 )
1501
1502 (define_insn "anddi3"
1503   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1504         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1505                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1506   "TARGET_32BIT && ! TARGET_IWMMXT"
1507   "#"
1508   [(set_attr "length" "8")]
1509 )
1510
1511 (define_insn_and_split "*anddi_zesidi_di"
1512   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1513         (and:DI (zero_extend:DI
1514                  (match_operand:SI 2 "s_register_operand" "r,r"))
1515                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1516   "TARGET_32BIT"
1517   "#"
1518   "TARGET_32BIT && reload_completed"
1519   ; The zero extend of operand 2 clears the high word of the output
1520   ; operand.
1521   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1522    (set (match_dup 3) (const_int 0))]
1523   "
1524   {
1525     operands[3] = gen_highpart (SImode, operands[0]);
1526     operands[0] = gen_lowpart (SImode, operands[0]);
1527     operands[1] = gen_lowpart (SImode, operands[1]);
1528   }"
1529   [(set_attr "length" "8")]
1530 )
1531
1532 (define_insn "*anddi_sesdi_di"
1533   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1534         (and:DI (sign_extend:DI
1535                  (match_operand:SI 2 "s_register_operand" "r,r"))
1536                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1537   "TARGET_32BIT"
1538   "#"
1539   [(set_attr "length" "8")]
1540 )
1541
1542 (define_expand "andsi3"
1543   [(set (match_operand:SI         0 "s_register_operand" "")
1544         (and:SI (match_operand:SI 1 "s_register_operand" "")
1545                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1546   "TARGET_EITHER"
1547   "
1548   if (TARGET_32BIT)
1549     {
1550       if (GET_CODE (operands[2]) == CONST_INT)
1551         {
1552           arm_split_constant (AND, SImode, NULL_RTX,
1553                               INTVAL (operands[2]), operands[0],
1554                               operands[1], optimize && !no_new_pseudos);
1555
1556           DONE;
1557         }
1558     }
1559   else /* TARGET_THUMB1 */
1560     {
1561       if (GET_CODE (operands[2]) != CONST_INT)
1562         operands[2] = force_reg (SImode, operands[2]);
1563       else
1564         {
1565           int i;
1566           
1567           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1568             {
1569               operands[2] = force_reg (SImode,
1570                                        GEN_INT (~INTVAL (operands[2])));
1571               
1572               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1573               
1574               DONE;
1575             }
1576
1577           for (i = 9; i <= 31; i++)
1578             {
1579               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1580                 {
1581                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1582                                         const0_rtx));
1583                   DONE;
1584                 }
1585               else if ((((HOST_WIDE_INT) 1) << i) - 1
1586                        == ~INTVAL (operands[2]))
1587                 {
1588                   rtx shift = GEN_INT (i);
1589                   rtx reg = gen_reg_rtx (SImode);
1590                 
1591                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1592                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1593                   
1594                   DONE;
1595                 }
1596             }
1597
1598           operands[2] = force_reg (SImode, operands[2]);
1599         }
1600     }
1601   "
1602 )
1603
1604 ; ??? Check split length for Thumb-2
1605 (define_insn_and_split "*arm_andsi3_insn"
1606   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1607         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1608                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1609   "TARGET_32BIT"
1610   "@
1611    and%?\\t%0, %1, %2
1612    bic%?\\t%0, %1, #%B2
1613    #"
1614   "TARGET_32BIT
1615    && GET_CODE (operands[2]) == CONST_INT
1616    && !(const_ok_for_arm (INTVAL (operands[2]))
1617         || const_ok_for_arm (~INTVAL (operands[2])))"
1618   [(clobber (const_int 0))]
1619   "
1620   arm_split_constant  (AND, SImode, curr_insn, 
1621                        INTVAL (operands[2]), operands[0], operands[1], 0);
1622   DONE;
1623   "
1624   [(set_attr "length" "4,4,16")
1625    (set_attr "predicable" "yes")]
1626 )
1627
1628 (define_insn "*thumb1_andsi3_insn"
1629   [(set (match_operand:SI         0 "register_operand" "=l")
1630         (and:SI (match_operand:SI 1 "register_operand" "%0")
1631                 (match_operand:SI 2 "register_operand" "l")))]
1632   "TARGET_THUMB1"
1633   "and\\t%0, %0, %2"
1634   [(set_attr "length" "2")]
1635 )
1636
1637 (define_insn "*andsi3_compare0"
1638   [(set (reg:CC_NOOV CC_REGNUM)
1639         (compare:CC_NOOV
1640          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1641                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1642          (const_int 0)))
1643    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1644         (and:SI (match_dup 1) (match_dup 2)))]
1645   "TARGET_32BIT"
1646   "@
1647    and%.\\t%0, %1, %2
1648    bic%.\\t%0, %1, #%B2"
1649   [(set_attr "conds" "set")]
1650 )
1651
1652 (define_insn "*andsi3_compare0_scratch"
1653   [(set (reg:CC_NOOV CC_REGNUM)
1654         (compare:CC_NOOV
1655          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1656                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1657          (const_int 0)))
1658    (clobber (match_scratch:SI 2 "=X,r"))]
1659   "TARGET_32BIT"
1660   "@
1661    tst%?\\t%0, %1
1662    bic%.\\t%2, %0, #%B1"
1663   [(set_attr "conds" "set")]
1664 )
1665
1666 (define_insn "*zeroextractsi_compare0_scratch"
1667   [(set (reg:CC_NOOV CC_REGNUM)
1668         (compare:CC_NOOV (zero_extract:SI
1669                           (match_operand:SI 0 "s_register_operand" "r")
1670                           (match_operand 1 "const_int_operand" "n")
1671                           (match_operand 2 "const_int_operand" "n"))
1672                          (const_int 0)))]
1673   "TARGET_32BIT
1674   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1675       && INTVAL (operands[1]) > 0 
1676       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1677       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1678   "*
1679   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1680                          << INTVAL (operands[2]));
1681   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1682   return \"\";
1683   "
1684   [(set_attr "conds" "set")]
1685 )
1686
1687 (define_insn_and_split "*ne_zeroextractsi"
1688   [(set (match_operand:SI 0 "s_register_operand" "=r")
1689         (ne:SI (zero_extract:SI
1690                 (match_operand:SI 1 "s_register_operand" "r")
1691                 (match_operand:SI 2 "const_int_operand" "n")
1692                 (match_operand:SI 3 "const_int_operand" "n"))
1693                (const_int 0)))
1694    (clobber (reg:CC CC_REGNUM))]
1695   "TARGET_32BIT
1696    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1697        && INTVAL (operands[2]) > 0 
1698        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1699        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1700   "#"
1701   "TARGET_32BIT
1702    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1703        && INTVAL (operands[2]) > 0 
1704        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1705        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1706   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1707                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1708                                     (const_int 0)))
1709               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1710    (set (match_dup 0)
1711         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1712                          (match_dup 0) (const_int 1)))]
1713   "
1714   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1715                          << INTVAL (operands[3])); 
1716   "
1717   [(set_attr "conds" "clob")
1718    (set (attr "length")
1719         (if_then_else (eq_attr "is_thumb" "yes")
1720                       (const_int 12)
1721                       (const_int 8)))]
1722 )
1723
1724 (define_insn_and_split "*ne_zeroextractsi_shifted"
1725   [(set (match_operand:SI 0 "s_register_operand" "=r")
1726         (ne:SI (zero_extract:SI
1727                 (match_operand:SI 1 "s_register_operand" "r")
1728                 (match_operand:SI 2 "const_int_operand" "n")
1729                 (const_int 0))
1730                (const_int 0)))
1731    (clobber (reg:CC CC_REGNUM))]
1732   "TARGET_ARM"
1733   "#"
1734   "TARGET_ARM"
1735   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1736                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1737                                     (const_int 0)))
1738               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1739    (set (match_dup 0)
1740         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1741                          (match_dup 0) (const_int 1)))]
1742   "
1743   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1744   "
1745   [(set_attr "conds" "clob")
1746    (set_attr "length" "8")]
1747 )
1748
1749 (define_insn_and_split "*ite_ne_zeroextractsi"
1750   [(set (match_operand:SI 0 "s_register_operand" "=r")
1751         (if_then_else:SI (ne (zero_extract:SI
1752                               (match_operand:SI 1 "s_register_operand" "r")
1753                               (match_operand:SI 2 "const_int_operand" "n")
1754                               (match_operand:SI 3 "const_int_operand" "n"))
1755                              (const_int 0))
1756                          (match_operand:SI 4 "arm_not_operand" "rIK")
1757                          (const_int 0)))
1758    (clobber (reg:CC CC_REGNUM))]
1759   "TARGET_ARM
1760    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1761        && INTVAL (operands[2]) > 0 
1762        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1763        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1764    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1765   "#"
1766   "TARGET_ARM
1767    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1768        && INTVAL (operands[2]) > 0 
1769        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1770        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1771    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1772   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1773                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1774                                     (const_int 0)))
1775               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1776    (set (match_dup 0)
1777         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1778                          (match_dup 0) (match_dup 4)))]
1779   "
1780   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1781                          << INTVAL (operands[3])); 
1782   "
1783   [(set_attr "conds" "clob")
1784    (set_attr "length" "8")]
1785 )
1786
1787 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1788   [(set (match_operand:SI 0 "s_register_operand" "=r")
1789         (if_then_else:SI (ne (zero_extract:SI
1790                               (match_operand:SI 1 "s_register_operand" "r")
1791                               (match_operand:SI 2 "const_int_operand" "n")
1792                               (const_int 0))
1793                              (const_int 0))
1794                          (match_operand:SI 3 "arm_not_operand" "rIK")
1795                          (const_int 0)))
1796    (clobber (reg:CC CC_REGNUM))]
1797   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1798   "#"
1799   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1800   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1801                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1802                                     (const_int 0)))
1803               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1804    (set (match_dup 0)
1805         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1806                          (match_dup 0) (match_dup 3)))]
1807   "
1808   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1809   "
1810   [(set_attr "conds" "clob")
1811    (set_attr "length" "8")]
1812 )
1813
1814 (define_split
1815   [(set (match_operand:SI 0 "s_register_operand" "")
1816         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1817                          (match_operand:SI 2 "const_int_operand" "")
1818                          (match_operand:SI 3 "const_int_operand" "")))
1819    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1820   "TARGET_THUMB1"
1821   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1822    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1823   "{
1824      HOST_WIDE_INT temp = INTVAL (operands[2]);
1825
1826      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1827      operands[3] = GEN_INT (32 - temp);
1828    }"
1829 )
1830
1831 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
1832 (define_split
1833   [(set (match_operand:SI 0 "s_register_operand" "")
1834         (match_operator:SI 1 "shiftable_operator"
1835          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1836                            (match_operand:SI 3 "const_int_operand" "")
1837                            (match_operand:SI 4 "const_int_operand" ""))
1838           (match_operand:SI 5 "s_register_operand" "")]))
1839    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1840   "TARGET_ARM"
1841   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1842    (set (match_dup 0)
1843         (match_op_dup 1
1844          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1845           (match_dup 5)]))]
1846   "{
1847      HOST_WIDE_INT temp = INTVAL (operands[3]);
1848
1849      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1850      operands[4] = GEN_INT (32 - temp);
1851    }"
1852 )
1853   
1854 (define_split
1855   [(set (match_operand:SI 0 "s_register_operand" "")
1856         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1857                          (match_operand:SI 2 "const_int_operand" "")
1858                          (match_operand:SI 3 "const_int_operand" "")))]
1859   "TARGET_THUMB1"
1860   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1861    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1862   "{
1863      HOST_WIDE_INT temp = INTVAL (operands[2]);
1864
1865      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1866      operands[3] = GEN_INT (32 - temp);
1867    }"
1868 )
1869
1870 (define_split
1871   [(set (match_operand:SI 0 "s_register_operand" "")
1872         (match_operator:SI 1 "shiftable_operator"
1873          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1874                            (match_operand:SI 3 "const_int_operand" "")
1875                            (match_operand:SI 4 "const_int_operand" ""))
1876           (match_operand:SI 5 "s_register_operand" "")]))
1877    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1878   "TARGET_ARM"
1879   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1880    (set (match_dup 0)
1881         (match_op_dup 1
1882          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1883           (match_dup 5)]))]
1884   "{
1885      HOST_WIDE_INT temp = INTVAL (operands[3]);
1886
1887      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1888      operands[4] = GEN_INT (32 - temp);
1889    }"
1890 )
1891   
1892 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1893 ;;; represented by the bitfield, then this will produce incorrect results.
1894 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1895 ;;; which have a real bit-field insert instruction, the truncation happens
1896 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1897 ;;; bit-field insert instruction, we would have to emit code here to truncate
1898 ;;; the value before we insert.  This loses some of the advantage of having
1899 ;;; this insv pattern, so this pattern needs to be reevalutated.
1900
1901 ; ??? Use Thumb-2 bitfield insert/extract instructions
1902 (define_expand "insv"
1903   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1904                          (match_operand:SI 1 "general_operand" "")
1905                          (match_operand:SI 2 "general_operand" ""))
1906         (match_operand:SI 3 "reg_or_int_operand" ""))]
1907   "TARGET_ARM"
1908   "
1909   {
1910     int start_bit = INTVAL (operands[2]);
1911     int width = INTVAL (operands[1]);
1912     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1913     rtx target, subtarget;
1914
1915     target = operands[0];
1916     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1917        subreg as the final target.  */
1918     if (GET_CODE (target) == SUBREG)
1919       {
1920         subtarget = gen_reg_rtx (SImode);
1921         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1922             < GET_MODE_SIZE (SImode))
1923           target = SUBREG_REG (target);
1924       }
1925     else
1926       subtarget = target;    
1927
1928     if (GET_CODE (operands[3]) == CONST_INT)
1929       {
1930         /* Since we are inserting a known constant, we may be able to
1931            reduce the number of bits that we have to clear so that
1932            the mask becomes simple.  */
1933         /* ??? This code does not check to see if the new mask is actually
1934            simpler.  It may not be.  */
1935         rtx op1 = gen_reg_rtx (SImode);
1936         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1937            start of this pattern.  */
1938         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1939         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1940
1941         emit_insn (gen_andsi3 (op1, operands[0],
1942                                gen_int_mode (~mask2, SImode)));
1943         emit_insn (gen_iorsi3 (subtarget, op1,
1944                                gen_int_mode (op3_value << start_bit, SImode)));
1945       }
1946     else if (start_bit == 0
1947              && !(const_ok_for_arm (mask)
1948                   || const_ok_for_arm (~mask)))
1949       {
1950         /* A Trick, since we are setting the bottom bits in the word,
1951            we can shift operand[3] up, operand[0] down, OR them together
1952            and rotate the result back again.  This takes 3 insns, and
1953            the third might be mergeable into another op.  */
1954         /* The shift up copes with the possibility that operand[3] is
1955            wider than the bitfield.  */
1956         rtx op0 = gen_reg_rtx (SImode);
1957         rtx op1 = gen_reg_rtx (SImode);
1958
1959         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1960         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1961         emit_insn (gen_iorsi3  (op1, op1, op0));
1962         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1963       }
1964     else if ((width + start_bit == 32)
1965              && !(const_ok_for_arm (mask)
1966                   || const_ok_for_arm (~mask)))
1967       {
1968         /* Similar trick, but slightly less efficient.  */
1969
1970         rtx op0 = gen_reg_rtx (SImode);
1971         rtx op1 = gen_reg_rtx (SImode);
1972
1973         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1974         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1975         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1976         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1977       }
1978     else
1979       {
1980         rtx op0 = gen_int_mode (mask, SImode);
1981         rtx op1 = gen_reg_rtx (SImode);
1982         rtx op2 = gen_reg_rtx (SImode);
1983
1984         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1985           {
1986             rtx tmp = gen_reg_rtx (SImode);
1987
1988             emit_insn (gen_movsi (tmp, op0));
1989             op0 = tmp;
1990           }
1991
1992         /* Mask out any bits in operand[3] that are not needed.  */
1993            emit_insn (gen_andsi3 (op1, operands[3], op0));
1994
1995         if (GET_CODE (op0) == CONST_INT
1996             && (const_ok_for_arm (mask << start_bit)
1997                 || const_ok_for_arm (~(mask << start_bit))))
1998           {
1999             op0 = gen_int_mode (~(mask << start_bit), SImode);
2000             emit_insn (gen_andsi3 (op2, operands[0], op0));
2001           }
2002         else
2003           {
2004             if (GET_CODE (op0) == CONST_INT)
2005               {
2006                 rtx tmp = gen_reg_rtx (SImode);
2007
2008                 emit_insn (gen_movsi (tmp, op0));
2009                 op0 = tmp;
2010               }
2011
2012             if (start_bit != 0)
2013               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2014             
2015             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2016           }
2017
2018         if (start_bit != 0)
2019           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2020
2021         emit_insn (gen_iorsi3 (subtarget, op1, op2));
2022       }
2023
2024     if (subtarget != target)
2025       {
2026         /* If TARGET is still a SUBREG, then it must be wider than a word,
2027            so we must be careful only to set the subword we were asked to.  */
2028         if (GET_CODE (target) == SUBREG)
2029           emit_move_insn (target, subtarget);
2030         else
2031           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2032       }
2033
2034     DONE;
2035   }"
2036 )
2037
2038 ; constants for op 2 will never be given to these patterns.
2039 (define_insn_and_split "*anddi_notdi_di"
2040   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2041         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2042                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2043   "TARGET_32BIT"
2044   "#"
2045   "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2046   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2047    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2048   "
2049   {
2050     operands[3] = gen_highpart (SImode, operands[0]);
2051     operands[0] = gen_lowpart (SImode, operands[0]);
2052     operands[4] = gen_highpart (SImode, operands[1]);
2053     operands[1] = gen_lowpart (SImode, operands[1]);
2054     operands[5] = gen_highpart (SImode, operands[2]);
2055     operands[2] = gen_lowpart (SImode, operands[2]);
2056   }"
2057   [(set_attr "length" "8")
2058    (set_attr "predicable" "yes")]
2059 )
2060   
2061 (define_insn_and_split "*anddi_notzesidi_di"
2062   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2063         (and:DI (not:DI (zero_extend:DI
2064                          (match_operand:SI 2 "s_register_operand" "r,r")))
2065                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2066   "TARGET_32BIT"
2067   "@
2068    bic%?\\t%Q0, %Q1, %2
2069    #"
2070   ; (not (zero_extend ...)) allows us to just copy the high word from
2071   ; operand1 to operand0.
2072   "TARGET_32BIT
2073    && reload_completed
2074    && operands[0] != operands[1]"
2075   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2076    (set (match_dup 3) (match_dup 4))]
2077   "
2078   {
2079     operands[3] = gen_highpart (SImode, operands[0]);
2080     operands[0] = gen_lowpart (SImode, operands[0]);
2081     operands[4] = gen_highpart (SImode, operands[1]);
2082     operands[1] = gen_lowpart (SImode, operands[1]);
2083   }"
2084   [(set_attr "length" "4,8")
2085    (set_attr "predicable" "yes")]
2086 )
2087   
2088 (define_insn_and_split "*anddi_notsesidi_di"
2089   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2090         (and:DI (not:DI (sign_extend:DI
2091                          (match_operand:SI 2 "s_register_operand" "r,r")))
2092                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2093   "TARGET_32BIT"
2094   "#"
2095   "TARGET_32BIT && reload_completed"
2096   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2097    (set (match_dup 3) (and:SI (not:SI
2098                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2099                                (match_dup 4)))]
2100   "
2101   {
2102     operands[3] = gen_highpart (SImode, operands[0]);
2103     operands[0] = gen_lowpart (SImode, operands[0]);
2104     operands[4] = gen_highpart (SImode, operands[1]);
2105     operands[1] = gen_lowpart (SImode, operands[1]);
2106   }"
2107   [(set_attr "length" "8")
2108    (set_attr "predicable" "yes")]
2109 )
2110   
2111 (define_insn "andsi_notsi_si"
2112   [(set (match_operand:SI 0 "s_register_operand" "=r")
2113         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114                 (match_operand:SI 1 "s_register_operand" "r")))]
2115   "TARGET_32BIT"
2116   "bic%?\\t%0, %1, %2"
2117   [(set_attr "predicable" "yes")]
2118 )
2119
2120 (define_insn "bicsi3"
2121   [(set (match_operand:SI                 0 "register_operand" "=l")
2122         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2123                 (match_operand:SI         2 "register_operand" "0")))]
2124   "TARGET_THUMB1"
2125   "bic\\t%0, %0, %1"
2126   [(set_attr "length" "2")]
2127 )
2128
2129 (define_insn "andsi_not_shiftsi_si"
2130   [(set (match_operand:SI 0 "s_register_operand" "=r")
2131         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2132                          [(match_operand:SI 2 "s_register_operand" "r")
2133                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2134                 (match_operand:SI 1 "s_register_operand" "r")))]
2135   "TARGET_ARM"
2136   "bic%?\\t%0, %1, %2%S4"
2137   [(set_attr "predicable" "yes")
2138    (set_attr "shift" "2")
2139    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2140                       (const_string "alu_shift")
2141                       (const_string "alu_shift_reg")))]
2142 )
2143
2144 (define_insn "*andsi_notsi_si_compare0"
2145   [(set (reg:CC_NOOV CC_REGNUM)
2146         (compare:CC_NOOV
2147          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2148                  (match_operand:SI 1 "s_register_operand" "r"))
2149          (const_int 0)))
2150    (set (match_operand:SI 0 "s_register_operand" "=r")
2151         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2152   "TARGET_32BIT"
2153   "bic%.\\t%0, %1, %2"
2154   [(set_attr "conds" "set")]
2155 )
2156
2157 (define_insn "*andsi_notsi_si_compare0_scratch"
2158   [(set (reg:CC_NOOV CC_REGNUM)
2159         (compare:CC_NOOV
2160          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2161                  (match_operand:SI 1 "s_register_operand" "r"))
2162          (const_int 0)))
2163    (clobber (match_scratch:SI 0 "=r"))]
2164   "TARGET_32BIT"
2165   "bic%.\\t%0, %1, %2"
2166   [(set_attr "conds" "set")]
2167 )
2168
2169 (define_insn "iordi3"
2170   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2171         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2172                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2173   "TARGET_32BIT && ! TARGET_IWMMXT"
2174   "#"
2175   [(set_attr "length" "8")
2176    (set_attr "predicable" "yes")]
2177 )
2178
2179 (define_insn "*iordi_zesidi_di"
2180   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2181         (ior:DI (zero_extend:DI
2182                  (match_operand:SI 2 "s_register_operand" "r,r"))
2183                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2184   "TARGET_32BIT"
2185   "@
2186    orr%?\\t%Q0, %Q1, %2
2187    #"
2188   [(set_attr "length" "4,8")
2189    (set_attr "predicable" "yes")]
2190 )
2191
2192 (define_insn "*iordi_sesidi_di"
2193   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2194         (ior:DI (sign_extend:DI
2195                  (match_operand:SI 2 "s_register_operand" "r,r"))
2196                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2197   "TARGET_32BIT"
2198   "#"
2199   [(set_attr "length" "8")
2200    (set_attr "predicable" "yes")]
2201 )
2202
2203 (define_expand "iorsi3"
2204   [(set (match_operand:SI         0 "s_register_operand" "")
2205         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2206                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2207   "TARGET_EITHER"
2208   "
2209   if (GET_CODE (operands[2]) == CONST_INT)
2210     {
2211       if (TARGET_32BIT)
2212         {
2213           arm_split_constant (IOR, SImode, NULL_RTX,
2214                               INTVAL (operands[2]), operands[0], operands[1],
2215                               optimize && !no_new_pseudos);
2216           DONE;
2217         }
2218       else /* TARGET_THUMB1 */
2219         operands [2] = force_reg (SImode, operands [2]);
2220     }
2221   "
2222 )
2223
2224 (define_insn_and_split "*arm_iorsi3"
2225   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2226         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2227                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2228   "TARGET_32BIT"
2229   "@
2230    orr%?\\t%0, %1, %2
2231    #"
2232   "TARGET_32BIT
2233    && GET_CODE (operands[2]) == CONST_INT
2234    && !const_ok_for_arm (INTVAL (operands[2]))"
2235   [(clobber (const_int 0))]
2236   "
2237   arm_split_constant (IOR, SImode, curr_insn, 
2238                       INTVAL (operands[2]), operands[0], operands[1], 0);
2239   DONE;
2240   "
2241   [(set_attr "length" "4,16")
2242    (set_attr "predicable" "yes")]
2243 )
2244
2245 (define_insn "*thumb1_iorsi3"
2246   [(set (match_operand:SI         0 "register_operand" "=l")
2247         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2248                 (match_operand:SI 2 "register_operand" "l")))]
2249   "TARGET_THUMB1"
2250   "orr\\t%0, %0, %2"
2251   [(set_attr "length" "2")]
2252 )
2253
2254 (define_peephole2
2255   [(match_scratch:SI 3 "r")
2256    (set (match_operand:SI 0 "arm_general_register_operand" "")
2257         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2258                 (match_operand:SI 2 "const_int_operand" "")))]
2259   "TARGET_32BIT
2260    && !const_ok_for_arm (INTVAL (operands[2]))
2261    && const_ok_for_arm (~INTVAL (operands[2]))"
2262   [(set (match_dup 3) (match_dup 2))
2263    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2264   ""
2265 )
2266
2267 (define_insn "*iorsi3_compare0"
2268   [(set (reg:CC_NOOV CC_REGNUM)
2269         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2270                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2271                          (const_int 0)))
2272    (set (match_operand:SI 0 "s_register_operand" "=r")
2273         (ior:SI (match_dup 1) (match_dup 2)))]
2274   "TARGET_32BIT"
2275   "orr%.\\t%0, %1, %2"
2276   [(set_attr "conds" "set")]
2277 )
2278
2279 (define_insn "*iorsi3_compare0_scratch"
2280   [(set (reg:CC_NOOV CC_REGNUM)
2281         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2282                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2283                          (const_int 0)))
2284    (clobber (match_scratch:SI 0 "=r"))]
2285   "TARGET_32BIT"
2286   "orr%.\\t%0, %1, %2"
2287   [(set_attr "conds" "set")]
2288 )
2289
2290 (define_insn "xordi3"
2291   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2292         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2293                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2294   "TARGET_32BIT && !TARGET_IWMMXT"
2295   "#"
2296   [(set_attr "length" "8")
2297    (set_attr "predicable" "yes")]
2298 )
2299
2300 (define_insn "*xordi_zesidi_di"
2301   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2302         (xor:DI (zero_extend:DI
2303                  (match_operand:SI 2 "s_register_operand" "r,r"))
2304                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2305   "TARGET_32BIT"
2306   "@
2307    eor%?\\t%Q0, %Q1, %2
2308    #"
2309   [(set_attr "length" "4,8")
2310    (set_attr "predicable" "yes")]
2311 )
2312
2313 (define_insn "*xordi_sesidi_di"
2314   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2315         (xor:DI (sign_extend:DI
2316                  (match_operand:SI 2 "s_register_operand" "r,r"))
2317                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2318   "TARGET_32BIT"
2319   "#"
2320   [(set_attr "length" "8")
2321    (set_attr "predicable" "yes")]
2322 )
2323
2324 (define_expand "xorsi3"
2325   [(set (match_operand:SI         0 "s_register_operand" "")
2326         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2327                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2328   "TARGET_EITHER"
2329   "if (TARGET_THUMB1)
2330      if (GET_CODE (operands[2]) == CONST_INT)
2331        operands[2] = force_reg (SImode, operands[2]);
2332   "
2333 )
2334
2335 (define_insn "*arm_xorsi3"
2336   [(set (match_operand:SI         0 "s_register_operand" "=r")
2337         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2338                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2339   "TARGET_32BIT"
2340   "eor%?\\t%0, %1, %2"
2341   [(set_attr "predicable" "yes")]
2342 )
2343
2344 (define_insn "*thumb1_xorsi3"
2345   [(set (match_operand:SI         0 "register_operand" "=l")
2346         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2347                 (match_operand:SI 2 "register_operand" "l")))]
2348   "TARGET_THUMB1"
2349   "eor\\t%0, %0, %2"
2350   [(set_attr "length" "2")]
2351 )
2352
2353 (define_insn "*xorsi3_compare0"
2354   [(set (reg:CC_NOOV CC_REGNUM)
2355         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2356                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2357                          (const_int 0)))
2358    (set (match_operand:SI 0 "s_register_operand" "=r")
2359         (xor:SI (match_dup 1) (match_dup 2)))]
2360   "TARGET_32BIT"
2361   "eor%.\\t%0, %1, %2"
2362   [(set_attr "conds" "set")]
2363 )
2364
2365 (define_insn "*xorsi3_compare0_scratch"
2366   [(set (reg:CC_NOOV CC_REGNUM)
2367         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2368                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2369                          (const_int 0)))]
2370   "TARGET_32BIT"
2371   "teq%?\\t%0, %1"
2372   [(set_attr "conds" "set")]
2373 )
2374
2375 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2376 ; (NOT D) we can sometimes merge the final NOT into one of the following
2377 ; insns.
2378
2379 (define_split
2380   [(set (match_operand:SI 0 "s_register_operand" "")
2381         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2382                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2383                 (match_operand:SI 3 "arm_rhs_operand" "")))
2384    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2385   "TARGET_32BIT"
2386   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2387                               (not:SI (match_dup 3))))
2388    (set (match_dup 0) (not:SI (match_dup 4)))]
2389   ""
2390 )
2391
2392 (define_insn "*andsi_iorsi3_notsi"
2393   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2394         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2395                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2396                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2397   "TARGET_32BIT"
2398   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2399   [(set_attr "length" "8")
2400    (set_attr "ce_count" "2")
2401    (set_attr "predicable" "yes")]
2402 )
2403
2404 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2405 ; insns are available?
2406 (define_split
2407   [(set (match_operand:SI 0 "s_register_operand" "")
2408         (match_operator:SI 1 "logical_binary_operator"
2409          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2410                            (match_operand:SI 3 "const_int_operand" "")
2411                            (match_operand:SI 4 "const_int_operand" ""))
2412           (match_operator:SI 9 "logical_binary_operator"
2413            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2414                          (match_operand:SI 6 "const_int_operand" ""))
2415             (match_operand:SI 7 "s_register_operand" "")])]))
2416    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2417   "TARGET_32BIT
2418    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2419    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2420   [(set (match_dup 8)
2421         (match_op_dup 1
2422          [(ashift:SI (match_dup 2) (match_dup 4))
2423           (match_dup 5)]))
2424    (set (match_dup 0)
2425         (match_op_dup 1
2426          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2427           (match_dup 7)]))]
2428   "
2429   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2430 ")
2431
2432 (define_split
2433   [(set (match_operand:SI 0 "s_register_operand" "")
2434         (match_operator:SI 1 "logical_binary_operator"
2435          [(match_operator:SI 9 "logical_binary_operator"
2436            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2437                          (match_operand:SI 6 "const_int_operand" ""))
2438             (match_operand:SI 7 "s_register_operand" "")])
2439           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2440                            (match_operand:SI 3 "const_int_operand" "")
2441                            (match_operand:SI 4 "const_int_operand" ""))]))
2442    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2443   "TARGET_32BIT
2444    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2445    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2446   [(set (match_dup 8)
2447         (match_op_dup 1
2448          [(ashift:SI (match_dup 2) (match_dup 4))
2449           (match_dup 5)]))
2450    (set (match_dup 0)
2451         (match_op_dup 1
2452          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2453           (match_dup 7)]))]
2454   "
2455   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2456 ")
2457
2458 (define_split
2459   [(set (match_operand:SI 0 "s_register_operand" "")
2460         (match_operator:SI 1 "logical_binary_operator"
2461          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2462                            (match_operand:SI 3 "const_int_operand" "")
2463                            (match_operand:SI 4 "const_int_operand" ""))
2464           (match_operator:SI 9 "logical_binary_operator"
2465            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2466                          (match_operand:SI 6 "const_int_operand" ""))
2467             (match_operand:SI 7 "s_register_operand" "")])]))
2468    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2469   "TARGET_32BIT
2470    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2471    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2472   [(set (match_dup 8)
2473         (match_op_dup 1
2474          [(ashift:SI (match_dup 2) (match_dup 4))
2475           (match_dup 5)]))
2476    (set (match_dup 0)
2477         (match_op_dup 1
2478          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2479           (match_dup 7)]))]
2480   "
2481   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2482 ")
2483
2484 (define_split
2485   [(set (match_operand:SI 0 "s_register_operand" "")
2486         (match_operator:SI 1 "logical_binary_operator"
2487          [(match_operator:SI 9 "logical_binary_operator"
2488            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2489                          (match_operand:SI 6 "const_int_operand" ""))
2490             (match_operand:SI 7 "s_register_operand" "")])
2491           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2492                            (match_operand:SI 3 "const_int_operand" "")
2493                            (match_operand:SI 4 "const_int_operand" ""))]))
2494    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2495   "TARGET_32BIT
2496    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2497    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2498   [(set (match_dup 8)
2499         (match_op_dup 1
2500          [(ashift:SI (match_dup 2) (match_dup 4))
2501           (match_dup 5)]))
2502    (set (match_dup 0)
2503         (match_op_dup 1
2504          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2505           (match_dup 7)]))]
2506   "
2507   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2508 ")
2509 \f
2510
2511 ;; Minimum and maximum insns
2512
2513 (define_expand "smaxsi3"
2514   [(parallel [
2515     (set (match_operand:SI 0 "s_register_operand" "")
2516          (smax:SI (match_operand:SI 1 "s_register_operand" "")
2517                   (match_operand:SI 2 "arm_rhs_operand" "")))
2518     (clobber (reg:CC CC_REGNUM))])]
2519   "TARGET_32BIT"
2520   "
2521   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2522     {
2523       /* No need for a clobber of the condition code register here.  */
2524       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2525                               gen_rtx_SMAX (SImode, operands[1],
2526                                             operands[2])));
2527       DONE;
2528     }
2529 ")
2530
2531 (define_insn "*smax_0"
2532   [(set (match_operand:SI 0 "s_register_operand" "=r")
2533         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2534                  (const_int 0)))]
2535   "TARGET_32BIT"
2536   "bic%?\\t%0, %1, %1, asr #31"
2537   [(set_attr "predicable" "yes")]
2538 )
2539
2540 (define_insn "*smax_m1"
2541   [(set (match_operand:SI 0 "s_register_operand" "=r")
2542         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2543                  (const_int -1)))]
2544   "TARGET_32BIT"
2545   "orr%?\\t%0, %1, %1, asr #31"
2546   [(set_attr "predicable" "yes")]
2547 )
2548
2549 (define_insn "*arm_smax_insn"
2550   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
2551         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
2552                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
2553    (clobber (reg:CC CC_REGNUM))]
2554   "TARGET_ARM"
2555   "@
2556    cmp\\t%1, %2\;movlt\\t%0, %2
2557    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2558   [(set_attr "conds" "clob")
2559    (set_attr "length" "8,12")]
2560 )
2561
2562 (define_expand "sminsi3"
2563   [(parallel [
2564     (set (match_operand:SI 0 "s_register_operand" "")
2565          (smin:SI (match_operand:SI 1 "s_register_operand" "")
2566                   (match_operand:SI 2 "arm_rhs_operand" "")))
2567     (clobber (reg:CC CC_REGNUM))])]
2568   "TARGET_32BIT"
2569   "
2570   if (operands[2] == const0_rtx)
2571     {
2572       /* No need for a clobber of the condition code register here.  */
2573       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2574                               gen_rtx_SMIN (SImode, operands[1],
2575                                             operands[2])));
2576       DONE;
2577     }
2578 ")
2579
2580 (define_insn "*smin_0"
2581   [(set (match_operand:SI 0 "s_register_operand" "=r")
2582         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2583                  (const_int 0)))]
2584   "TARGET_32BIT"
2585   "and%?\\t%0, %1, %1, asr #31"
2586   [(set_attr "predicable" "yes")]
2587 )
2588
2589 (define_insn "*arm_smin_insn"
2590   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2591         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2592                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2593    (clobber (reg:CC CC_REGNUM))]
2594   "TARGET_ARM"
2595   "@
2596    cmp\\t%1, %2\;movge\\t%0, %2
2597    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2598   [(set_attr "conds" "clob")
2599    (set_attr "length" "8,12")]
2600 )
2601
2602 (define_expand "umaxsi3"
2603   [(parallel [
2604     (set (match_operand:SI 0 "s_register_operand" "")
2605          (umax:SI (match_operand:SI 1 "s_register_operand" "")
2606                   (match_operand:SI 2 "arm_rhs_operand" "")))
2607     (clobber (reg:CC CC_REGNUM))])]
2608   "TARGET_32BIT"
2609   ""
2610 )
2611
2612 (define_insn "*arm_umaxsi3"
2613   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2614         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2615                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2616    (clobber (reg:CC CC_REGNUM))]
2617   "TARGET_ARM"
2618   "@
2619    cmp\\t%1, %2\;movcc\\t%0, %2
2620    cmp\\t%1, %2\;movcs\\t%0, %1
2621    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2622   [(set_attr "conds" "clob")
2623    (set_attr "length" "8,8,12")]
2624 )
2625
2626 (define_expand "uminsi3"
2627   [(parallel [
2628     (set (match_operand:SI 0 "s_register_operand" "")
2629          (umin:SI (match_operand:SI 1 "s_register_operand" "")
2630                   (match_operand:SI 2 "arm_rhs_operand" "")))
2631     (clobber (reg:CC CC_REGNUM))])]
2632   "TARGET_32BIT"
2633   ""
2634 )
2635
2636 (define_insn "*arm_uminsi3"
2637   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2638         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2639                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2640    (clobber (reg:CC CC_REGNUM))]
2641   "TARGET_ARM"
2642   "@
2643    cmp\\t%1, %2\;movcs\\t%0, %2
2644    cmp\\t%1, %2\;movcc\\t%0, %1
2645    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2646   [(set_attr "conds" "clob")
2647    (set_attr "length" "8,8,12")]
2648 )
2649
2650 (define_insn "*store_minmaxsi"
2651   [(set (match_operand:SI 0 "memory_operand" "=m")
2652         (match_operator:SI 3 "minmax_operator"
2653          [(match_operand:SI 1 "s_register_operand" "r")
2654           (match_operand:SI 2 "s_register_operand" "r")]))
2655    (clobber (reg:CC CC_REGNUM))]
2656   "TARGET_32BIT"
2657   "*
2658   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2659                                 operands[1], operands[2]);
2660   output_asm_insn (\"cmp\\t%1, %2\", operands);
2661   if (TARGET_THUMB2)
2662     output_asm_insn (\"ite\t%d3\", operands);
2663   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2664   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2665   return \"\";
2666   "
2667   [(set_attr "conds" "clob")
2668    (set (attr "length")
2669         (if_then_else (eq_attr "is_thumb" "yes")
2670                       (const_int 14)
2671                       (const_int 12)))
2672    (set_attr "type" "store1")]
2673 )
2674
2675 ; Reject the frame pointer in operand[1], since reloading this after
2676 ; it has been eliminated can cause carnage.
2677 (define_insn "*minmax_arithsi"
2678   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2679         (match_operator:SI 4 "shiftable_operator"
2680          [(match_operator:SI 5 "minmax_operator"
2681            [(match_operand:SI 2 "s_register_operand" "r,r")
2682             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2683           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2684    (clobber (reg:CC CC_REGNUM))]
2685   "TARGET_32BIT && !arm_eliminable_register (operands[1])"
2686   "*
2687   {
2688     enum rtx_code code = GET_CODE (operands[4]);
2689     bool need_else;
2690
2691     if (which_alternative != 0 || operands[3] != const0_rtx
2692         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2693       need_else = true;
2694     else
2695       need_else = false;
2696
2697     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2698                                   operands[2], operands[3]);
2699     output_asm_insn (\"cmp\\t%2, %3\", operands);
2700     if (TARGET_THUMB2)
2701       {
2702         if (need_else)
2703           output_asm_insn (\"ite\\t%d5\", operands);
2704         else
2705           output_asm_insn (\"it\\t%d5\", operands);
2706       }
2707     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2708     if (need_else)
2709       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2710     return \"\";
2711   }"
2712   [(set_attr "conds" "clob")
2713    (set (attr "length")
2714         (if_then_else (eq_attr "is_thumb" "yes")
2715                       (const_int 14)
2716                       (const_int 12)))]
2717 )
2718
2719 \f
2720 ;; Shift and rotation insns
2721
2722 (define_expand "ashldi3"
2723   [(set (match_operand:DI            0 "s_register_operand" "")
2724         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2725                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2726   "TARGET_32BIT"
2727   "
2728   if (GET_CODE (operands[2]) == CONST_INT)
2729     {
2730       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2731         {
2732           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2733           DONE;
2734         }
2735         /* Ideally we shouldn't fail here if we could know that operands[1] 
2736            ends up already living in an iwmmxt register. Otherwise it's
2737            cheaper to have the alternate code being generated than moving
2738            values to iwmmxt regs and back.  */
2739         FAIL;
2740     }
2741   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2742     FAIL;
2743   "
2744 )
2745
2746 (define_insn "arm_ashldi3_1bit"
2747   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2748         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2749                    (const_int 1)))
2750    (clobber (reg:CC CC_REGNUM))]
2751   "TARGET_32BIT"
2752   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2753   [(set_attr "conds" "clob")
2754    (set_attr "length" "8")]
2755 )
2756
2757 (define_expand "ashlsi3"
2758   [(set (match_operand:SI            0 "s_register_operand" "")
2759         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2760                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2761   "TARGET_EITHER"
2762   "
2763   if (GET_CODE (operands[2]) == CONST_INT
2764       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2765     {
2766       emit_insn (gen_movsi (operands[0], const0_rtx));
2767       DONE;
2768     }
2769   "
2770 )
2771
2772 (define_insn "*thumb1_ashlsi3"
2773   [(set (match_operand:SI            0 "register_operand" "=l,l")
2774         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2775                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2776   "TARGET_THUMB1"
2777   "lsl\\t%0, %1, %2"
2778   [(set_attr "length" "2")]
2779 )
2780
2781 (define_expand "ashrdi3"
2782   [(set (match_operand:DI              0 "s_register_operand" "")
2783         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2784                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2785   "TARGET_32BIT"
2786   "
2787   if (GET_CODE (operands[2]) == CONST_INT)
2788     {
2789       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2790         {
2791           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2792           DONE;
2793         }
2794         /* Ideally we shouldn't fail here if we could know that operands[1] 
2795            ends up already living in an iwmmxt register. Otherwise it's
2796            cheaper to have the alternate code being generated than moving
2797            values to iwmmxt regs and back.  */
2798         FAIL;
2799     }
2800   else if (!TARGET_REALLY_IWMMXT)
2801     FAIL;
2802   "
2803 )
2804
2805 (define_insn "arm_ashrdi3_1bit"
2806   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2807         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2808                      (const_int 1)))
2809    (clobber (reg:CC CC_REGNUM))]
2810   "TARGET_32BIT"
2811   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2812   [(set_attr "conds" "clob")
2813    (set_attr "length" "8")]
2814 )
2815
2816 (define_expand "ashrsi3"
2817   [(set (match_operand:SI              0 "s_register_operand" "")
2818         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2819                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2820   "TARGET_EITHER"
2821   "
2822   if (GET_CODE (operands[2]) == CONST_INT
2823       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2824     operands[2] = GEN_INT (31);
2825   "
2826 )
2827
2828 (define_insn "*thumb1_ashrsi3"
2829   [(set (match_operand:SI              0 "register_operand" "=l,l")
2830         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2831                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2832   "TARGET_THUMB1"
2833   "asr\\t%0, %1, %2"
2834   [(set_attr "length" "2")]
2835 )
2836
2837 (define_expand "lshrdi3"
2838   [(set (match_operand:DI              0 "s_register_operand" "")
2839         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2840                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2841   "TARGET_32BIT"
2842   "
2843   if (GET_CODE (operands[2]) == CONST_INT)
2844     {
2845       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2846         {
2847           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2848           DONE;
2849         }
2850         /* Ideally we shouldn't fail here if we could know that operands[1] 
2851            ends up already living in an iwmmxt register. Otherwise it's
2852            cheaper to have the alternate code being generated than moving
2853            values to iwmmxt regs and back.  */
2854         FAIL;
2855     }
2856   else if (!TARGET_REALLY_IWMMXT)
2857     FAIL;
2858   "
2859 )
2860
2861 (define_insn "arm_lshrdi3_1bit"
2862   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2863         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2864                      (const_int 1)))
2865    (clobber (reg:CC CC_REGNUM))]
2866   "TARGET_32BIT"
2867   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2868   [(set_attr "conds" "clob")
2869    (set_attr "length" "8")]
2870 )
2871
2872 (define_expand "lshrsi3"
2873   [(set (match_operand:SI              0 "s_register_operand" "")
2874         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2875                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2876   "TARGET_EITHER"
2877   "
2878   if (GET_CODE (operands[2]) == CONST_INT
2879       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2880     {
2881       emit_insn (gen_movsi (operands[0], const0_rtx));
2882       DONE;
2883     }
2884   "
2885 )
2886
2887 (define_insn "*thumb1_lshrsi3"
2888   [(set (match_operand:SI              0 "register_operand" "=l,l")
2889         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2890                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2891   "TARGET_THUMB1"
2892   "lsr\\t%0, %1, %2"
2893   [(set_attr "length" "2")]
2894 )
2895
2896 (define_expand "rotlsi3"
2897   [(set (match_operand:SI              0 "s_register_operand" "")
2898         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2899                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2900   "TARGET_32BIT"
2901   "
2902   if (GET_CODE (operands[2]) == CONST_INT)
2903     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2904   else
2905     {
2906       rtx reg = gen_reg_rtx (SImode);
2907       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2908       operands[2] = reg;
2909     }
2910   "
2911 )
2912
2913 (define_expand "rotrsi3"
2914   [(set (match_operand:SI              0 "s_register_operand" "")
2915         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2916                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2917   "TARGET_EITHER"
2918   "
2919   if (TARGET_32BIT)
2920     {
2921       if (GET_CODE (operands[2]) == CONST_INT
2922           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2923         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2924     }
2925   else /* TARGET_THUMB1 */
2926     {
2927       if (GET_CODE (operands [2]) == CONST_INT)
2928         operands [2] = force_reg (SImode, operands[2]);
2929     }
2930   "
2931 )
2932
2933 (define_insn "*thumb1_rotrsi3"
2934   [(set (match_operand:SI              0 "register_operand" "=l")
2935         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2936                      (match_operand:SI 2 "register_operand" "l")))]
2937   "TARGET_THUMB1"
2938   "ror\\t%0, %0, %2"
2939   [(set_attr "length" "2")]
2940 )
2941
2942 (define_insn "*arm_shiftsi3"
2943   [(set (match_operand:SI   0 "s_register_operand" "=r")
2944         (match_operator:SI  3 "shift_operator"
2945          [(match_operand:SI 1 "s_register_operand"  "r")
2946           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2947   "TARGET_32BIT"
2948   "* return arm_output_shift(operands, 0);"
2949   [(set_attr "predicable" "yes")
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 (define_insn "*shiftsi3_compare0"
2957   [(set (reg:CC_NOOV CC_REGNUM)
2958         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2959                           [(match_operand:SI 1 "s_register_operand" "r")
2960                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2961                          (const_int 0)))
2962    (set (match_operand:SI 0 "s_register_operand" "=r")
2963         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2964   "TARGET_32BIT"
2965   "* return arm_output_shift(operands, 1);"
2966   [(set_attr "conds" "set")
2967    (set_attr "shift" "1")
2968    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2969                       (const_string "alu_shift")
2970                       (const_string "alu_shift_reg")))]
2971 )
2972
2973 (define_insn "*shiftsi3_compare0_scratch"
2974   [(set (reg:CC_NOOV CC_REGNUM)
2975         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2976                           [(match_operand:SI 1 "s_register_operand" "r")
2977                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2978                          (const_int 0)))
2979    (clobber (match_scratch:SI 0 "=r"))]
2980   "TARGET_32BIT"
2981   "* return arm_output_shift(operands, 1);"
2982   [(set_attr "conds" "set")
2983    (set_attr "shift" "1")]
2984 )
2985
2986 (define_insn "*arm_notsi_shiftsi"
2987   [(set (match_operand:SI 0 "s_register_operand" "=r")
2988         (not:SI (match_operator:SI 3 "shift_operator"
2989                  [(match_operand:SI 1 "s_register_operand" "r")
2990                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2991   "TARGET_ARM"
2992   "mvn%?\\t%0, %1%S3"
2993   [(set_attr "predicable" "yes")
2994    (set_attr "shift" "1")
2995    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2996                       (const_string "alu_shift")
2997                       (const_string "alu_shift_reg")))]
2998 )
2999
3000 (define_insn "*arm_notsi_shiftsi_compare0"
3001   [(set (reg:CC_NOOV CC_REGNUM)
3002         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3003                           [(match_operand:SI 1 "s_register_operand" "r")
3004                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3005                          (const_int 0)))
3006    (set (match_operand:SI 0 "s_register_operand" "=r")
3007         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3008   "TARGET_ARM"
3009   "mvn%.\\t%0, %1%S3"
3010   [(set_attr "conds" "set")
3011    (set_attr "shift" "1")
3012    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3013                       (const_string "alu_shift")
3014                       (const_string "alu_shift_reg")))]
3015 )
3016
3017 (define_insn "*arm_not_shiftsi_compare0_scratch"
3018   [(set (reg:CC_NOOV CC_REGNUM)
3019         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3020                           [(match_operand:SI 1 "s_register_operand" "r")
3021                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3022                          (const_int 0)))
3023    (clobber (match_scratch:SI 0 "=r"))]
3024   "TARGET_ARM"
3025   "mvn%.\\t%0, %1%S3"
3026   [(set_attr "conds" "set")
3027    (set_attr "shift" "1")
3028    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3029                       (const_string "alu_shift")
3030                       (const_string "alu_shift_reg")))]
3031 )
3032
3033 ;; We don't really have extzv, but defining this using shifts helps
3034 ;; to reduce register pressure later on.
3035
3036 (define_expand "extzv"
3037   [(set (match_dup 4)
3038         (ashift:SI (match_operand:SI   1 "register_operand" "")
3039                    (match_operand:SI   2 "const_int_operand" "")))
3040    (set (match_operand:SI              0 "register_operand" "")
3041         (lshiftrt:SI (match_dup 4)
3042                      (match_operand:SI 3 "const_int_operand" "")))]
3043   "TARGET_THUMB1"
3044   "
3045   {
3046     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3047     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3048     
3049     operands[3] = GEN_INT (rshift);
3050     
3051     if (lshift == 0)
3052       {
3053         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3054         DONE;
3055       }
3056       
3057     operands[2] = GEN_INT (lshift);
3058     operands[4] = gen_reg_rtx (SImode);
3059   }"
3060 )
3061
3062 \f
3063 ;; Unary arithmetic insns
3064
3065 (define_expand "negdi2"
3066  [(parallel
3067    [(set (match_operand:DI          0 "s_register_operand" "")
3068           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
3069     (clobber (reg:CC CC_REGNUM))])]
3070   "TARGET_EITHER"
3071   "
3072   if (TARGET_THUMB1)
3073     {
3074       if (GET_CODE (operands[1]) != REG)
3075         operands[1] = force_reg (SImode, operands[1]);
3076      }
3077   "
3078 )
3079
3080 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3081 ;; The second alternative is to allow the common case of a *full* overlap.
3082 (define_insn "*arm_negdi2"
3083   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3084         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
3085    (clobber (reg:CC CC_REGNUM))]
3086   "TARGET_ARM"
3087   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3088   [(set_attr "conds" "clob")
3089    (set_attr "length" "8")]
3090 )
3091
3092 (define_insn "*thumb1_negdi2"
3093   [(set (match_operand:DI         0 "register_operand" "=&l")
3094         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
3095    (clobber (reg:CC CC_REGNUM))]
3096   "TARGET_THUMB1"
3097   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3098   [(set_attr "length" "6")]
3099 )
3100
3101 (define_expand "negsi2"
3102   [(set (match_operand:SI         0 "s_register_operand" "")
3103         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3104   "TARGET_EITHER"
3105   ""
3106 )
3107
3108 (define_insn "*arm_negsi2"
3109   [(set (match_operand:SI         0 "s_register_operand" "=r")
3110         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3111   "TARGET_32BIT"
3112   "rsb%?\\t%0, %1, #0"
3113   [(set_attr "predicable" "yes")]
3114 )
3115
3116 (define_insn "*thumb1_negsi2"
3117   [(set (match_operand:SI         0 "register_operand" "=l")
3118         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3119   "TARGET_THUMB1"
3120   "neg\\t%0, %1"
3121   [(set_attr "length" "2")]
3122 )
3123
3124 (define_expand "negsf2"
3125   [(set (match_operand:SF         0 "s_register_operand" "")
3126         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3127   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3128   ""
3129 )
3130
3131 (define_expand "negdf2"
3132   [(set (match_operand:DF         0 "s_register_operand" "")
3133         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3134   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3135   "")
3136
3137 ;; abssi2 doesn't really clobber the condition codes if a different register
3138 ;; is being set.  To keep things simple, assume during rtl manipulations that
3139 ;; it does, but tell the final scan operator the truth.  Similarly for
3140 ;; (neg (abs...))
3141
3142 (define_expand "abssi2"
3143   [(parallel
3144     [(set (match_operand:SI         0 "s_register_operand" "")
3145           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3146      (clobber (match_dup 2))])]
3147   "TARGET_EITHER"
3148   "
3149   if (TARGET_THUMB1)
3150     operands[2] = gen_rtx_SCRATCH (SImode);
3151   else
3152     operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3153 ")
3154
3155 (define_insn "*arm_abssi2"
3156   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3157         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3158    (clobber (reg:CC CC_REGNUM))]
3159   "TARGET_ARM"
3160   "@
3161    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3162    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3163   [(set_attr "conds" "clob,*")
3164    (set_attr "shift" "1")
3165    ;; predicable can't be set based on the variant, so left as no
3166    (set_attr "length" "8")]
3167 )
3168
3169 (define_insn_and_split "*thumb1_abssi2"
3170   [(set (match_operand:SI 0 "s_register_operand" "=l")
3171         (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3172    (clobber (match_scratch:SI 2 "=&l"))]
3173   "TARGET_THUMB1"
3174   "#"
3175   "TARGET_THUMB1 && reload_completed"
3176   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3177    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3178    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3179   ""
3180   [(set_attr "length" "6")]
3181 )
3182
3183 (define_insn "*arm_neg_abssi2"
3184   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3185         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3186    (clobber (reg:CC CC_REGNUM))]
3187   "TARGET_ARM"
3188   "@
3189    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3190    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3191   [(set_attr "conds" "clob,*")
3192    (set_attr "shift" "1")
3193    ;; predicable can't be set based on the variant, so left as no
3194    (set_attr "length" "8")]
3195 )
3196
3197 (define_insn_and_split "*thumb1_neg_abssi2"
3198   [(set (match_operand:SI 0 "s_register_operand" "=l")
3199         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3200    (clobber (match_scratch:SI 2 "=&l"))]
3201   "TARGET_THUMB1"
3202   "#"
3203   "TARGET_THUMB1 && reload_completed"
3204   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3205    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3206    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3207   ""
3208   [(set_attr "length" "6")]
3209 )
3210
3211 (define_expand "abssf2"
3212   [(set (match_operand:SF         0 "s_register_operand" "")
3213         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3214   "TARGET_32BIT && TARGET_HARD_FLOAT"
3215   "")
3216
3217 (define_expand "absdf2"
3218   [(set (match_operand:DF         0 "s_register_operand" "")
3219         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3220   "TARGET_32BIT && TARGET_HARD_FLOAT"
3221   "")
3222
3223 (define_expand "sqrtsf2"
3224   [(set (match_operand:SF 0 "s_register_operand" "")
3225         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3226   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3227   "")
3228
3229 (define_expand "sqrtdf2"
3230   [(set (match_operand:DF 0 "s_register_operand" "")
3231         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3232   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3233   "")
3234
3235 (define_insn_and_split "one_cmpldi2"
3236   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3237         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3238   "TARGET_32BIT"
3239   "#"
3240   "TARGET_32BIT && reload_completed"
3241   [(set (match_dup 0) (not:SI (match_dup 1)))
3242    (set (match_dup 2) (not:SI (match_dup 3)))]
3243   "
3244   {
3245     operands[2] = gen_highpart (SImode, operands[0]);
3246     operands[0] = gen_lowpart (SImode, operands[0]);
3247     operands[3] = gen_highpart (SImode, operands[1]);
3248     operands[1] = gen_lowpart (SImode, operands[1]);
3249   }"
3250   [(set_attr "length" "8")
3251    (set_attr "predicable" "yes")]
3252 )
3253
3254 (define_expand "one_cmplsi2"
3255   [(set (match_operand:SI         0 "s_register_operand" "")
3256         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3257   "TARGET_EITHER"
3258   ""
3259 )
3260
3261 (define_insn "*arm_one_cmplsi2"
3262   [(set (match_operand:SI         0 "s_register_operand" "=r")
3263         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3264   "TARGET_32BIT"
3265   "mvn%?\\t%0, %1"
3266   [(set_attr "predicable" "yes")]
3267 )
3268
3269 (define_insn "*thumb1_one_cmplsi2"
3270   [(set (match_operand:SI         0 "register_operand" "=l")
3271         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3272   "TARGET_THUMB1"
3273   "mvn\\t%0, %1"
3274   [(set_attr "length" "2")]
3275 )
3276
3277 (define_insn "*notsi_compare0"
3278   [(set (reg:CC_NOOV CC_REGNUM)
3279         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3280                          (const_int 0)))
3281    (set (match_operand:SI 0 "s_register_operand" "=r")
3282         (not:SI (match_dup 1)))]
3283   "TARGET_32BIT"
3284   "mvn%.\\t%0, %1"
3285   [(set_attr "conds" "set")]
3286 )
3287
3288 (define_insn "*notsi_compare0_scratch"
3289   [(set (reg:CC_NOOV CC_REGNUM)
3290         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3291                          (const_int 0)))
3292    (clobber (match_scratch:SI 0 "=r"))]
3293   "TARGET_32BIT"
3294   "mvn%.\\t%0, %1"
3295   [(set_attr "conds" "set")]
3296 )
3297 \f
3298 ;; Fixed <--> Floating conversion insns
3299
3300 (define_expand "floatsisf2"
3301   [(set (match_operand:SF           0 "s_register_operand" "")
3302         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3303   "TARGET_32BIT && TARGET_HARD_FLOAT"
3304   "
3305   if (TARGET_MAVERICK)
3306     {
3307       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3308       DONE;
3309     }
3310 ")
3311
3312 (define_expand "floatsidf2"
3313   [(set (match_operand:DF           0 "s_register_operand" "")
3314         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3315   "TARGET_32BIT && TARGET_HARD_FLOAT"
3316   "
3317   if (TARGET_MAVERICK)
3318     {
3319       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3320       DONE;
3321     }
3322 ")
3323
3324 (define_expand "fix_truncsfsi2"
3325   [(set (match_operand:SI         0 "s_register_operand" "")
3326         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3327   "TARGET_32BIT && TARGET_HARD_FLOAT"
3328   "
3329   if (TARGET_MAVERICK)
3330     {
3331       if (!cirrus_fp_register (operands[0], SImode))
3332         operands[0] = force_reg (SImode, operands[0]);
3333       if (!cirrus_fp_register (operands[1], SFmode))
3334         operands[1] = force_reg (SFmode, operands[0]);
3335       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3336       DONE;
3337     }
3338 ")
3339
3340 (define_expand "fix_truncdfsi2"
3341   [(set (match_operand:SI         0 "s_register_operand" "")
3342         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3343   "TARGET_32BIT && TARGET_HARD_FLOAT"
3344   "
3345   if (TARGET_MAVERICK)
3346     {
3347       if (!cirrus_fp_register (operands[1], DFmode))
3348         operands[1] = force_reg (DFmode, operands[0]);
3349       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3350       DONE;
3351     }
3352 ")
3353
3354 ;; Truncation insns
3355
3356 (define_expand "truncdfsf2"
3357   [(set (match_operand:SF  0 "s_register_operand" "")
3358         (float_truncate:SF
3359          (match_operand:DF 1 "s_register_operand" "")))]
3360   "TARGET_32BIT && TARGET_HARD_FLOAT"
3361   ""
3362 )
3363 \f
3364 ;; Zero and sign extension instructions.
3365
3366 (define_expand "zero_extendsidi2"
3367   [(set (match_operand:DI 0 "s_register_operand" "")
3368         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3369   "TARGET_32BIT"
3370   ""
3371 )
3372
3373 (define_insn "*arm_zero_extendsidi2"
3374   [(set (match_operand:DI 0 "s_register_operand" "=r")
3375         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3376   "TARGET_ARM"
3377   "*
3378     if (REGNO (operands[1])
3379         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3380       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3381     return \"mov%?\\t%R0, #0\";
3382   "
3383   [(set_attr "length" "8")
3384    (set_attr "predicable" "yes")]
3385 )
3386
3387 (define_expand "zero_extendqidi2"
3388   [(set (match_operand:DI                 0 "s_register_operand"  "")
3389         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3390   "TARGET_32BIT"
3391   ""
3392 )
3393
3394 (define_insn "*arm_zero_extendqidi2"
3395   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3396         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3397   "TARGET_ARM"
3398   "@
3399    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3400    ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
3401   [(set_attr "length" "8")
3402    (set_attr "predicable" "yes")
3403    (set_attr "type" "*,load_byte")
3404    (set_attr "pool_range" "*,4092")
3405    (set_attr "neg_pool_range" "*,4084")]
3406 )
3407
3408 (define_expand "extendsidi2"
3409   [(set (match_operand:DI 0 "s_register_operand" "")
3410         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3411   "TARGET_32BIT"
3412   ""
3413 )
3414
3415 (define_insn "*arm_extendsidi2"
3416   [(set (match_operand:DI 0 "s_register_operand" "=r")
3417         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3418   "TARGET_ARM"
3419   "*
3420     if (REGNO (operands[1])
3421         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3422       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3423     return \"mov%?\\t%R0, %Q0, asr #31\";
3424   "
3425   [(set_attr "length" "8")
3426    (set_attr "shift" "1")
3427    (set_attr "predicable" "yes")]
3428 )
3429
3430 (define_expand "zero_extendhisi2"
3431   [(set (match_dup 2)
3432         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3433                    (const_int 16)))
3434    (set (match_operand:SI 0 "s_register_operand" "")
3435         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3436   "TARGET_EITHER"
3437   "
3438   {
3439     if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
3440       {
3441         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3442                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3443         DONE;
3444       }
3445
3446     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3447       {
3448         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3449         DONE;
3450       }
3451
3452     if (!s_register_operand (operands[1], HImode))
3453       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3454
3455     if (arm_arch6)
3456       {
3457         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3458                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3459         DONE;
3460       }
3461
3462     operands[1] = gen_lowpart (SImode, operands[1]);
3463     operands[2] = gen_reg_rtx (SImode);
3464   }"
3465 )
3466
3467 (define_insn "*thumb1_zero_extendhisi2"
3468   [(set (match_operand:SI 0 "register_operand" "=l")
3469         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3470   "TARGET_THUMB1 && !arm_arch6"
3471   "*
3472   rtx mem = XEXP (operands[1], 0);
3473
3474   if (GET_CODE (mem) == CONST)
3475     mem = XEXP (mem, 0);
3476     
3477   if (GET_CODE (mem) == LABEL_REF)
3478     return \"ldr\\t%0, %1\";
3479     
3480   if (GET_CODE (mem) == PLUS)
3481     {
3482       rtx a = XEXP (mem, 0);
3483       rtx b = XEXP (mem, 1);
3484
3485       /* This can happen due to bugs in reload.  */
3486       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3487         {
3488           rtx ops[2];
3489           ops[0] = operands[0];
3490           ops[1] = a;
3491       
3492           output_asm_insn (\"mov        %0, %1\", ops);
3493
3494           XEXP (mem, 0) = operands[0];
3495        }
3496
3497       else if (   GET_CODE (a) == LABEL_REF
3498                && GET_CODE (b) == CONST_INT)
3499         return \"ldr\\t%0, %1\";
3500     }
3501     
3502   return \"ldrh\\t%0, %1\";
3503   "
3504   [(set_attr "length" "4")
3505    (set_attr "type" "load_byte")
3506    (set_attr "pool_range" "60")]
3507 )
3508
3509 (define_insn "*thumb1_zero_extendhisi2_v6"
3510   [(set (match_operand:SI 0 "register_operand" "=l,l")
3511         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3512   "TARGET_THUMB1 && arm_arch6"
3513   "*
3514   rtx mem;
3515
3516   if (which_alternative == 0)
3517     return \"uxth\\t%0, %1\";
3518
3519   mem = XEXP (operands[1], 0);
3520
3521   if (GET_CODE (mem) == CONST)
3522     mem = XEXP (mem, 0);
3523     
3524   if (GET_CODE (mem) == LABEL_REF)
3525     return \"ldr\\t%0, %1\";
3526     
3527   if (GET_CODE (mem) == PLUS)
3528     {
3529       rtx a = XEXP (mem, 0);
3530       rtx b = XEXP (mem, 1);
3531
3532       /* This can happen due to bugs in reload.  */
3533       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3534         {
3535           rtx ops[2];
3536           ops[0] = operands[0];
3537           ops[1] = a;
3538       
3539           output_asm_insn (\"mov        %0, %1\", ops);
3540
3541           XEXP (mem, 0) = operands[0];
3542        }
3543
3544       else if (   GET_CODE (a) == LABEL_REF
3545                && GET_CODE (b) == CONST_INT)
3546         return \"ldr\\t%0, %1\";
3547     }
3548     
3549   return \"ldrh\\t%0, %1\";
3550   "
3551   [(set_attr "length" "2,4")
3552    (set_attr "type" "alu_shift,load_byte")
3553    (set_attr "pool_range" "*,60")]
3554 )
3555
3556 (define_insn "*arm_zero_extendhisi2"
3557   [(set (match_operand:SI 0 "s_register_operand" "=r")
3558         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3559   "TARGET_ARM && arm_arch4 && !arm_arch6"
3560   "ldr%(h%)\\t%0, %1"
3561   [(set_attr "type" "load_byte")
3562    (set_attr "predicable" "yes")
3563    (set_attr "pool_range" "256")
3564    (set_attr "neg_pool_range" "244")]
3565 )
3566
3567 (define_insn "*arm_zero_extendhisi2_v6"
3568   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3569         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3570   "TARGET_ARM && arm_arch6"
3571   "@
3572    uxth%?\\t%0, %1
3573    ldr%(h%)\\t%0, %1"
3574   [(set_attr "type" "alu_shift,load_byte")
3575    (set_attr "predicable" "yes")
3576    (set_attr "pool_range" "*,256")
3577    (set_attr "neg_pool_range" "*,244")]
3578 )
3579
3580 (define_insn "*arm_zero_extendhisi2addsi"
3581   [(set (match_operand:SI 0 "s_register_operand" "=r")
3582         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3583                  (match_operand:SI 2 "s_register_operand" "r")))]
3584   "TARGET_INT_SIMD"
3585   "uxtah%?\\t%0, %2, %1"
3586   [(set_attr "type" "alu_shift")
3587    (set_attr "predicable" "yes")]
3588 )
3589
3590 (define_expand "zero_extendqisi2"
3591   [(set (match_operand:SI 0 "s_register_operand" "")
3592         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3593   "TARGET_EITHER"
3594   "
3595   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3596     {
3597       if (TARGET_ARM)
3598         {
3599           emit_insn (gen_andsi3 (operands[0],
3600                                  gen_lowpart (SImode, operands[1]),
3601                                  GEN_INT (255)));
3602         }
3603       else /* TARGET_THUMB */
3604         {
3605           rtx temp = gen_reg_rtx (SImode);
3606           rtx ops[3];
3607           
3608           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3609           operands[1] = gen_lowpart (SImode, operands[1]);
3610
3611           ops[0] = temp;
3612           ops[1] = operands[1];
3613           ops[2] = GEN_INT (24);
3614
3615           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3616                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3617           
3618           ops[0] = operands[0];
3619           ops[1] = temp;
3620           ops[2] = GEN_INT (24);
3621
3622           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3623                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3624         }
3625       DONE;
3626     }
3627   "
3628 )
3629
3630 (define_insn "*thumb1_zero_extendqisi2"
3631   [(set (match_operand:SI 0 "register_operand" "=l")
3632         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3633   "TARGET_THUMB1 && !arm_arch6"
3634   "ldrb\\t%0, %1"
3635   [(set_attr "length" "2")
3636    (set_attr "type" "load_byte")
3637    (set_attr "pool_range" "32")]
3638 )
3639
3640 (define_insn "*thumb1_zero_extendqisi2_v6"
3641   [(set (match_operand:SI 0 "register_operand" "=l,l")
3642         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3643   "TARGET_THUMB1 && arm_arch6"
3644   "@
3645    uxtb\\t%0, %1
3646    ldrb\\t%0, %1"
3647   [(set_attr "length" "2,2")
3648    (set_attr "type" "alu_shift,load_byte")
3649    (set_attr "pool_range" "*,32")]
3650 )
3651
3652 (define_insn "*arm_zero_extendqisi2"
3653   [(set (match_operand:SI 0 "s_register_operand" "=r")
3654         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3655   "TARGET_ARM && !arm_arch6"
3656   "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
3657   [(set_attr "type" "load_byte")
3658    (set_attr "predicable" "yes")
3659    (set_attr "pool_range" "4096")
3660    (set_attr "neg_pool_range" "4084")]
3661 )
3662
3663 (define_insn "*arm_zero_extendqisi2_v6"
3664   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3665         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3666   "TARGET_ARM && arm_arch6"
3667   "@
3668    uxtb%(%)\\t%0, %1
3669    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
3670   [(set_attr "type" "alu_shift,load_byte")
3671    (set_attr "predicable" "yes")
3672    (set_attr "pool_range" "*,4096")
3673    (set_attr "neg_pool_range" "*,4084")]
3674 )
3675
3676 (define_insn "*arm_zero_extendqisi2addsi"
3677   [(set (match_operand:SI 0 "s_register_operand" "=r")
3678         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3679                  (match_operand:SI 2 "s_register_operand" "r")))]
3680   "TARGET_INT_SIMD"
3681   "uxtab%?\\t%0, %2, %1"
3682   [(set_attr "predicable" "yes")
3683    (set_attr "type" "alu_shift")]
3684 )
3685
3686 (define_split
3687   [(set (match_operand:SI 0 "s_register_operand" "")
3688         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3689    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3690   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3691   [(set (match_dup 2) (match_dup 1))
3692    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3693   ""
3694 )
3695
3696 (define_split
3697   [(set (match_operand:SI 0 "s_register_operand" "")
3698         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3699    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3700   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3701   [(set (match_dup 2) (match_dup 1))
3702    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3703   ""
3704 )
3705
3706 (define_insn "*compareqi_eq0"
3707   [(set (reg:CC_Z CC_REGNUM)
3708         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3709                          (const_int 0)))]
3710   "TARGET_32BIT"
3711   "tst\\t%0, #255"
3712   [(set_attr "conds" "set")]
3713 )
3714
3715 (define_expand "extendhisi2"
3716   [(set (match_dup 2)
3717         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3718                    (const_int 16)))
3719    (set (match_operand:SI 0 "s_register_operand" "")
3720         (ashiftrt:SI (match_dup 2)
3721                      (const_int 16)))]
3722   "TARGET_EITHER"
3723   "
3724   {
3725     if (GET_CODE (operands[1]) == MEM)
3726       {
3727         if (TARGET_THUMB1)
3728           {
3729             emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
3730             DONE;
3731           }
3732         else if (arm_arch4)
3733           {
3734             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3735                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3736             DONE;
3737           }
3738       }
3739
3740     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3741       {
3742         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3743         DONE;
3744       }
3745
3746     if (!s_register_operand (operands[1], HImode))
3747       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3748
3749     if (arm_arch6)
3750       {
3751         if (TARGET_THUMB1)
3752           emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
3753         else
3754           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3755                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3756
3757         DONE;
3758       }
3759
3760     operands[1] = gen_lowpart (SImode, operands[1]);
3761     operands[2] = gen_reg_rtx (SImode);
3762   }"
3763 )
3764
3765 (define_insn "thumb1_extendhisi2"
3766   [(set (match_operand:SI 0 "register_operand" "=l")
3767         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3768    (clobber (match_scratch:SI 2 "=&l"))]
3769   "TARGET_THUMB1 && !arm_arch6"
3770   "*
3771   {
3772     rtx ops[4];
3773     rtx mem = XEXP (operands[1], 0);
3774
3775     /* This code used to try to use 'V', and fix the address only if it was
3776        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3777        range of QImode offsets, and offsettable_address_p does a QImode
3778        address check.  */
3779        
3780     if (GET_CODE (mem) == CONST)
3781       mem = XEXP (mem, 0);
3782     
3783     if (GET_CODE (mem) == LABEL_REF)
3784       return \"ldr\\t%0, %1\";
3785     
3786     if (GET_CODE (mem) == PLUS)
3787       {
3788         rtx a = XEXP (mem, 0);
3789         rtx b = XEXP (mem, 1);
3790
3791         if (GET_CODE (a) == LABEL_REF
3792             && GET_CODE (b) == CONST_INT)
3793           return \"ldr\\t%0, %1\";
3794
3795         if (GET_CODE (b) == REG)
3796           return \"ldrsh\\t%0, %1\";
3797           
3798         ops[1] = a;
3799         ops[2] = b;
3800       }
3801     else
3802       {
3803         ops[1] = mem;
3804         ops[2] = const0_rtx;
3805       }
3806
3807     gcc_assert (GET_CODE (ops[1]) == REG);
3808
3809     ops[0] = operands[0];
3810     ops[3] = operands[2];
3811     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3812     return \"\";
3813   }"
3814   [(set_attr "length" "4")
3815    (set_attr "type" "load_byte")
3816    (set_attr "pool_range" "1020")]
3817 )
3818
3819 ;; We used to have an early-clobber on the scratch register here.
3820 ;; However, there's a bug somewhere in reload which means that this
3821 ;; can be partially ignored during spill allocation if the memory
3822 ;; address also needs reloading; this causes us to die later on when
3823 ;; we try to verify the operands.  Fortunately, we don't really need
3824 ;; the early-clobber: we can always use operand 0 if operand 2
3825 ;; overlaps the address.
3826 (define_insn "*thumb1_extendhisi2_insn_v6"
3827   [(set (match_operand:SI 0 "register_operand" "=l,l")
3828         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3829    (clobber (match_scratch:SI 2 "=X,l"))]
3830   "TARGET_THUMB1 && arm_arch6"
3831   "*
3832   {
3833     rtx ops[4];
3834     rtx mem;
3835
3836     if (which_alternative == 0)
3837       return \"sxth\\t%0, %1\";
3838
3839     mem = XEXP (operands[1], 0);
3840
3841     /* This code used to try to use 'V', and fix the address only if it was
3842        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3843        range of QImode offsets, and offsettable_address_p does a QImode
3844        address check.  */
3845        
3846     if (GET_CODE (mem) == CONST)
3847       mem = XEXP (mem, 0);
3848     
3849     if (GET_CODE (mem) == LABEL_REF)
3850       return \"ldr\\t%0, %1\";
3851     
3852     if (GET_CODE (mem) == PLUS)
3853       {
3854         rtx a = XEXP (mem, 0);
3855         rtx b = XEXP (mem, 1);
3856
3857         if (GET_CODE (a) == LABEL_REF
3858             && GET_CODE (b) == CONST_INT)
3859           return \"ldr\\t%0, %1\";
3860
3861         if (GET_CODE (b) == REG)
3862           return \"ldrsh\\t%0, %1\";
3863           
3864         ops[1] = a;
3865         ops[2] = b;
3866       }
3867     else
3868       {
3869         ops[1] = mem;
3870         ops[2] = const0_rtx;
3871       }
3872       
3873     gcc_assert (GET_CODE (ops[1]) == REG);
3874
3875     ops[0] = operands[0];
3876     if (reg_mentioned_p (operands[2], ops[1]))
3877       ops[3] = ops[0];
3878     else
3879       ops[3] = operands[2];
3880     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3881     return \"\";
3882   }"
3883   [(set_attr "length" "2,4")
3884    (set_attr "type" "alu_shift,load_byte")
3885    (set_attr "pool_range" "*,1020")]
3886 )
3887
3888 ;; This pattern will only be used when ldsh is not available
3889 (define_expand "extendhisi2_mem"
3890   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3891    (set (match_dup 3)
3892         (zero_extend:SI (match_dup 7)))
3893    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3894    (set (match_operand:SI 0 "" "")
3895         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3896   "TARGET_ARM"
3897   "
3898   {
3899     rtx mem1, mem2;
3900     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3901
3902     mem1 = change_address (operands[1], QImode, addr);
3903     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3904     operands[0] = gen_lowpart (SImode, operands[0]);
3905     operands[1] = mem1;
3906     operands[2] = gen_reg_rtx (SImode);
3907     operands[3] = gen_reg_rtx (SImode);
3908     operands[6] = gen_reg_rtx (SImode);
3909     operands[7] = mem2;
3910
3911     if (BYTES_BIG_ENDIAN)
3912       {
3913         operands[4] = operands[2];
3914         operands[5] = operands[3];
3915       }
3916     else
3917       {
3918         operands[4] = operands[3];
3919         operands[5] = operands[2];
3920       }
3921   }"
3922 )
3923
3924 (define_insn "*arm_extendhisi2"
3925   [(set (match_operand:SI 0 "s_register_operand" "=r")
3926         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3927   "TARGET_ARM && arm_arch4 && !arm_arch6"
3928   "ldr%(sh%)\\t%0, %1"
3929   [(set_attr "type" "load_byte")
3930    (set_attr "predicable" "yes")
3931    (set_attr "pool_range" "256")
3932    (set_attr "neg_pool_range" "244")]
3933 )
3934
3935 ;; ??? Check Thumb-2 pool range
3936 (define_insn "*arm_extendhisi2_v6"
3937   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3938         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3939   "TARGET_32BIT && arm_arch6"
3940   "@
3941    sxth%?\\t%0, %1
3942    ldr%(sh%)\\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_extendhisi2addsi"
3950   [(set (match_operand:SI 0 "s_register_operand" "=r")
3951         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3952                  (match_operand:SI 2 "s_register_operand" "r")))]
3953   "TARGET_INT_SIMD"
3954   "sxtah%?\\t%0, %2, %1"
3955 )
3956
3957 (define_expand "extendqihi2"
3958   [(set (match_dup 2)
3959         (ashift:SI (match_operand:QI 1 "general_operand" "")
3960                    (const_int 24)))
3961    (set (match_operand:HI 0 "s_register_operand" "")
3962         (ashiftrt:SI (match_dup 2)
3963                      (const_int 24)))]
3964   "TARGET_ARM"
3965   "
3966   {
3967     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3968       {
3969         emit_insn (gen_rtx_SET (VOIDmode,
3970                                 operands[0],
3971                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3972         DONE;
3973       }
3974     if (!s_register_operand (operands[1], QImode))
3975       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3976     operands[0] = gen_lowpart (SImode, operands[0]);
3977     operands[1] = gen_lowpart (SImode, operands[1]);
3978     operands[2] = gen_reg_rtx (SImode);
3979   }"
3980 )
3981
3982 (define_insn "*arm_extendqihi_insn"
3983   [(set (match_operand:HI 0 "s_register_operand" "=r")
3984         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3985   "TARGET_ARM && arm_arch4"
3986   "ldr%(sb%)\\t%0, %1"
3987   [(set_attr "type" "load_byte")
3988    (set_attr "predicable" "yes")
3989    (set_attr "pool_range" "256")
3990    (set_attr "neg_pool_range" "244")]
3991 )
3992
3993 (define_expand "extendqisi2"
3994   [(set (match_dup 2)
3995         (ashift:SI (match_operand:QI 1 "general_operand" "")
3996                    (const_int 24)))
3997    (set (match_operand:SI 0 "s_register_operand" "")
3998         (ashiftrt:SI (match_dup 2)
3999                      (const_int 24)))]
4000   "TARGET_EITHER"
4001   "
4002   {
4003     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
4004       {
4005         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4006                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4007         DONE;
4008       }
4009
4010     if (!s_register_operand (operands[1], QImode))
4011       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4012
4013     if (arm_arch6)
4014       {
4015         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4016                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4017         DONE;
4018       }
4019
4020     operands[1] = gen_lowpart (SImode, operands[1]);
4021     operands[2] = gen_reg_rtx (SImode);
4022   }"
4023 )
4024
4025 (define_insn "*arm_extendqisi"
4026   [(set (match_operand:SI 0 "s_register_operand" "=r")
4027         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
4028   "TARGET_ARM && arm_arch4 && !arm_arch6"
4029   "ldr%(sb%)\\t%0, %1"
4030   [(set_attr "type" "load_byte")
4031    (set_attr "predicable" "yes")
4032    (set_attr "pool_range" "256")
4033    (set_attr "neg_pool_range" "244")]
4034 )
4035
4036 (define_insn "*arm_extendqisi_v6"
4037   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4038         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
4039   "TARGET_ARM && arm_arch6"
4040   "@
4041    sxtb%?\\t%0, %1
4042    ldr%(sb%)\\t%0, %1"
4043   [(set_attr "type" "alu_shift,load_byte")
4044    (set_attr "predicable" "yes")
4045    (set_attr "pool_range" "*,256")
4046    (set_attr "neg_pool_range" "*,244")]
4047 )
4048
4049 (define_insn "*arm_extendqisi2addsi"
4050   [(set (match_operand:SI 0 "s_register_operand" "=r")
4051         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4052                  (match_operand:SI 2 "s_register_operand" "r")))]
4053   "TARGET_INT_SIMD"
4054   "sxtab%?\\t%0, %2, %1"
4055   [(set_attr "type" "alu_shift")
4056    (set_attr "predicable" "yes")]
4057 )
4058
4059 (define_insn "*thumb1_extendqisi2"
4060   [(set (match_operand:SI 0 "register_operand" "=l,l")
4061         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
4062   "TARGET_THUMB1 && !arm_arch6"
4063   "*
4064   {
4065     rtx ops[3];
4066     rtx mem = XEXP (operands[1], 0);
4067     
4068     if (GET_CODE (mem) == CONST)
4069       mem = XEXP (mem, 0);
4070     
4071     if (GET_CODE (mem) == LABEL_REF)
4072       return \"ldr\\t%0, %1\";
4073
4074     if (GET_CODE (mem) == PLUS
4075         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4076       return \"ldr\\t%0, %1\";
4077       
4078     if (which_alternative == 0)
4079       return \"ldrsb\\t%0, %1\";
4080       
4081     ops[0] = operands[0];
4082     
4083     if (GET_CODE (mem) == PLUS)
4084       {
4085         rtx a = XEXP (mem, 0);
4086         rtx b = XEXP (mem, 1);
4087         
4088         ops[1] = a;
4089         ops[2] = b;
4090
4091         if (GET_CODE (a) == REG)
4092           {
4093             if (GET_CODE (b) == REG)
4094               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4095             else if (REGNO (a) == REGNO (ops[0]))
4096               {
4097                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4098                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4099                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4100               }
4101             else
4102               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4103           }
4104         else
4105           {
4106             gcc_assert (GET_CODE (b) == REG);
4107             if (REGNO (b) == REGNO (ops[0]))
4108               {
4109                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4110                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4111                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4112               }
4113             else
4114               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4115           }
4116       }
4117     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4118       {
4119         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4120         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4121         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4122       }
4123     else
4124       {
4125         ops[1] = mem;
4126         ops[2] = const0_rtx;
4127         
4128         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4129       }
4130     return \"\";
4131   }"
4132   [(set_attr "length" "2,6")
4133    (set_attr "type" "load_byte,load_byte")
4134    (set_attr "pool_range" "32,32")]
4135 )
4136
4137 (define_insn "*thumb1_extendqisi2_v6"
4138   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4139         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4140   "TARGET_THUMB1 && arm_arch6"
4141   "*
4142   {
4143     rtx ops[3];
4144     rtx mem;
4145
4146     if (which_alternative == 0)
4147       return \"sxtb\\t%0, %1\";
4148
4149     mem = XEXP (operands[1], 0);
4150     
4151     if (GET_CODE (mem) == CONST)
4152       mem = XEXP (mem, 0);
4153     
4154     if (GET_CODE (mem) == LABEL_REF)
4155       return \"ldr\\t%0, %1\";
4156
4157     if (GET_CODE (mem) == PLUS
4158         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4159       return \"ldr\\t%0, %1\";
4160       
4161     if (which_alternative == 0)
4162       return \"ldrsb\\t%0, %1\";
4163       
4164     ops[0] = operands[0];
4165     
4166     if (GET_CODE (mem) == PLUS)
4167       {
4168         rtx a = XEXP (mem, 0);
4169         rtx b = XEXP (mem, 1);
4170         
4171         ops[1] = a;
4172         ops[2] = b;
4173
4174         if (GET_CODE (a) == REG)
4175           {
4176             if (GET_CODE (b) == REG)
4177               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4178             else if (REGNO (a) == REGNO (ops[0]))
4179               {
4180                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4181                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4182               }
4183             else
4184               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4185           }
4186         else
4187           {
4188             gcc_assert (GET_CODE (b) == REG);
4189             if (REGNO (b) == REGNO (ops[0]))
4190               {
4191                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4192                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4193               }
4194             else
4195               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4196           }
4197       }
4198     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4199       {
4200         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4201         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4202       }
4203     else
4204       {
4205         ops[1] = mem;
4206         ops[2] = const0_rtx;
4207         
4208         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4209       }
4210     return \"\";
4211   }"
4212   [(set_attr "length" "2,2,4")
4213    (set_attr "type" "alu_shift,load_byte,load_byte")
4214    (set_attr "pool_range" "*,32,32")]
4215 )
4216
4217 (define_expand "extendsfdf2"
4218   [(set (match_operand:DF                  0 "s_register_operand" "")
4219         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4220   "TARGET_32BIT && TARGET_HARD_FLOAT"
4221   ""
4222 )
4223 \f
4224 ;; Move insns (including loads and stores)
4225
4226 ;; XXX Just some ideas about movti.
4227 ;; I don't think these are a good idea on the arm, there just aren't enough
4228 ;; registers
4229 ;;(define_expand "loadti"
4230 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4231 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4232 ;;  "" "")
4233
4234 ;;(define_expand "storeti"
4235 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4236 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4237 ;;  "" "")
4238
4239 ;;(define_expand "movti"
4240 ;;  [(set (match_operand:TI 0 "general_operand" "")
4241 ;;      (match_operand:TI 1 "general_operand" ""))]
4242 ;;  ""
4243 ;;  "
4244 ;;{
4245 ;;  rtx insn;
4246 ;;
4247 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4248 ;;    operands[1] = copy_to_reg (operands[1]);
4249 ;;  if (GET_CODE (operands[0]) == MEM)
4250 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4251 ;;  else if (GET_CODE (operands[1]) == MEM)
4252 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4253 ;;  else
4254 ;;    FAIL;
4255 ;;
4256 ;;  emit_insn (insn);
4257 ;;  DONE;
4258 ;;}")
4259
4260 ;; Recognize garbage generated above.
4261
4262 ;;(define_insn ""
4263 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4264 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4265 ;;  ""
4266 ;;  "*
4267 ;;  {
4268 ;;    register mem = (which_alternative < 3);
4269 ;;    register const char *template;
4270 ;;
4271 ;;    operands[mem] = XEXP (operands[mem], 0);
4272 ;;    switch (which_alternative)
4273 ;;      {
4274 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4275 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4276 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4277 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4278 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4279 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4280 ;;      }
4281 ;;    output_asm_insn (template, operands);
4282 ;;    return \"\";
4283 ;;  }")
4284
4285 (define_expand "movdi"
4286   [(set (match_operand:DI 0 "general_operand" "")
4287         (match_operand:DI 1 "general_operand" ""))]
4288   "TARGET_EITHER"
4289   "
4290   if (!no_new_pseudos)
4291     {
4292       if (GET_CODE (operands[0]) != REG)
4293         operands[1] = force_reg (DImode, operands[1]);
4294     }
4295   "
4296 )
4297
4298 (define_insn "*arm_movdi"
4299   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4300         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4301   "TARGET_ARM
4302    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4303    && !TARGET_IWMMXT
4304    && (   register_operand (operands[0], DImode)
4305        || register_operand (operands[1], DImode))"
4306   "*
4307   switch (which_alternative)
4308     {
4309     case 0:
4310     case 1:
4311     case 2:
4312       return \"#\";
4313     default:
4314       return output_move_double (operands);
4315     }
4316   "
4317   [(set_attr "length" "8,12,16,8,8")
4318    (set_attr "type" "*,*,*,load2,store2")
4319    (set_attr "pool_range" "*,*,*,1020,*")
4320    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4321 )
4322
4323 (define_split
4324   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4325         (match_operand:ANY64 1 "const_double_operand" ""))]
4326   "TARGET_32BIT
4327    && reload_completed
4328    && (arm_const_double_inline_cost (operands[1])
4329        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4330   [(const_int 0)]
4331   "
4332   arm_split_constant (SET, SImode, curr_insn,
4333                       INTVAL (gen_lowpart (SImode, operands[1])),
4334                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4335   arm_split_constant (SET, SImode, curr_insn,
4336                       INTVAL (gen_highpart_mode (SImode,
4337                                                  GET_MODE (operands[0]),
4338                                                  operands[1])),
4339                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4340   DONE;
4341   "
4342 )
4343
4344 ; If optimizing for size, or if we have load delay slots, then 
4345 ; we want to split the constant into two separate operations. 
4346 ; In both cases this may split a trivial part into a single data op
4347 ; leaving a single complex constant to load.  We can also get longer
4348 ; offsets in a LDR which means we get better chances of sharing the pool
4349 ; entries.  Finally, we can normally do a better job of scheduling
4350 ; LDR instructions than we can with LDM.
4351 ; This pattern will only match if the one above did not.
4352 (define_split
4353   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4354         (match_operand:ANY64 1 "const_double_operand" ""))]
4355   "TARGET_ARM && reload_completed
4356    && arm_const_double_by_parts (operands[1])"
4357   [(set (match_dup 0) (match_dup 1))
4358    (set (match_dup 2) (match_dup 3))]
4359   "
4360   operands[2] = gen_highpart (SImode, operands[0]);
4361   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4362                                    operands[1]);
4363   operands[0] = gen_lowpart (SImode, operands[0]);
4364   operands[1] = gen_lowpart (SImode, operands[1]);
4365   "
4366 )
4367
4368 (define_split
4369   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4370         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4371   "TARGET_EITHER && reload_completed"
4372   [(set (match_dup 0) (match_dup 1))
4373    (set (match_dup 2) (match_dup 3))]
4374   "
4375   operands[2] = gen_highpart (SImode, operands[0]);
4376   operands[3] = gen_highpart (SImode, operands[1]);
4377   operands[0] = gen_lowpart (SImode, operands[0]);
4378   operands[1] = gen_lowpart (SImode, operands[1]);
4379
4380   /* Handle a partial overlap.  */
4381   if (rtx_equal_p (operands[0], operands[3]))
4382     {
4383       rtx tmp0 = operands[0];
4384       rtx tmp1 = operands[1];
4385
4386       operands[0] = operands[2];
4387       operands[1] = operands[3];
4388       operands[2] = tmp0;
4389       operands[3] = tmp1;
4390     }
4391   "
4392 )
4393
4394 ;; We can't actually do base+index doubleword loads if the index and
4395 ;; destination overlap.  Split here so that we at least have chance to
4396 ;; schedule.
4397 (define_split
4398   [(set (match_operand:DI 0 "s_register_operand" "")
4399         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4400                          (match_operand:SI 2 "s_register_operand" ""))))]
4401   "TARGET_LDRD
4402   && reg_overlap_mentioned_p (operands[0], operands[1])
4403   && reg_overlap_mentioned_p (operands[0], operands[2])"
4404   [(set (match_dup 4)
4405         (plus:SI (match_dup 1)
4406                  (match_dup 2)))
4407    (set (match_dup 0)
4408         (mem:DI (match_dup 4)))]
4409   "
4410   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4411   "
4412 )
4413
4414 ;;; ??? This should have alternatives for constants.
4415 ;;; ??? This was originally identical to the movdf_insn pattern.
4416 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4417 ;;; thumb_reorg with a memory reference.
4418 (define_insn "*thumb1_movdi_insn"
4419   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4420         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4421   "TARGET_THUMB1
4422    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4423    && (   register_operand (operands[0], DImode)
4424        || register_operand (operands[1], DImode))"
4425   "*
4426   {
4427   switch (which_alternative)
4428     {
4429     default:
4430     case 0:
4431       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4432         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4433       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4434     case 1:
4435       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4436     case 2:
4437       operands[1] = GEN_INT (- INTVAL (operands[1]));
4438       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4439     case 3:
4440       return \"ldmia\\t%1, {%0, %H0}\";
4441     case 4:
4442       return \"stmia\\t%0, {%1, %H1}\";
4443     case 5:
4444       return thumb_load_double_from_address (operands);
4445     case 6:
4446       operands[2] = gen_rtx_MEM (SImode,
4447                              plus_constant (XEXP (operands[0], 0), 4));
4448       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4449       return \"\";
4450     case 7:
4451       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4452         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4453       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4454     }
4455   }"
4456   [(set_attr "length" "4,4,6,2,2,6,4,4")
4457    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4458    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4459 )
4460
4461 (define_expand "movsi"
4462   [(set (match_operand:SI 0 "general_operand" "")
4463         (match_operand:SI 1 "general_operand" ""))]
4464   "TARGET_EITHER"
4465   "
4466   if (TARGET_32BIT)
4467     {
4468       /* Everything except mem = const or mem = mem can be done easily.  */
4469       if (GET_CODE (operands[0]) == MEM)
4470         operands[1] = force_reg (SImode, operands[1]);
4471       if (arm_general_register_operand (operands[0], SImode)
4472           && GET_CODE (operands[1]) == CONST_INT
4473           && !(const_ok_for_arm (INTVAL (operands[1]))
4474                || const_ok_for_arm (~INTVAL (operands[1]))))
4475         {
4476            arm_split_constant (SET, SImode, NULL_RTX,
4477                                INTVAL (operands[1]), operands[0], NULL_RTX,
4478                                optimize && !no_new_pseudos);
4479           DONE;
4480         }
4481     }
4482   else /* TARGET_THUMB1...  */
4483     {
4484       if (!no_new_pseudos)
4485         {
4486           if (GET_CODE (operands[0]) != REG)
4487             operands[1] = force_reg (SImode, operands[1]);
4488         }
4489     }
4490
4491   /* Recognize the case where operand[1] is a reference to thread-local
4492      data and load its address to a register.  */
4493   if (arm_tls_referenced_p (operands[1]))
4494     {
4495       rtx tmp = operands[1];
4496       rtx addend = NULL;
4497
4498       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4499         {
4500           addend = XEXP (XEXP (tmp, 0), 1);
4501           tmp = XEXP (XEXP (tmp, 0), 0);
4502         }
4503
4504       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4505       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4506
4507       tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4508       if (addend)
4509         {
4510           tmp = gen_rtx_PLUS (SImode, tmp, addend);
4511           tmp = force_operand (tmp, operands[0]);
4512         }
4513       operands[1] = tmp;
4514     }
4515   else if (flag_pic
4516            && (CONSTANT_P (operands[1])
4517                || symbol_mentioned_p (operands[1])
4518                || label_mentioned_p (operands[1])))
4519       operands[1] = legitimize_pic_address (operands[1], SImode,
4520                                             (no_new_pseudos ? operands[0] : 0));
4521   "
4522 )
4523
4524 (define_insn "*arm_movsi_insn"
4525   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r, m")
4526         (match_operand:SI 1 "general_operand"      "rI,K,N,mi,r"))]
4527   "TARGET_ARM && ! TARGET_IWMMXT
4528    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4529    && (   register_operand (operands[0], SImode)
4530        || register_operand (operands[1], SImode))"
4531   "@
4532    mov%?\\t%0, %1
4533    mvn%?\\t%0, #%B1
4534    movw%?\\t%0, %1
4535    ldr%?\\t%0, %1
4536    str%?\\t%1, %0"
4537   [(set_attr "type" "*,*,*,load1,store1")
4538    (set_attr "predicable" "yes")
4539    (set_attr "pool_range" "*,*,*,4096,*")
4540    (set_attr "neg_pool_range" "*,*,*,4084,*")]
4541 )
4542
4543 (define_split
4544   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4545         (match_operand:SI 1 "const_int_operand" ""))]
4546   "TARGET_32BIT
4547   && (!(const_ok_for_arm (INTVAL (operands[1]))
4548         || const_ok_for_arm (~INTVAL (operands[1]))))"
4549   [(clobber (const_int 0))]
4550   "
4551   arm_split_constant (SET, SImode, NULL_RTX, 
4552                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4553   DONE;
4554   "
4555 )
4556
4557 (define_insn "*thumb1_movsi_insn"
4558   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4559         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4560   "TARGET_THUMB1
4561    && (   register_operand (operands[0], SImode) 
4562        || register_operand (operands[1], SImode))"
4563   "@
4564    mov  %0, %1
4565    mov  %0, %1
4566    #
4567    #
4568    ldmia\\t%1, {%0}
4569    stmia\\t%0, {%1}
4570    ldr\\t%0, %1
4571    str\\t%1, %0
4572    mov\\t%0, %1"
4573   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4574    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4575    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4576 )
4577
4578 (define_split 
4579   [(set (match_operand:SI 0 "register_operand" "")
4580         (match_operand:SI 1 "const_int_operand" ""))]
4581   "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
4582   [(set (match_dup 0) (match_dup 1))
4583    (set (match_dup 0) (neg:SI (match_dup 0)))]
4584   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4585 )
4586
4587 (define_split 
4588   [(set (match_operand:SI 0 "register_operand" "")
4589         (match_operand:SI 1 "const_int_operand" ""))]
4590   "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
4591   [(set (match_dup 0) (match_dup 1))
4592    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4593   "
4594   {
4595     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4596     unsigned HOST_WIDE_INT mask = 0xff;
4597     int i;
4598     
4599     for (i = 0; i < 25; i++)
4600       if ((val & (mask << i)) == val)
4601         break;
4602
4603     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4604     if (i == 0)
4605       FAIL;
4606
4607     operands[1] = GEN_INT (val >> i);
4608     operands[2] = GEN_INT (i);
4609   }"
4610 )
4611
4612 ;; When generating pic, we need to load the symbol offset into a register.
4613 ;; So that the optimizer does not confuse this with a normal symbol load
4614 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4615 ;; since that is the only type of relocation we can use.
4616
4617 ;; The rather odd constraints on the following are to force reload to leave
4618 ;; the insn alone, and to force the minipool generation pass to then move
4619 ;; the GOT symbol to memory.
4620
4621 (define_insn "pic_load_addr_arm"
4622   [(set (match_operand:SI 0 "s_register_operand" "=r")
4623         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4624   "TARGET_ARM && flag_pic"
4625   "ldr%?\\t%0, %1"
4626   [(set_attr "type" "load1")
4627    (set (attr "pool_range")     (const_int 4096))
4628    (set (attr "neg_pool_range") (const_int 4084))]
4629 )
4630
4631 (define_insn "pic_load_addr_thumb1"
4632   [(set (match_operand:SI 0 "s_register_operand" "=l")
4633         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4634   "TARGET_THUMB1 && flag_pic"
4635   "ldr\\t%0, %1"
4636   [(set_attr "type" "load1")
4637    (set (attr "pool_range") (const_int 1024))]
4638 )
4639
4640 ;; This variant is used for AOF assembly, since it needs to mention the
4641 ;; pic register in the rtl.
4642 (define_expand "pic_load_addr_based"
4643   [(set (match_operand:SI 0 "s_register_operand" "")
4644         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4645   "TARGET_ARM && flag_pic"
4646   "operands[2] = cfun->machine->pic_reg;"
4647 )
4648
4649 (define_insn "*pic_load_addr_based_insn"
4650   [(set (match_operand:SI 0 "s_register_operand" "=r")
4651         (unspec:SI [(match_operand 1 "" "")
4652                     (match_operand 2 "s_register_operand" "r")]
4653                    UNSPEC_PIC_SYM))]
4654   "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
4655   "*
4656 #ifdef AOF_ASSEMBLER
4657   operands[1] = aof_pic_entry (operands[1]);
4658 #endif
4659   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4660   return \"\";
4661   "
4662   [(set_attr "type" "load1")
4663    (set (attr "pool_range")
4664         (if_then_else (eq_attr "is_thumb" "yes")
4665                       (const_int 1024)
4666                       (const_int 4096)))
4667    (set (attr "neg_pool_range")
4668         (if_then_else (eq_attr "is_thumb" "yes")
4669                       (const_int 0)
4670                       (const_int 4084)))]
4671 )
4672
4673 (define_insn "pic_add_dot_plus_four"
4674   [(set (match_operand:SI 0 "register_operand" "=r")
4675         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4676                              (const (plus:SI (pc) (const_int 4))))]
4677                    UNSPEC_PIC_BASE))
4678    (use (match_operand 2 "" ""))]
4679   "TARGET_THUMB1"
4680   "*
4681   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4682                                      INTVAL (operands[2]));
4683   return \"add\\t%0, %|pc\";
4684   "
4685   [(set_attr "length" "2")]
4686 )
4687
4688 (define_insn "pic_add_dot_plus_eight"
4689   [(set (match_operand:SI 0 "register_operand" "=r")
4690         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4691                              (const (plus:SI (pc) (const_int 8))))]
4692                    UNSPEC_PIC_BASE))
4693    (use (match_operand 2 "" ""))]
4694   "TARGET_ARM"
4695   "*
4696     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4697                                        INTVAL (operands[2]));
4698     return \"add%?\\t%0, %|pc, %1\";
4699   "
4700   [(set_attr "predicable" "yes")]
4701 )
4702
4703 (define_insn "tls_load_dot_plus_eight"
4704   [(set (match_operand:SI 0 "register_operand" "+r")
4705         (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4706                                      (const (plus:SI (pc) (const_int 8))))]
4707                            UNSPEC_PIC_BASE)))
4708    (use (match_operand 2 "" ""))]
4709   "TARGET_ARM"
4710   "*
4711     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4712                                        INTVAL (operands[2]));
4713     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4714   "
4715   [(set_attr "predicable" "yes")]
4716 )
4717
4718 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4719 ;; followed by a load.  These sequences can be crunched down to
4720 ;; tls_load_dot_plus_eight by a peephole.
4721
4722 (define_peephole2
4723   [(parallel [(set (match_operand:SI 0 "register_operand" "")
4724                    (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4725                                         (const (plus:SI (pc) (const_int 8))))]
4726                               UNSPEC_PIC_BASE))
4727               (use (label_ref (match_operand 1 "" "")))])
4728    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4729   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4730   [(parallel [(set (match_dup 2)
4731                    (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4732                                                 (const (plus:SI (pc) (const_int 8))))]
4733                                       UNSPEC_PIC_BASE)))
4734               (use (label_ref (match_dup 1)))])]
4735   ""
4736 )
4737
4738 (define_expand "builtin_setjmp_receiver"
4739   [(label_ref (match_operand 0 "" ""))]
4740   "flag_pic"
4741   "
4742 {
4743   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4744      register.  */
4745   if (arm_pic_register != INVALID_REGNUM)
4746     arm_load_pic_register (1UL << 3);
4747   DONE;
4748 }")
4749
4750 ;; If copying one reg to another we can set the condition codes according to
4751 ;; its value.  Such a move is common after a return from subroutine and the
4752 ;; result is being tested against zero.
4753
4754 (define_insn "*movsi_compare0"
4755   [(set (reg:CC CC_REGNUM)
4756         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4757                     (const_int 0)))
4758    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4759         (match_dup 1))]
4760   "TARGET_32BIT"
4761   "@
4762    cmp%?\\t%0, #0
4763    sub%.\\t%0, %1, #0"
4764   [(set_attr "conds" "set")]
4765 )
4766
4767 ;; Subroutine to store a half word from a register into memory.
4768 ;; Operand 0 is the source register (HImode)
4769 ;; Operand 1 is the destination address in a register (SImode)
4770
4771 ;; In both this routine and the next, we must be careful not to spill
4772 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4773 ;; can generate unrecognizable rtl.
4774
4775 (define_expand "storehi"
4776   [;; store the low byte
4777    (set (match_operand 1 "" "") (match_dup 3))
4778    ;; extract the high byte
4779    (set (match_dup 2)
4780         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4781    ;; store the high byte
4782    (set (match_dup 4) (match_dup 5))]
4783   "TARGET_ARM"
4784   "
4785   {
4786     rtx op1 = operands[1];
4787     rtx addr = XEXP (op1, 0);
4788     enum rtx_code code = GET_CODE (addr);
4789
4790     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4791         || code == MINUS)
4792       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4793
4794     operands[4] = adjust_address (op1, QImode, 1);
4795     operands[1] = adjust_address (operands[1], QImode, 0);
4796     operands[3] = gen_lowpart (QImode, operands[0]);
4797     operands[0] = gen_lowpart (SImode, operands[0]);
4798     operands[2] = gen_reg_rtx (SImode);
4799     operands[5] = gen_lowpart (QImode, operands[2]);
4800   }"
4801 )
4802
4803 (define_expand "storehi_bigend"
4804   [(set (match_dup 4) (match_dup 3))
4805    (set (match_dup 2)
4806         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4807    (set (match_operand 1 "" "") (match_dup 5))]
4808   "TARGET_ARM"
4809   "
4810   {
4811     rtx op1 = operands[1];
4812     rtx addr = XEXP (op1, 0);
4813     enum rtx_code code = GET_CODE (addr);
4814
4815     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4816         || code == MINUS)
4817       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4818
4819     operands[4] = adjust_address (op1, QImode, 1);
4820     operands[1] = adjust_address (operands[1], QImode, 0);
4821     operands[3] = gen_lowpart (QImode, operands[0]);
4822     operands[0] = gen_lowpart (SImode, operands[0]);
4823     operands[2] = gen_reg_rtx (SImode);
4824     operands[5] = gen_lowpart (QImode, operands[2]);
4825   }"
4826 )
4827
4828 ;; Subroutine to store a half word integer constant into memory.
4829 (define_expand "storeinthi"
4830   [(set (match_operand 0 "" "")
4831         (match_operand 1 "" ""))
4832    (set (match_dup 3) (match_dup 2))]
4833   "TARGET_ARM"
4834   "
4835   {
4836     HOST_WIDE_INT value = INTVAL (operands[1]);
4837     rtx addr = XEXP (operands[0], 0);
4838     rtx op0 = operands[0];
4839     enum rtx_code code = GET_CODE (addr);
4840
4841     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4842         || code == MINUS)
4843       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4844
4845     operands[1] = gen_reg_rtx (SImode);
4846     if (BYTES_BIG_ENDIAN)
4847       {
4848         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4849         if ((value & 255) == ((value >> 8) & 255))
4850           operands[2] = operands[1];
4851         else
4852           {
4853             operands[2] = gen_reg_rtx (SImode);
4854             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4855           }
4856       }
4857     else
4858       {
4859         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4860         if ((value & 255) == ((value >> 8) & 255))
4861           operands[2] = operands[1];
4862         else
4863           {
4864             operands[2] = gen_reg_rtx (SImode);
4865             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4866           }
4867       }
4868
4869     operands[3] = adjust_address (op0, QImode, 1);
4870     operands[0] = adjust_address (operands[0], QImode, 0);
4871     operands[2] = gen_lowpart (QImode, operands[2]);
4872     operands[1] = gen_lowpart (QImode, operands[1]);
4873   }"
4874 )
4875
4876 (define_expand "storehi_single_op"
4877   [(set (match_operand:HI 0 "memory_operand" "")
4878         (match_operand:HI 1 "general_operand" ""))]
4879   "TARGET_32BIT && arm_arch4"
4880   "
4881   if (!s_register_operand (operands[1], HImode))
4882     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4883   "
4884 )
4885
4886 (define_expand "movhi"
4887   [(set (match_operand:HI 0 "general_operand" "")
4888         (match_operand:HI 1 "general_operand" ""))]
4889   "TARGET_EITHER"
4890   "
4891   if (TARGET_ARM)
4892     {
4893       if (!no_new_pseudos)
4894         {
4895           if (GET_CODE (operands[0]) == MEM)
4896             {
4897               if (arm_arch4)
4898                 {
4899                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4900                   DONE;
4901                 }
4902               if (GET_CODE (operands[1]) == CONST_INT)
4903                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4904               else
4905                 {
4906                   if (GET_CODE (operands[1]) == MEM)
4907                     operands[1] = force_reg (HImode, operands[1]);
4908                   if (BYTES_BIG_ENDIAN)
4909                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4910                   else
4911                    emit_insn (gen_storehi (operands[1], operands[0]));
4912                 }
4913               DONE;
4914             }
4915           /* Sign extend a constant, and keep it in an SImode reg.  */
4916           else if (GET_CODE (operands[1]) == CONST_INT)
4917             {
4918               rtx reg = gen_reg_rtx (SImode);
4919               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4920
4921               /* If the constant is already valid, leave it alone.  */
4922               if (!const_ok_for_arm (val))
4923                 {
4924                   /* If setting all the top bits will make the constant 
4925                      loadable in a single instruction, then set them.  
4926                      Otherwise, sign extend the number.  */
4927
4928                   if (const_ok_for_arm (~(val | ~0xffff)))
4929                     val |= ~0xffff;
4930                   else if (val & 0x8000)
4931                     val |= ~0xffff;
4932                 }
4933
4934               emit_insn (gen_movsi (reg, GEN_INT (val)));
4935               operands[1] = gen_lowpart (HImode, reg);
4936             }
4937           else if (arm_arch4 && optimize && !no_new_pseudos
4938                    && GET_CODE (operands[1]) == MEM)
4939             {
4940               rtx reg = gen_reg_rtx (SImode);
4941
4942               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4943               operands[1] = gen_lowpart (HImode, reg);
4944             }
4945           else if (!arm_arch4)
4946             {
4947               if (GET_CODE (operands[1]) == MEM)
4948                 {
4949                   rtx base;
4950                   rtx offset = const0_rtx;
4951                   rtx reg = gen_reg_rtx (SImode);
4952
4953                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4954                        || (GET_CODE (base) == PLUS
4955                            && (GET_CODE (offset = XEXP (base, 1))
4956                                == CONST_INT)
4957                            && ((INTVAL(offset) & 1) != 1)
4958                            && GET_CODE (base = XEXP (base, 0)) == REG))
4959                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4960                     {
4961                       rtx new;
4962
4963                       new = widen_memory_access (operands[1], SImode,
4964                                                  ((INTVAL (offset) & ~3)
4965                                                   - INTVAL (offset)));
4966                       emit_insn (gen_movsi (reg, new));
4967                       if (((INTVAL (offset) & 2) != 0)
4968                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4969                         {
4970                           rtx reg2 = gen_reg_rtx (SImode);
4971
4972                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4973                           reg = reg2;
4974                         }
4975                     }
4976                   else
4977                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4978
4979                   operands[1] = gen_lowpart (HImode, reg);
4980                }
4981            }
4982         }
4983       /* Handle loading a large integer during reload.  */
4984       else if (GET_CODE (operands[1]) == CONST_INT
4985                && !const_ok_for_arm (INTVAL (operands[1]))
4986                && !const_ok_for_arm (~INTVAL (operands[1])))
4987         {
4988           /* Writing a constant to memory needs a scratch, which should
4989              be handled with SECONDARY_RELOADs.  */
4990           gcc_assert (GET_CODE (operands[0]) == REG);
4991
4992           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4993           emit_insn (gen_movsi (operands[0], operands[1]));
4994           DONE;
4995        }
4996     }
4997   else if (TARGET_THUMB2)
4998     {
4999       /* Thumb-2 can do everything except mem=mem and mem=const easily.  */
5000       if (!no_new_pseudos)
5001         {
5002           if (GET_CODE (operands[0]) != REG)
5003             operands[1] = force_reg (HImode, operands[1]);
5004           /* Zero extend a constant, and keep it in an SImode reg.  */
5005           else if (GET_CODE (operands[1]) == CONST_INT)
5006             {
5007               rtx reg = gen_reg_rtx (SImode);
5008               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5009
5010               emit_insn (gen_movsi (reg, GEN_INT (val)));
5011               operands[1] = gen_lowpart (HImode, reg);
5012             }
5013         }
5014     }
5015   else /* TARGET_THUMB1 */
5016     {
5017       if (!no_new_pseudos)
5018         {
5019           if (GET_CODE (operands[1]) == CONST_INT)
5020             {
5021               rtx reg = gen_reg_rtx (SImode);
5022
5023               emit_insn (gen_movsi (reg, operands[1]));
5024               operands[1] = gen_lowpart (HImode, reg);
5025             }
5026
5027           /* ??? We shouldn't really get invalid addresses here, but this can
5028              happen if we are passed a SP (never OK for HImode/QImode) or 
5029              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
5030              HImode/QImode) relative address.  */
5031           /* ??? This should perhaps be fixed elsewhere, for instance, in
5032              fixup_stack_1, by checking for other kinds of invalid addresses,
5033              e.g. a bare reference to a virtual register.  This may confuse the
5034              alpha though, which must handle this case differently.  */
5035           if (GET_CODE (operands[0]) == MEM
5036               && !memory_address_p (GET_MODE (operands[0]),
5037                                     XEXP (operands[0], 0)))
5038             operands[0]
5039               = replace_equiv_address (operands[0],
5040                                        copy_to_reg (XEXP (operands[0], 0)));
5041    
5042           if (GET_CODE (operands[1]) == MEM
5043               && !memory_address_p (GET_MODE (operands[1]),
5044                                     XEXP (operands[1], 0)))
5045             operands[1]
5046               = replace_equiv_address (operands[1],
5047                                        copy_to_reg (XEXP (operands[1], 0)));
5048
5049           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5050             {
5051               rtx reg = gen_reg_rtx (SImode);
5052
5053               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5054               operands[1] = gen_lowpart (HImode, reg);
5055             }
5056
5057           if (GET_CODE (operands[0]) == MEM)
5058             operands[1] = force_reg (HImode, operands[1]);
5059         }
5060       else if (GET_CODE (operands[1]) == CONST_INT
5061                 && !satisfies_constraint_I (operands[1]))
5062         {
5063           /* Handle loading a large integer during reload.  */
5064
5065           /* Writing a constant to memory needs a scratch, which should
5066              be handled with SECONDARY_RELOADs.  */
5067           gcc_assert (GET_CODE (operands[0]) == REG);
5068
5069           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5070           emit_insn (gen_movsi (operands[0], operands[1]));
5071           DONE;
5072         }
5073     }
5074   "
5075 )
5076
5077 (define_insn "*thumb1_movhi_insn"
5078   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5079         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
5080   "TARGET_THUMB1
5081    && (   register_operand (operands[0], HImode)
5082        || register_operand (operands[1], HImode))"
5083   "*
5084   switch (which_alternative)
5085     {
5086     case 0: return \"add        %0, %1, #0\";
5087     case 2: return \"strh       %1, %0\";
5088     case 3: return \"mov        %0, %1\";
5089     case 4: return \"mov        %0, %1\";
5090     case 5: return \"mov        %0, %1\";
5091     default: gcc_unreachable ();
5092     case 1:
5093       /* The stack pointer can end up being taken as an index register.
5094           Catch this case here and deal with it.  */
5095       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5096           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5097           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5098         {
5099           rtx ops[2];
5100           ops[0] = operands[0];
5101           ops[1] = XEXP (XEXP (operands[1], 0), 0);
5102       
5103           output_asm_insn (\"mov        %0, %1\", ops);
5104
5105           XEXP (XEXP (operands[1], 0), 0) = operands[0];
5106     
5107         }
5108       return \"ldrh     %0, %1\";
5109     }"
5110   [(set_attr "length" "2,4,2,2,2,2")
5111    (set_attr "type" "*,load1,store1,*,*,*")]
5112 )
5113
5114
5115 (define_expand "movhi_bytes"
5116   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5117    (set (match_dup 3)
5118         (zero_extend:SI (match_dup 6)))
5119    (set (match_operand:SI 0 "" "")
5120          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5121   "TARGET_ARM"
5122   "
5123   {
5124     rtx mem1, mem2;
5125     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5126
5127     mem1 = change_address (operands[1], QImode, addr);
5128     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5129     operands[0] = gen_lowpart (SImode, operands[0]);
5130     operands[1] = mem1;
5131     operands[2] = gen_reg_rtx (SImode);
5132     operands[3] = gen_reg_rtx (SImode);
5133     operands[6] = mem2;
5134
5135     if (BYTES_BIG_ENDIAN)
5136       {
5137         operands[4] = operands[2];
5138         operands[5] = operands[3];
5139       }
5140     else
5141       {
5142         operands[4] = operands[3];
5143         operands[5] = operands[2];
5144       }
5145   }"
5146 )
5147
5148 (define_expand "movhi_bigend"
5149   [(set (match_dup 2)
5150         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5151                    (const_int 16)))
5152    (set (match_dup 3)
5153         (ashiftrt:SI (match_dup 2) (const_int 16)))
5154    (set (match_operand:HI 0 "s_register_operand" "")
5155         (match_dup 4))]
5156   "TARGET_ARM"
5157   "
5158   operands[2] = gen_reg_rtx (SImode);
5159   operands[3] = gen_reg_rtx (SImode);
5160   operands[4] = gen_lowpart (HImode, operands[3]);
5161   "
5162 )
5163
5164 ;; Pattern to recognize insn generated default case above
5165 (define_insn "*movhi_insn_arch4"
5166   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
5167         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5168   "TARGET_ARM
5169    && arm_arch4
5170    && (GET_CODE (operands[1]) != CONST_INT
5171        || const_ok_for_arm (INTVAL (operands[1]))
5172        || const_ok_for_arm (~INTVAL (operands[1])))"
5173   "@
5174    mov%?\\t%0, %1\\t%@ movhi
5175    mvn%?\\t%0, #%B1\\t%@ movhi
5176    str%(h%)\\t%1, %0\\t%@ movhi
5177    ldr%(h%)\\t%0, %1\\t%@ movhi"
5178   [(set_attr "type" "*,*,store1,load1")
5179    (set_attr "predicable" "yes")
5180    (set_attr "pool_range" "*,*,*,256")
5181    (set_attr "neg_pool_range" "*,*,*,244")]
5182 )
5183
5184 (define_insn "*movhi_bytes"
5185   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5186         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5187   "TARGET_ARM"
5188   "@
5189    mov%?\\t%0, %1\\t%@ movhi
5190    mvn%?\\t%0, #%B1\\t%@ movhi"
5191   [(set_attr "predicable" "yes")]
5192 )
5193
5194 (define_expand "thumb_movhi_clobber"
5195   [(set (match_operand:HI     0 "memory_operand"   "")
5196         (match_operand:HI     1 "register_operand" ""))
5197    (clobber (match_operand:DI 2 "register_operand" ""))]
5198   "TARGET_THUMB1"
5199   "
5200   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5201       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5202     {
5203       emit_insn (gen_movhi (operands[0], operands[1]));
5204       DONE;
5205     }
5206   /* XXX Fixme, need to handle other cases here as well.  */
5207   gcc_unreachable ();
5208   "
5209 )
5210         
5211 ;; We use a DImode scratch because we may occasionally need an additional
5212 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5213 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5214 (define_expand "reload_outhi"
5215   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5216               (match_operand:HI 1 "s_register_operand"        "r")
5217               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5218   "TARGET_EITHER"
5219   "if (TARGET_ARM)
5220      arm_reload_out_hi (operands);
5221    else
5222      thumb_reload_out_hi (operands);
5223   DONE;
5224   "
5225 )
5226
5227 (define_expand "reload_inhi"
5228   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5229               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5230               (match_operand:DI 2 "s_register_operand" "=&r")])]
5231   "TARGET_EITHER"
5232   "
5233   if (TARGET_ARM)
5234     arm_reload_in_hi (operands);
5235   else
5236     thumb_reload_out_hi (operands);
5237   DONE;
5238 ")
5239
5240 (define_expand "movqi"
5241   [(set (match_operand:QI 0 "general_operand" "")
5242         (match_operand:QI 1 "general_operand" ""))]
5243   "TARGET_EITHER"
5244   "
5245   /* Everything except mem = const or mem = mem can be done easily */
5246
5247   if (!no_new_pseudos)
5248     {
5249       if (GET_CODE (operands[1]) == CONST_INT)
5250         {
5251           rtx reg = gen_reg_rtx (SImode);
5252
5253           emit_insn (gen_movsi (reg, operands[1]));
5254           operands[1] = gen_lowpart (QImode, reg);
5255         }
5256
5257       if (TARGET_THUMB)
5258         {
5259           /* ??? We shouldn't really get invalid addresses here, but this can
5260              happen if we are passed a SP (never OK for HImode/QImode) or
5261              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5262              HImode/QImode) relative address.  */
5263           /* ??? This should perhaps be fixed elsewhere, for instance, in
5264              fixup_stack_1, by checking for other kinds of invalid addresses,
5265              e.g. a bare reference to a virtual register.  This may confuse the
5266              alpha though, which must handle this case differently.  */
5267           if (GET_CODE (operands[0]) == MEM
5268               && !memory_address_p (GET_MODE (operands[0]),
5269                                      XEXP (operands[0], 0)))
5270             operands[0]
5271               = replace_equiv_address (operands[0],
5272                                        copy_to_reg (XEXP (operands[0], 0)));
5273           if (GET_CODE (operands[1]) == MEM
5274               && !memory_address_p (GET_MODE (operands[1]),
5275                                     XEXP (operands[1], 0)))
5276              operands[1]
5277                = replace_equiv_address (operands[1],
5278                                         copy_to_reg (XEXP (operands[1], 0)));
5279         }
5280
5281       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5282         {
5283           rtx reg = gen_reg_rtx (SImode);
5284
5285           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5286           operands[1] = gen_lowpart (QImode, reg);
5287         }
5288
5289       if (GET_CODE (operands[0]) == MEM)
5290         operands[1] = force_reg (QImode, operands[1]);
5291     }
5292   else if (TARGET_THUMB
5293            && GET_CODE (operands[1]) == CONST_INT
5294            && !satisfies_constraint_I (operands[1]))
5295     {
5296       /* Handle loading a large integer during reload.  */
5297
5298       /* Writing a constant to memory needs a scratch, which should
5299          be handled with SECONDARY_RELOADs.  */
5300       gcc_assert (GET_CODE (operands[0]) == REG);
5301
5302       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5303       emit_insn (gen_movsi (operands[0], operands[1]));
5304       DONE;
5305     }
5306   "
5307 )
5308
5309
5310 (define_insn "*arm_movqi_insn"
5311   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5312         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5313   "TARGET_32BIT
5314    && (   register_operand (operands[0], QImode)
5315        || register_operand (operands[1], QImode))"
5316   "@
5317    mov%?\\t%0, %1
5318    mvn%?\\t%0, #%B1
5319    ldr%(b%)\\t%0, %1
5320    str%(b%)\\t%1, %0"
5321   [(set_attr "type" "*,*,load1,store1")
5322    (set_attr "predicable" "yes")]
5323 )
5324
5325 (define_insn "*thumb1_movqi_insn"
5326   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5327         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5328   "TARGET_THUMB1
5329    && (   register_operand (operands[0], QImode)
5330        || register_operand (operands[1], QImode))"
5331   "@
5332    add\\t%0, %1, #0
5333    ldrb\\t%0, %1
5334    strb\\t%1, %0
5335    mov\\t%0, %1
5336    mov\\t%0, %1
5337    mov\\t%0, %1"
5338   [(set_attr "length" "2")
5339    (set_attr "type" "*,load1,store1,*,*,*")
5340    (set_attr "pool_range" "*,32,*,*,*,*")]
5341 )
5342
5343 (define_expand "movsf"
5344   [(set (match_operand:SF 0 "general_operand" "")
5345         (match_operand:SF 1 "general_operand" ""))]
5346   "TARGET_EITHER"
5347   "
5348   if (TARGET_32BIT)
5349     {
5350       if (GET_CODE (operands[0]) == MEM)
5351         operands[1] = force_reg (SFmode, operands[1]);
5352     }
5353   else /* TARGET_THUMB1 */
5354     {
5355       if (!no_new_pseudos)
5356         {
5357            if (GET_CODE (operands[0]) != REG)
5358              operands[1] = force_reg (SFmode, operands[1]);
5359         }
5360     }
5361   "
5362 )
5363
5364 ;; Transform a floating-point move of a constant into a core register into
5365 ;; an SImode operation.
5366 (define_split
5367   [(set (match_operand:SF 0 "arm_general_register_operand" "")
5368         (match_operand:SF 1 "immediate_operand" ""))]
5369   "TARGET_32BIT
5370    && reload_completed
5371    && GET_CODE (operands[1]) == CONST_DOUBLE"
5372   [(set (match_dup 2) (match_dup 3))]
5373   "
5374   operands[2] = gen_lowpart (SImode, operands[0]);
5375   operands[3] = gen_lowpart (SImode, operands[1]);
5376   if (operands[2] == 0 || operands[3] == 0)
5377     FAIL;
5378   "
5379 )
5380
5381 (define_insn "*arm_movsf_soft_insn"
5382   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5383         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5384   "TARGET_ARM
5385    && TARGET_SOFT_FLOAT
5386    && (GET_CODE (operands[0]) != MEM
5387        || register_operand (operands[1], SFmode))"
5388   "@
5389    mov%?\\t%0, %1
5390    ldr%?\\t%0, %1\\t%@ float
5391    str%?\\t%1, %0\\t%@ float"
5392   [(set_attr "length" "4,4,4")
5393    (set_attr "predicable" "yes")
5394    (set_attr "type" "*,load1,store1")
5395    (set_attr "pool_range" "*,4096,*")
5396    (set_attr "neg_pool_range" "*,4084,*")]
5397 )
5398
5399 ;;; ??? This should have alternatives for constants.
5400 (define_insn "*thumb1_movsf_insn"
5401   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5402         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5403   "TARGET_THUMB1
5404    && (   register_operand (operands[0], SFmode) 
5405        || register_operand (operands[1], SFmode))"
5406   "@
5407    add\\t%0, %1, #0
5408    ldmia\\t%1, {%0}
5409    stmia\\t%0, {%1}
5410    ldr\\t%0, %1
5411    str\\t%1, %0
5412    mov\\t%0, %1
5413    mov\\t%0, %1"
5414   [(set_attr "length" "2")
5415    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5416    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5417 )
5418
5419 (define_expand "movdf"
5420   [(set (match_operand:DF 0 "general_operand" "")
5421         (match_operand:DF 1 "general_operand" ""))]
5422   "TARGET_EITHER"
5423   "
5424   if (TARGET_32BIT)
5425     {
5426       if (GET_CODE (operands[0]) == MEM)
5427         operands[1] = force_reg (DFmode, operands[1]);
5428     }
5429   else /* TARGET_THUMB */
5430     {
5431       if (!no_new_pseudos)
5432         {
5433           if (GET_CODE (operands[0]) != REG)
5434             operands[1] = force_reg (DFmode, operands[1]);
5435         }
5436     }
5437   "
5438 )
5439
5440 ;; Reloading a df mode value stored in integer regs to memory can require a
5441 ;; scratch reg.
5442 (define_expand "reload_outdf"
5443   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5444    (match_operand:DF 1 "s_register_operand" "r")
5445    (match_operand:SI 2 "s_register_operand" "=&r")]
5446   "TARGET_32BIT"
5447   "
5448   {
5449     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5450
5451     if (code == REG)
5452       operands[2] = XEXP (operands[0], 0);
5453     else if (code == POST_INC || code == PRE_DEC)
5454       {
5455         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5456         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5457         emit_insn (gen_movdi (operands[0], operands[1]));
5458         DONE;
5459       }
5460     else if (code == PRE_INC)
5461       {
5462         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5463
5464         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5465         operands[2] = reg;
5466       }
5467     else if (code == POST_DEC)
5468       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5469     else
5470       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5471                              XEXP (XEXP (operands[0], 0), 1)));
5472
5473     emit_insn (gen_rtx_SET (VOIDmode,
5474                             replace_equiv_address (operands[0], operands[2]),
5475                             operands[1]));
5476
5477     if (code == POST_DEC)
5478       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5479
5480     DONE;
5481   }"
5482 )
5483
5484 (define_insn "*movdf_soft_insn"
5485   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5486         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5487   "TARGET_ARM && TARGET_SOFT_FLOAT
5488    && (   register_operand (operands[0], DFmode)
5489        || register_operand (operands[1], DFmode))"
5490   "*
5491   switch (which_alternative)
5492     {
5493     case 0:
5494     case 1:
5495     case 2:
5496       return \"#\";
5497     default:
5498       return output_move_double (operands);
5499     }
5500   "
5501   [(set_attr "length" "8,12,16,8,8")
5502    (set_attr "type" "*,*,*,load2,store2")
5503    (set_attr "pool_range" "1020")
5504    (set_attr "neg_pool_range" "1008")]
5505 )
5506
5507 ;;; ??? This should have alternatives for constants.
5508 ;;; ??? This was originally identical to the movdi_insn pattern.
5509 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5510 ;;; thumb_reorg with a memory reference.
5511 (define_insn "*thumb_movdf_insn"
5512   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5513         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5514   "TARGET_THUMB1
5515    && (   register_operand (operands[0], DFmode)
5516        || register_operand (operands[1], DFmode))"
5517   "*
5518   switch (which_alternative)
5519     {
5520     default:
5521     case 0:
5522       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5523         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5524       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5525     case 1:
5526       return \"ldmia\\t%1, {%0, %H0}\";
5527     case 2:
5528       return \"stmia\\t%0, {%1, %H1}\";
5529     case 3:
5530       return thumb_load_double_from_address (operands);
5531     case 4:
5532       operands[2] = gen_rtx_MEM (SImode,
5533                                  plus_constant (XEXP (operands[0], 0), 4));
5534       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5535       return \"\";
5536     case 5:
5537       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5538         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5539       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5540     }
5541   "
5542   [(set_attr "length" "4,2,2,6,4,4")
5543    (set_attr "type" "*,load2,store2,load2,store2,*")
5544    (set_attr "pool_range" "*,*,*,1020,*,*")]
5545 )
5546
5547 (define_expand "movxf"
5548   [(set (match_operand:XF 0 "general_operand" "")
5549         (match_operand:XF 1 "general_operand" ""))]
5550   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
5551   "
5552   if (GET_CODE (operands[0]) == MEM)
5553     operands[1] = force_reg (XFmode, operands[1]);
5554   "
5555 )
5556
5557 ;; Vector Moves
5558 (define_expand "movv2si"
5559   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5560         (match_operand:V2SI 1 "general_operand" ""))]
5561   "TARGET_REALLY_IWMMXT"
5562 {
5563 })
5564
5565 (define_expand "movv4hi"
5566   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5567         (match_operand:V4HI 1 "general_operand" ""))]
5568   "TARGET_REALLY_IWMMXT"
5569 {
5570 })
5571
5572 (define_expand "movv8qi"
5573   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5574         (match_operand:V8QI 1 "general_operand" ""))]
5575   "TARGET_REALLY_IWMMXT"
5576 {
5577 })
5578 \f
5579
5580 ;; load- and store-multiple insns
5581 ;; The arm can load/store any set of registers, provided that they are in
5582 ;; ascending order; but that is beyond GCC so stick with what it knows.
5583
5584 (define_expand "load_multiple"
5585   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5586                           (match_operand:SI 1 "" ""))
5587                      (use (match_operand:SI 2 "" ""))])]
5588   "TARGET_32BIT"
5589 {
5590   HOST_WIDE_INT offset = 0;
5591
5592   /* Support only fixed point registers.  */
5593   if (GET_CODE (operands[2]) != CONST_INT
5594       || INTVAL (operands[2]) > 14
5595       || INTVAL (operands[2]) < 2
5596       || GET_CODE (operands[1]) != MEM
5597       || GET_CODE (operands[0]) != REG
5598       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5599       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5600     FAIL;
5601
5602   operands[3]
5603     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5604                              force_reg (SImode, XEXP (operands[1], 0)),
5605                              TRUE, FALSE, operands[1], &offset);
5606 })
5607
5608 ;; Load multiple with write-back
5609
5610 (define_insn "*ldmsi_postinc4"
5611   [(match_parallel 0 "load_multiple_operation"
5612     [(set (match_operand:SI 1 "s_register_operand" "=r")
5613           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5614                    (const_int 16)))
5615      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5616           (mem:SI (match_dup 2)))
5617      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5618           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5619      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5620           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5621      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5622           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5623   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5624   "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
5625   [(set_attr "type" "load4")
5626    (set_attr "predicable" "yes")]
5627 )
5628
5629 (define_insn "*ldmsi_postinc4_thumb1"
5630   [(match_parallel 0 "load_multiple_operation"
5631     [(set (match_operand:SI 1 "s_register_operand" "=l")
5632           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5633                    (const_int 16)))
5634      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5635           (mem:SI (match_dup 2)))
5636      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5637           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5638      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5639           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5640      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5641           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5642   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
5643   "ldmia\\t%1!, {%3, %4, %5, %6}"
5644   [(set_attr "type" "load4")]
5645 )
5646
5647 (define_insn "*ldmsi_postinc3"
5648   [(match_parallel 0 "load_multiple_operation"
5649     [(set (match_operand:SI 1 "s_register_operand" "=r")
5650           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5651                    (const_int 12)))
5652      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5653           (mem:SI (match_dup 2)))
5654      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5655           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5656      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5657           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5658   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5659   "ldm%(ia%)\\t%1!, {%3, %4, %5}"
5660   [(set_attr "type" "load3")
5661    (set_attr "predicable" "yes")]
5662 )
5663
5664 (define_insn "*ldmsi_postinc2"
5665   [(match_parallel 0 "load_multiple_operation"
5666     [(set (match_operand:SI 1 "s_register_operand" "=r")
5667           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5668                    (const_int 8)))
5669      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5670           (mem:SI (match_dup 2)))
5671      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5672           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5673   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5674   "ldm%(ia%)\\t%1!, {%3, %4}"
5675   [(set_attr "type" "load2")
5676    (set_attr "predicable" "yes")]
5677 )
5678
5679 ;; Ordinary load multiple
5680
5681 (define_insn "*ldmsi4"
5682   [(match_parallel 0 "load_multiple_operation"
5683     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5684           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5685      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5686           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5687      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5688           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5689      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5690           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5691   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5692   "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
5693   [(set_attr "type" "load4")
5694    (set_attr "predicable" "yes")]
5695 )
5696
5697 (define_insn "*ldmsi3"
5698   [(match_parallel 0 "load_multiple_operation"
5699     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5700           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5701      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5702           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5703      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5704           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5705   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5706   "ldm%(ia%)\\t%1, {%2, %3, %4}"
5707   [(set_attr "type" "load3")
5708    (set_attr "predicable" "yes")]
5709 )
5710
5711 (define_insn "*ldmsi2"
5712   [(match_parallel 0 "load_multiple_operation"
5713     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5714           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5715      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5716           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5717   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
5718   "ldm%(ia%)\\t%1, {%2, %3}"
5719   [(set_attr "type" "load2")
5720    (set_attr "predicable" "yes")]
5721 )
5722
5723 (define_expand "store_multiple"
5724   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5725                           (match_operand:SI 1 "" ""))
5726                      (use (match_operand:SI 2 "" ""))])]
5727   "TARGET_32BIT"
5728 {
5729   HOST_WIDE_INT offset = 0;
5730
5731   /* Support only fixed point registers.  */
5732   if (GET_CODE (operands[2]) != CONST_INT
5733       || INTVAL (operands[2]) > 14
5734       || INTVAL (operands[2]) < 2
5735       || GET_CODE (operands[1]) != REG
5736       || GET_CODE (operands[0]) != MEM
5737       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5738       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5739     FAIL;
5740
5741   operands[3]
5742     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5743                               force_reg (SImode, XEXP (operands[0], 0)),
5744                               TRUE, FALSE, operands[0], &offset);
5745 })
5746
5747 ;; Store multiple with write-back
5748
5749 (define_insn "*stmsi_postinc4"
5750   [(match_parallel 0 "store_multiple_operation"
5751     [(set (match_operand:SI 1 "s_register_operand" "=r")
5752           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5753                    (const_int 16)))
5754      (set (mem:SI (match_dup 2))
5755           (match_operand:SI 3 "arm_hard_register_operand" ""))
5756      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5757           (match_operand:SI 4 "arm_hard_register_operand" ""))
5758      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5759           (match_operand:SI 5 "arm_hard_register_operand" ""))
5760      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5761           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5762   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5763   "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
5764   [(set_attr "predicable" "yes")
5765    (set_attr "type" "store4")]
5766 )
5767
5768 (define_insn "*stmsi_postinc4_thumb1"
5769   [(match_parallel 0 "store_multiple_operation"
5770     [(set (match_operand:SI 1 "s_register_operand" "=l")
5771           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5772                    (const_int 16)))
5773      (set (mem:SI (match_dup 2))
5774           (match_operand:SI 3 "arm_hard_register_operand" ""))
5775      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5776           (match_operand:SI 4 "arm_hard_register_operand" ""))
5777      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5778           (match_operand:SI 5 "arm_hard_register_operand" ""))
5779      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5780           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5781   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
5782   "stmia\\t%1!, {%3, %4, %5, %6}"
5783   [(set_attr "type" "store4")]
5784 )
5785
5786 (define_insn "*stmsi_postinc3"
5787   [(match_parallel 0 "store_multiple_operation"
5788     [(set (match_operand:SI 1 "s_register_operand" "=r")
5789           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5790                    (const_int 12)))
5791      (set (mem:SI (match_dup 2))
5792           (match_operand:SI 3 "arm_hard_register_operand" ""))
5793      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5794           (match_operand:SI 4 "arm_hard_register_operand" ""))
5795      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5796           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5797   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5798   "stm%(ia%)\\t%1!, {%3, %4, %5}"
5799   [(set_attr "predicable" "yes")
5800    (set_attr "type" "store3")]
5801 )
5802
5803 (define_insn "*stmsi_postinc2"
5804   [(match_parallel 0 "store_multiple_operation"
5805     [(set (match_operand:SI 1 "s_register_operand" "=r")
5806           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5807                    (const_int 8)))
5808      (set (mem:SI (match_dup 2))
5809           (match_operand:SI 3 "arm_hard_register_operand" ""))
5810      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5811           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5812   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5813   "stm%(ia%)\\t%1!, {%3, %4}"
5814   [(set_attr "predicable" "yes")
5815    (set_attr "type" "store2")]
5816 )
5817
5818 ;; Ordinary store multiple
5819
5820 (define_insn "*stmsi4"
5821   [(match_parallel 0 "store_multiple_operation"
5822     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5823           (match_operand:SI 2 "arm_hard_register_operand" ""))
5824      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5825           (match_operand:SI 3 "arm_hard_register_operand" ""))
5826      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5827           (match_operand:SI 4 "arm_hard_register_operand" ""))
5828      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5829           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5830   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5831   "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
5832   [(set_attr "predicable" "yes")
5833    (set_attr "type" "store4")]
5834 )
5835
5836 (define_insn "*stmsi3"
5837   [(match_parallel 0 "store_multiple_operation"
5838     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5839           (match_operand:SI 2 "arm_hard_register_operand" ""))
5840      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5841           (match_operand:SI 3 "arm_hard_register_operand" ""))
5842      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5843           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5844   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5845   "stm%(ia%)\\t%1, {%2, %3, %4}"
5846   [(set_attr "predicable" "yes")
5847    (set_attr "type" "store3")]
5848 )
5849
5850 (define_insn "*stmsi2"
5851   [(match_parallel 0 "store_multiple_operation"
5852     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5853           (match_operand:SI 2 "arm_hard_register_operand" ""))
5854      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5855           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5856   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
5857   "stm%(ia%)\\t%1, {%2, %3}"
5858   [(set_attr "predicable" "yes")
5859    (set_attr "type" "store2")]
5860 )
5861
5862 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5863 ;; We could let this apply for blocks of less than this, but it clobbers so
5864 ;; many registers that there is then probably a better way.
5865
5866 (define_expand "movmemqi"
5867   [(match_operand:BLK 0 "general_operand" "")
5868    (match_operand:BLK 1 "general_operand" "")
5869    (match_operand:SI 2 "const_int_operand" "")
5870    (match_operand:SI 3 "const_int_operand" "")]
5871   "TARGET_EITHER"
5872   "
5873   if (TARGET_32BIT)
5874     {
5875       if (arm_gen_movmemqi (operands))
5876         DONE;
5877       FAIL;
5878     }
5879   else /* TARGET_THUMB1 */
5880     {
5881       if (   INTVAL (operands[3]) != 4
5882           || INTVAL (operands[2]) > 48)
5883         FAIL;
5884
5885       thumb_expand_movmemqi (operands);
5886       DONE;
5887     }
5888   "
5889 )
5890
5891 ;; Thumb block-move insns
5892
5893 (define_insn "movmem12b"
5894   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5895         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5896    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5897         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5898    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5899         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5900    (set (match_operand:SI 0 "register_operand" "=l")
5901         (plus:SI (match_dup 2) (const_int 12)))
5902    (set (match_operand:SI 1 "register_operand" "=l")
5903         (plus:SI (match_dup 3) (const_int 12)))
5904    (clobber (match_scratch:SI 4 "=&l"))
5905    (clobber (match_scratch:SI 5 "=&l"))
5906    (clobber (match_scratch:SI 6 "=&l"))]
5907   "TARGET_THUMB1"
5908   "* return thumb_output_move_mem_multiple (3, operands);"
5909   [(set_attr "length" "4")
5910    ; This isn't entirely accurate...  It loads as well, but in terms of
5911    ; scheduling the following insn it is better to consider it as a store
5912    (set_attr "type" "store3")]
5913 )
5914
5915 (define_insn "movmem8b"
5916   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5917         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5918    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5919         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5920    (set (match_operand:SI 0 "register_operand" "=l")
5921         (plus:SI (match_dup 2) (const_int 8)))
5922    (set (match_operand:SI 1 "register_operand" "=l")
5923         (plus:SI (match_dup 3) (const_int 8)))
5924    (clobber (match_scratch:SI 4 "=&l"))
5925    (clobber (match_scratch:SI 5 "=&l"))]
5926   "TARGET_THUMB1"
5927   "* return thumb_output_move_mem_multiple (2, operands);"
5928   [(set_attr "length" "4")
5929    ; This isn't entirely accurate...  It loads as well, but in terms of
5930    ; scheduling the following insn it is better to consider it as a store
5931    (set_attr "type" "store2")]
5932 )
5933
5934 \f
5935
5936 ;; Compare & branch insns
5937 ;; The range calculations are based as follows:
5938 ;; For forward branches, the address calculation returns the address of
5939 ;; the next instruction.  This is 2 beyond the branch instruction.
5940 ;; For backward branches, the address calculation returns the address of
5941 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5942 ;; instruction for the shortest sequence, and 4 before the branch instruction
5943 ;; if we have to jump around an unconditional branch.
5944 ;; To the basic branch range the PC offset must be added (this is +4).
5945 ;; So for forward branches we have 
5946 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5947 ;; And for backward branches we have 
5948 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5949 ;;
5950 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5951 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5952
5953 (define_expand "cbranchsi4"
5954   [(set (pc) (if_then_else
5955               (match_operator 0 "arm_comparison_operator"
5956                [(match_operand:SI 1 "s_register_operand" "")
5957                 (match_operand:SI 2 "nonmemory_operand" "")])
5958               (label_ref (match_operand 3 "" ""))
5959               (pc)))]
5960   "TARGET_THUMB1"
5961   "
5962   if (thumb1_cmpneg_operand (operands[2], SImode))
5963     {
5964       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5965                                               operands[3], operands[0]));
5966       DONE;
5967     }
5968   if (!thumb1_cmp_operand (operands[2], SImode))
5969     operands[2] = force_reg (SImode, operands[2]);
5970   ")
5971
5972 (define_insn "*cbranchsi4_insn"
5973   [(set (pc) (if_then_else
5974               (match_operator 0 "arm_comparison_operator"
5975                [(match_operand:SI 1 "s_register_operand" "l,*h")
5976                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
5977               (label_ref (match_operand 3 "" ""))
5978               (pc)))]
5979   "TARGET_THUMB1"
5980   "*
5981   output_asm_insn (\"cmp\\t%1, %2\", operands);
5982
5983   switch (get_attr_length (insn))
5984     {
5985     case 4:  return \"b%d0\\t%l3\";
5986     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5987     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5988     }
5989   "
5990   [(set (attr "far_jump")
5991         (if_then_else
5992             (eq_attr "length" "8")
5993             (const_string "yes")
5994             (const_string "no")))
5995    (set (attr "length") 
5996         (if_then_else
5997             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5998                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5999             (const_int 4)
6000             (if_then_else
6001                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6002                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6003                 (const_int 6)
6004                 (const_int 8))))]
6005 )
6006
6007 (define_insn "cbranchsi4_scratch"
6008   [(set (pc) (if_then_else
6009               (match_operator 4 "arm_comparison_operator"
6010                [(match_operand:SI 1 "s_register_operand" "l,0")
6011                 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
6012               (label_ref (match_operand 3 "" ""))
6013               (pc)))
6014    (clobber (match_scratch:SI 0 "=l,l"))]
6015   "TARGET_THUMB1"
6016   "*
6017   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6018
6019   switch (get_attr_length (insn))
6020     {
6021     case 4:  return \"b%d4\\t%l3\";
6022     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6023     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6024     }
6025   "
6026   [(set (attr "far_jump")
6027         (if_then_else
6028             (eq_attr "length" "8")
6029             (const_string "yes")
6030             (const_string "no")))
6031    (set (attr "length") 
6032         (if_then_else
6033             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6034                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6035             (const_int 4)
6036             (if_then_else
6037                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6038                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6039                 (const_int 6)
6040                 (const_int 8))))]
6041 )
6042 (define_insn "*movsi_cbranchsi4"
6043   [(set (pc)
6044         (if_then_else
6045          (match_operator 3 "arm_comparison_operator"
6046           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6047            (const_int 0)])
6048          (label_ref (match_operand 2 "" ""))
6049          (pc)))
6050    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6051         (match_dup 1))]
6052   "TARGET_THUMB1"
6053   "*{
6054   if (which_alternative == 0)
6055     output_asm_insn (\"cmp\t%0, #0\", operands);
6056   else if (which_alternative == 1)
6057     output_asm_insn (\"sub\t%0, %1, #0\", operands);
6058   else
6059     {
6060       output_asm_insn (\"cmp\t%1, #0\", operands);
6061       if (which_alternative == 2)
6062         output_asm_insn (\"mov\t%0, %1\", operands);
6063       else
6064         output_asm_insn (\"str\t%1, %0\", operands);
6065     }
6066   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6067     {
6068     case 4:  return \"b%d3\\t%l2\";
6069     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6070     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6071     }
6072   }"
6073   [(set (attr "far_jump")
6074         (if_then_else
6075             (ior (and (gt (symbol_ref ("which_alternative"))
6076                           (const_int 1))
6077                       (eq_attr "length" "8"))
6078                  (eq_attr "length" "10"))
6079             (const_string "yes")
6080             (const_string "no")))
6081    (set (attr "length")
6082      (if_then_else
6083        (le (symbol_ref ("which_alternative"))
6084                        (const_int 1))
6085        (if_then_else
6086          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6087               (le (minus (match_dup 2) (pc)) (const_int 256)))
6088          (const_int 4)
6089          (if_then_else
6090            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6091                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6092            (const_int 6)
6093            (const_int 8)))
6094        (if_then_else
6095          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6096               (le (minus (match_dup 2) (pc)) (const_int 256)))
6097          (const_int 6)
6098          (if_then_else
6099            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6100                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6101            (const_int 8)
6102            (const_int 10)))))]
6103 )
6104
6105 (define_insn "*negated_cbranchsi4"
6106   [(set (pc)
6107         (if_then_else
6108          (match_operator 0 "equality_operator"
6109           [(match_operand:SI 1 "s_register_operand" "l")
6110            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6111          (label_ref (match_operand 3 "" ""))
6112          (pc)))]
6113   "TARGET_THUMB1"
6114   "*
6115   output_asm_insn (\"cmn\\t%1, %2\", operands);
6116   switch (get_attr_length (insn))
6117     {
6118     case 4:  return \"b%d0\\t%l3\";
6119     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6120     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6121     }
6122   "
6123   [(set (attr "far_jump")
6124         (if_then_else
6125             (eq_attr "length" "8")
6126             (const_string "yes")
6127             (const_string "no")))
6128    (set (attr "length") 
6129         (if_then_else
6130             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6131                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6132             (const_int 4)
6133             (if_then_else
6134                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6135                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6136                 (const_int 6)
6137                 (const_int 8))))]
6138 )
6139
6140 (define_insn "*tbit_cbranch"
6141   [(set (pc)
6142         (if_then_else
6143          (match_operator 0 "equality_operator"
6144           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6145                             (const_int 1)
6146                             (match_operand:SI 2 "const_int_operand" "i"))
6147            (const_int 0)])
6148          (label_ref (match_operand 3 "" ""))
6149          (pc)))
6150    (clobber (match_scratch:SI 4 "=l"))]
6151   "TARGET_THUMB1"
6152   "*
6153   {
6154   rtx op[3];
6155   op[0] = operands[4];
6156   op[1] = operands[1];
6157   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6158
6159   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6160   switch (get_attr_length (insn))
6161     {
6162     case 4:  return \"b%d0\\t%l3\";
6163     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6164     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6165     }
6166   }"
6167   [(set (attr "far_jump")
6168         (if_then_else
6169             (eq_attr "length" "8")
6170             (const_string "yes")
6171             (const_string "no")))
6172    (set (attr "length") 
6173         (if_then_else
6174             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6175                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6176             (const_int 4)
6177             (if_then_else
6178                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6179                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6180                 (const_int 6)
6181                 (const_int 8))))]
6182 )
6183   
6184 (define_insn "*tlobits_cbranch"
6185   [(set (pc)
6186         (if_then_else
6187          (match_operator 0 "equality_operator"
6188           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6189                             (match_operand:SI 2 "const_int_operand" "i")
6190                             (const_int 0))
6191            (const_int 0)])
6192          (label_ref (match_operand 3 "" ""))
6193          (pc)))
6194    (clobber (match_scratch:SI 4 "=l"))]
6195   "TARGET_THUMB1"
6196   "*
6197   {
6198   rtx op[3];
6199   op[0] = operands[4];
6200   op[1] = operands[1];
6201   op[2] = GEN_INT (32 - INTVAL (operands[2]));
6202
6203   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6204   switch (get_attr_length (insn))
6205     {
6206     case 4:  return \"b%d0\\t%l3\";
6207     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6208     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6209     }
6210   }"
6211   [(set (attr "far_jump")
6212         (if_then_else
6213             (eq_attr "length" "8")
6214             (const_string "yes")
6215             (const_string "no")))
6216    (set (attr "length") 
6217         (if_then_else
6218             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6219                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6220             (const_int 4)
6221             (if_then_else
6222                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6223                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6224                 (const_int 6)
6225                 (const_int 8))))]
6226 )
6227   
6228 (define_insn "*tstsi3_cbranch"
6229   [(set (pc)
6230         (if_then_else
6231          (match_operator 3 "equality_operator"
6232           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6233                    (match_operand:SI 1 "s_register_operand" "l"))
6234            (const_int 0)])
6235          (label_ref (match_operand 2 "" ""))
6236          (pc)))]
6237   "TARGET_THUMB1"
6238   "*
6239   {
6240   output_asm_insn (\"tst\\t%0, %1\", operands);
6241   switch (get_attr_length (insn))
6242     {
6243     case 4:  return \"b%d3\\t%l2\";
6244     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6245     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6246     }
6247   }"
6248   [(set (attr "far_jump")
6249         (if_then_else
6250             (eq_attr "length" "8")
6251             (const_string "yes")
6252             (const_string "no")))
6253    (set (attr "length") 
6254         (if_then_else
6255             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6256                  (le (minus (match_dup 2) (pc)) (const_int 256)))
6257             (const_int 4)
6258             (if_then_else
6259                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6260                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6261                 (const_int 6)
6262                 (const_int 8))))]
6263 )
6264   
6265 (define_insn "*andsi3_cbranch"
6266   [(set (pc)
6267         (if_then_else
6268          (match_operator 5 "equality_operator"
6269           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6270                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6271            (const_int 0)])
6272          (label_ref (match_operand 4 "" ""))
6273          (pc)))
6274    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6275         (and:SI (match_dup 2) (match_dup 3)))
6276    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6277   "TARGET_THUMB1"
6278   "*
6279   {
6280   if (which_alternative == 0)
6281     output_asm_insn (\"and\\t%0, %3\", operands);
6282   else if (which_alternative == 1)
6283     {
6284       output_asm_insn (\"and\\t%1, %3\", operands);
6285       output_asm_insn (\"mov\\t%0, %1\", operands);
6286     }
6287   else
6288     {
6289       output_asm_insn (\"and\\t%1, %3\", operands);
6290       output_asm_insn (\"str\\t%1, %0\", operands);
6291     }
6292
6293   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6294     {
6295     case 4:  return \"b%d5\\t%l4\";
6296     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6297     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6298     }
6299   }"
6300   [(set (attr "far_jump")
6301         (if_then_else
6302             (ior (and (eq (symbol_ref ("which_alternative"))
6303                           (const_int 0))
6304                       (eq_attr "length" "8"))
6305                  (eq_attr "length" "10"))
6306             (const_string "yes")
6307             (const_string "no")))
6308    (set (attr "length")
6309      (if_then_else
6310        (eq (symbol_ref ("which_alternative"))
6311                        (const_int 0))
6312        (if_then_else
6313          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6314               (le (minus (match_dup 4) (pc)) (const_int 256)))
6315          (const_int 4)
6316          (if_then_else
6317            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6318                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6319            (const_int 6)
6320            (const_int 8)))
6321        (if_then_else
6322          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6323               (le (minus (match_dup 4) (pc)) (const_int 256)))
6324          (const_int 6)
6325          (if_then_else
6326            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6327                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6328            (const_int 8)
6329            (const_int 10)))))]
6330 )
6331
6332 (define_insn "*orrsi3_cbranch_scratch"
6333   [(set (pc)
6334         (if_then_else
6335          (match_operator 4 "equality_operator"
6336           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6337                    (match_operand:SI 2 "s_register_operand" "l"))
6338            (const_int 0)])
6339          (label_ref (match_operand 3 "" ""))
6340          (pc)))
6341    (clobber (match_scratch:SI 0 "=l"))]
6342   "TARGET_THUMB1"
6343   "*
6344   {
6345   output_asm_insn (\"orr\\t%0, %2\", operands);
6346   switch (get_attr_length (insn))
6347     {
6348     case 4:  return \"b%d4\\t%l3\";
6349     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6350     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6351     }
6352   }"
6353   [(set (attr "far_jump")
6354         (if_then_else
6355             (eq_attr "length" "8")
6356             (const_string "yes")
6357             (const_string "no")))
6358    (set (attr "length") 
6359         (if_then_else
6360             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6361                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6362             (const_int 4)
6363             (if_then_else
6364                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6365                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6366                 (const_int 6)
6367                 (const_int 8))))]
6368 )
6369   
6370 (define_insn "*orrsi3_cbranch"
6371   [(set (pc)
6372         (if_then_else
6373          (match_operator 5 "equality_operator"
6374           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6375                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6376            (const_int 0)])
6377          (label_ref (match_operand 4 "" ""))
6378          (pc)))
6379    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6380         (ior:SI (match_dup 2) (match_dup 3)))
6381    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6382   "TARGET_THUMB1"
6383   "*
6384   {
6385   if (which_alternative == 0)
6386     output_asm_insn (\"orr\\t%0, %3\", operands);
6387   else if (which_alternative == 1)
6388     {
6389       output_asm_insn (\"orr\\t%1, %3\", operands);
6390       output_asm_insn (\"mov\\t%0, %1\", operands);
6391     }
6392   else
6393     {
6394       output_asm_insn (\"orr\\t%1, %3\", operands);
6395       output_asm_insn (\"str\\t%1, %0\", operands);
6396     }
6397
6398   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6399     {
6400     case 4:  return \"b%d5\\t%l4\";
6401     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6402     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6403     }
6404   }"
6405   [(set (attr "far_jump")
6406         (if_then_else
6407             (ior (and (eq (symbol_ref ("which_alternative"))
6408                           (const_int 0))
6409                       (eq_attr "length" "8"))
6410                  (eq_attr "length" "10"))
6411             (const_string "yes")
6412             (const_string "no")))
6413    (set (attr "length")
6414      (if_then_else
6415        (eq (symbol_ref ("which_alternative"))
6416                        (const_int 0))
6417        (if_then_else
6418          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6419               (le (minus (match_dup 4) (pc)) (const_int 256)))
6420          (const_int 4)
6421          (if_then_else
6422            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6423                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6424            (const_int 6)
6425            (const_int 8)))
6426        (if_then_else
6427          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6428               (le (minus (match_dup 4) (pc)) (const_int 256)))
6429          (const_int 6)
6430          (if_then_else
6431            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6432                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6433            (const_int 8)
6434            (const_int 10)))))]
6435 )
6436
6437 (define_insn "*xorsi3_cbranch_scratch"
6438   [(set (pc)
6439         (if_then_else
6440          (match_operator 4 "equality_operator"
6441           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6442                    (match_operand:SI 2 "s_register_operand" "l"))
6443            (const_int 0)])
6444          (label_ref (match_operand 3 "" ""))
6445          (pc)))
6446    (clobber (match_scratch:SI 0 "=l"))]
6447   "TARGET_THUMB1"
6448   "*
6449   {
6450   output_asm_insn (\"eor\\t%0, %2\", operands);
6451   switch (get_attr_length (insn))
6452     {
6453     case 4:  return \"b%d4\\t%l3\";
6454     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6455     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6456     }
6457   }"
6458   [(set (attr "far_jump")
6459         (if_then_else
6460             (eq_attr "length" "8")
6461             (const_string "yes")
6462             (const_string "no")))
6463    (set (attr "length") 
6464         (if_then_else
6465             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6466                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6467             (const_int 4)
6468             (if_then_else
6469                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6470                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6471                 (const_int 6)
6472                 (const_int 8))))]
6473 )
6474   
6475 (define_insn "*xorsi3_cbranch"
6476   [(set (pc)
6477         (if_then_else
6478          (match_operator 5 "equality_operator"
6479           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6480                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6481            (const_int 0)])
6482          (label_ref (match_operand 4 "" ""))
6483          (pc)))
6484    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6485         (xor:SI (match_dup 2) (match_dup 3)))
6486    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6487   "TARGET_THUMB1"
6488   "*
6489   {
6490   if (which_alternative == 0)
6491     output_asm_insn (\"eor\\t%0, %3\", operands);
6492   else if (which_alternative == 1)
6493     {
6494       output_asm_insn (\"eor\\t%1, %3\", operands);
6495       output_asm_insn (\"mov\\t%0, %1\", operands);
6496     }
6497   else
6498     {
6499       output_asm_insn (\"eor\\t%1, %3\", operands);
6500       output_asm_insn (\"str\\t%1, %0\", operands);
6501     }
6502
6503   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6504     {
6505     case 4:  return \"b%d5\\t%l4\";
6506     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6507     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6508     }
6509   }"
6510   [(set (attr "far_jump")
6511         (if_then_else
6512             (ior (and (eq (symbol_ref ("which_alternative"))
6513                           (const_int 0))
6514                       (eq_attr "length" "8"))
6515                  (eq_attr "length" "10"))
6516             (const_string "yes")
6517             (const_string "no")))
6518    (set (attr "length")
6519      (if_then_else
6520        (eq (symbol_ref ("which_alternative"))
6521                        (const_int 0))
6522        (if_then_else
6523          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6524               (le (minus (match_dup 4) (pc)) (const_int 256)))
6525          (const_int 4)
6526          (if_then_else
6527            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6528                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6529            (const_int 6)
6530            (const_int 8)))
6531        (if_then_else
6532          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6533               (le (minus (match_dup 4) (pc)) (const_int 256)))
6534          (const_int 6)
6535          (if_then_else
6536            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6537                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6538            (const_int 8)
6539            (const_int 10)))))]
6540 )
6541
6542 (define_insn "*bicsi3_cbranch_scratch"
6543   [(set (pc)
6544         (if_then_else
6545          (match_operator 4 "equality_operator"
6546           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6547                    (match_operand:SI 1 "s_register_operand" "0"))
6548            (const_int 0)])
6549          (label_ref (match_operand 3 "" ""))
6550          (pc)))
6551    (clobber (match_scratch:SI 0 "=l"))]
6552   "TARGET_THUMB1"
6553   "*
6554   {
6555   output_asm_insn (\"bic\\t%0, %2\", operands);
6556   switch (get_attr_length (insn))
6557     {
6558     case 4:  return \"b%d4\\t%l3\";
6559     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6560     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6561     }
6562   }"
6563   [(set (attr "far_jump")
6564         (if_then_else
6565             (eq_attr "length" "8")
6566             (const_string "yes")
6567             (const_string "no")))
6568    (set (attr "length") 
6569         (if_then_else
6570             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6571                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6572             (const_int 4)
6573             (if_then_else
6574                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6575                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6576                 (const_int 6)
6577                 (const_int 8))))]
6578 )
6579   
6580 (define_insn "*bicsi3_cbranch"
6581   [(set (pc)
6582         (if_then_else
6583          (match_operator 5 "equality_operator"
6584           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6585                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6586            (const_int 0)])
6587          (label_ref (match_operand 4 "" ""))
6588          (pc)))
6589    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6590         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6591    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6592   "TARGET_THUMB1"
6593   "*
6594   {
6595   if (which_alternative == 0)
6596     output_asm_insn (\"bic\\t%0, %3\", operands);
6597   else if (which_alternative <= 2)
6598     {
6599       output_asm_insn (\"bic\\t%1, %3\", operands);
6600       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6601          conditions again, since we're only testing for equality.  */
6602       output_asm_insn (\"mov\\t%0, %1\", operands);
6603     }
6604   else
6605     {
6606       output_asm_insn (\"bic\\t%1, %3\", operands);
6607       output_asm_insn (\"str\\t%1, %0\", operands);
6608     }
6609
6610   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6611     {
6612     case 4:  return \"b%d5\\t%l4\";
6613     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6614     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6615     }
6616   }"
6617   [(set (attr "far_jump")
6618         (if_then_else
6619             (ior (and (eq (symbol_ref ("which_alternative"))
6620                           (const_int 0))
6621                       (eq_attr "length" "8"))
6622                  (eq_attr "length" "10"))
6623             (const_string "yes")
6624             (const_string "no")))
6625    (set (attr "length")
6626      (if_then_else
6627        (eq (symbol_ref ("which_alternative"))
6628                        (const_int 0))
6629        (if_then_else
6630          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6631               (le (minus (match_dup 4) (pc)) (const_int 256)))
6632          (const_int 4)
6633          (if_then_else
6634            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6635                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6636            (const_int 6)
6637            (const_int 8)))
6638        (if_then_else
6639          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6640               (le (minus (match_dup 4) (pc)) (const_int 256)))
6641          (const_int 6)
6642          (if_then_else
6643            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6644                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6645            (const_int 8)
6646            (const_int 10)))))]
6647 )
6648
6649 (define_insn "*cbranchne_decr1"
6650   [(set (pc)
6651         (if_then_else (match_operator 3 "equality_operator"
6652                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6653                         (const_int 0)])
6654                       (label_ref (match_operand 4 "" ""))
6655                       (pc)))
6656    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6657         (plus:SI (match_dup 2) (const_int -1)))
6658    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6659   "TARGET_THUMB1"
6660   "*
6661    {
6662      rtx cond[2];
6663      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6664                                 ? GEU : LTU),
6665                                VOIDmode, operands[2], const1_rtx);
6666      cond[1] = operands[4];
6667
6668      if (which_alternative == 0)
6669        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6670      else if (which_alternative == 1)
6671        {
6672          /* We must provide an alternative for a hi reg because reload 
6673             cannot handle output reloads on a jump instruction, but we
6674             can't subtract into that.  Fortunately a mov from lo to hi
6675             does not clobber the condition codes.  */
6676          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6677          output_asm_insn (\"mov\\t%0, %1\", operands);
6678        }
6679      else
6680        {
6681          /* Similarly, but the target is memory.  */
6682          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6683          output_asm_insn (\"str\\t%1, %0\", operands);
6684        }
6685
6686      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6687        {
6688          case 4:
6689            output_asm_insn (\"b%d0\\t%l1\", cond);
6690            return \"\";
6691          case 6:
6692            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6693            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6694          default:
6695            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6696            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6697        }
6698    }
6699   "
6700   [(set (attr "far_jump")
6701         (if_then_else
6702             (ior (and (eq (symbol_ref ("which_alternative"))
6703                           (const_int 0))
6704                       (eq_attr "length" "8"))
6705                  (eq_attr "length" "10"))
6706             (const_string "yes")
6707             (const_string "no")))
6708    (set_attr_alternative "length"
6709       [
6710        ;; Alternative 0
6711        (if_then_else
6712          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6713               (le (minus (match_dup 4) (pc)) (const_int 256)))
6714          (const_int 4)
6715          (if_then_else
6716            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6717                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6718            (const_int 6)
6719            (const_int 8)))
6720        ;; Alternative 1
6721        (if_then_else
6722          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6723               (le (minus (match_dup 4) (pc)) (const_int 256)))
6724          (const_int 6)
6725          (if_then_else
6726            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6727                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6728            (const_int 8)
6729            (const_int 10)))
6730        ;; Alternative 2
6731        (if_then_else
6732          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6733               (le (minus (match_dup 4) (pc)) (const_int 256)))
6734          (const_int 6)
6735          (if_then_else
6736            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6737                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6738            (const_int 8)
6739            (const_int 10)))
6740        ;; Alternative 3
6741        (if_then_else
6742          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6743               (le (minus (match_dup 4) (pc)) (const_int 256)))
6744          (const_int 6)
6745          (if_then_else
6746            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6747                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6748            (const_int 8)
6749            (const_int 10)))])]
6750 )
6751
6752 (define_insn "*addsi3_cbranch"
6753   [(set (pc)
6754         (if_then_else
6755          (match_operator 4 "comparison_operator"
6756           [(plus:SI
6757             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6758             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6759            (const_int 0)])
6760          (label_ref (match_operand 5 "" ""))
6761          (pc)))
6762    (set
6763     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6764     (plus:SI (match_dup 2) (match_dup 3)))
6765    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6766   "TARGET_THUMB1
6767    && (GET_CODE (operands[4]) == EQ
6768        || GET_CODE (operands[4]) == NE
6769        || GET_CODE (operands[4]) == GE
6770        || GET_CODE (operands[4]) == LT)"
6771   "*
6772    {
6773      rtx cond[3];
6774
6775      
6776      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6777      cond[1] = operands[2];
6778      cond[2] = operands[3];
6779
6780      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6781        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6782      else
6783        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6784
6785      if (which_alternative >= 3
6786          && which_alternative < 4)
6787        output_asm_insn (\"mov\\t%0, %1\", operands);
6788      else if (which_alternative >= 4)
6789        output_asm_insn (\"str\\t%1, %0\", operands);
6790
6791      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6792        {
6793          case 4:
6794            return \"b%d4\\t%l5\";
6795          case 6:
6796            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6797          default:
6798            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6799        }
6800    }
6801   "
6802   [(set (attr "far_jump")
6803         (if_then_else
6804             (ior (and (lt (symbol_ref ("which_alternative"))
6805                           (const_int 3))
6806                       (eq_attr "length" "8"))
6807                  (eq_attr "length" "10"))
6808             (const_string "yes")
6809             (const_string "no")))
6810    (set (attr "length")
6811      (if_then_else
6812        (lt (symbol_ref ("which_alternative"))
6813                        (const_int 3))
6814        (if_then_else
6815          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6816               (le (minus (match_dup 5) (pc)) (const_int 256)))
6817          (const_int 4)
6818          (if_then_else
6819            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6820                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6821            (const_int 6)
6822            (const_int 8)))
6823        (if_then_else
6824          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6825               (le (minus (match_dup 5) (pc)) (const_int 256)))
6826          (const_int 6)
6827          (if_then_else
6828            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6829                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6830            (const_int 8)
6831            (const_int 10)))))]
6832 )
6833
6834 (define_insn "*addsi3_cbranch_scratch"
6835   [(set (pc)
6836         (if_then_else
6837          (match_operator 3 "comparison_operator"
6838           [(plus:SI
6839             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6840             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6841            (const_int 0)])
6842          (label_ref (match_operand 4 "" ""))
6843          (pc)))
6844    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6845   "TARGET_THUMB1
6846    && (GET_CODE (operands[3]) == EQ
6847        || GET_CODE (operands[3]) == NE
6848        || GET_CODE (operands[3]) == GE
6849        || GET_CODE (operands[3]) == LT)"
6850   "*
6851    {
6852      switch (which_alternative)
6853        {
6854        case 0:
6855          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6856          break;
6857        case 1:
6858          output_asm_insn (\"cmn\t%1, %2\", operands);
6859          break;
6860        case 2:
6861          if (INTVAL (operands[2]) < 0)
6862            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6863          else
6864            output_asm_insn (\"add\t%0, %1, %2\", operands);
6865          break;
6866        case 3:
6867          if (INTVAL (operands[2]) < 0)
6868            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6869          else
6870            output_asm_insn (\"add\t%0, %0, %2\", operands);
6871          break;
6872        }
6873
6874      switch (get_attr_length (insn))
6875        {
6876          case 4:
6877            return \"b%d3\\t%l4\";
6878          case 6:
6879            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6880          default:
6881            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6882        }
6883    }
6884   "
6885   [(set (attr "far_jump")
6886         (if_then_else
6887             (eq_attr "length" "8")
6888             (const_string "yes")
6889             (const_string "no")))
6890    (set (attr "length")
6891        (if_then_else
6892          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6893               (le (minus (match_dup 4) (pc)) (const_int 256)))
6894          (const_int 4)
6895          (if_then_else
6896            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6897                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6898            (const_int 6)
6899            (const_int 8))))]
6900 )
6901
6902 (define_insn "*subsi3_cbranch"
6903   [(set (pc)
6904         (if_then_else
6905          (match_operator 4 "comparison_operator"
6906           [(minus:SI
6907             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6908             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6909            (const_int 0)])
6910          (label_ref (match_operand 5 "" ""))
6911          (pc)))
6912    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6913         (minus:SI (match_dup 2) (match_dup 3)))
6914    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6915   "TARGET_THUMB1
6916    && (GET_CODE (operands[4]) == EQ
6917        || GET_CODE (operands[4]) == NE
6918        || GET_CODE (operands[4]) == GE
6919        || GET_CODE (operands[4]) == LT)"
6920   "*
6921    {
6922      if (which_alternative == 0)
6923        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6924      else if (which_alternative == 1)
6925        {
6926          /* We must provide an alternative for a hi reg because reload 
6927             cannot handle output reloads on a jump instruction, but we
6928             can't subtract into that.  Fortunately a mov from lo to hi
6929             does not clobber the condition codes.  */
6930          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6931          output_asm_insn (\"mov\\t%0, %1\", operands);
6932        }
6933      else
6934        {
6935          /* Similarly, but the target is memory.  */
6936          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6937          output_asm_insn (\"str\\t%1, %0\", operands);
6938        }
6939
6940      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6941        {
6942          case 4:
6943            return \"b%d4\\t%l5\";
6944          case 6:
6945            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6946          default:
6947            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6948        }
6949    }
6950   "
6951   [(set (attr "far_jump")
6952         (if_then_else
6953             (ior (and (eq (symbol_ref ("which_alternative"))
6954                           (const_int 0))
6955                       (eq_attr "length" "8"))
6956                  (eq_attr "length" "10"))
6957             (const_string "yes")
6958             (const_string "no")))
6959    (set (attr "length")
6960      (if_then_else
6961        (eq (symbol_ref ("which_alternative"))
6962                        (const_int 0))
6963        (if_then_else
6964          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6965               (le (minus (match_dup 5) (pc)) (const_int 256)))
6966          (const_int 4)
6967          (if_then_else
6968            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6969                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6970            (const_int 6)
6971            (const_int 8)))
6972        (if_then_else
6973          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6974               (le (minus (match_dup 5) (pc)) (const_int 256)))
6975          (const_int 6)
6976          (if_then_else
6977            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6978                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6979            (const_int 8)
6980            (const_int 10)))))]
6981 )
6982
6983 (define_insn "*subsi3_cbranch_scratch"
6984   [(set (pc)
6985         (if_then_else
6986          (match_operator 0 "arm_comparison_operator"
6987           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6988                      (match_operand:SI 2 "nonmemory_operand" "l"))
6989            (const_int 0)])
6990          (label_ref (match_operand 3 "" ""))
6991          (pc)))]
6992   "TARGET_THUMB1
6993    && (GET_CODE (operands[0]) == EQ
6994        || GET_CODE (operands[0]) == NE
6995        || GET_CODE (operands[0]) == GE
6996        || GET_CODE (operands[0]) == LT)"
6997   "*
6998   output_asm_insn (\"cmp\\t%1, %2\", operands);
6999   switch (get_attr_length (insn))
7000     {
7001     case 4:  return \"b%d0\\t%l3\";
7002     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7003     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7004     }
7005   "
7006   [(set (attr "far_jump")
7007         (if_then_else
7008             (eq_attr "length" "8")
7009             (const_string "yes")
7010             (const_string "no")))
7011    (set (attr "length") 
7012         (if_then_else
7013             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7014                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7015             (const_int 4)
7016             (if_then_else
7017                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7018                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7019                 (const_int 6)
7020                 (const_int 8))))]
7021 )
7022
7023 ;; Comparison and test insns
7024
7025 (define_expand "cmpsi"
7026   [(match_operand:SI 0 "s_register_operand" "")
7027    (match_operand:SI 1 "arm_add_operand" "")]
7028   "TARGET_32BIT"
7029   "{
7030     arm_compare_op0 = operands[0];
7031     arm_compare_op1 = operands[1];
7032     DONE;
7033   }"
7034 )
7035
7036 (define_expand "cmpsf"
7037   [(match_operand:SF 0 "s_register_operand" "")
7038    (match_operand:SF 1 "arm_float_compare_operand" "")]
7039   "TARGET_32BIT && TARGET_HARD_FLOAT"
7040   "
7041   arm_compare_op0 = operands[0];
7042   arm_compare_op1 = operands[1];
7043   DONE;
7044   "
7045 )
7046
7047 (define_expand "cmpdf"
7048   [(match_operand:DF 0 "s_register_operand" "")
7049    (match_operand:DF 1 "arm_float_compare_operand" "")]
7050   "TARGET_32BIT && TARGET_HARD_FLOAT"
7051   "
7052   arm_compare_op0 = operands[0];
7053   arm_compare_op1 = operands[1];
7054   DONE;
7055   "
7056 )
7057
7058 (define_insn "*arm_cmpsi_insn"
7059   [(set (reg:CC CC_REGNUM)
7060         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
7061                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
7062   "TARGET_32BIT"
7063   "@
7064    cmp%?\\t%0, %1
7065    cmn%?\\t%0, #%n1"
7066   [(set_attr "conds" "set")]
7067 )
7068
7069 (define_insn "*arm_cmpsi_shiftsi"
7070   [(set (reg:CC CC_REGNUM)
7071         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
7072                     (match_operator:SI  3 "shift_operator"
7073                      [(match_operand:SI 1 "s_register_operand" "r")
7074                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
7075   "TARGET_ARM"
7076   "cmp%?\\t%0, %1%S3"
7077   [(set_attr "conds" "set")
7078    (set_attr "shift" "1")
7079    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7080                       (const_string "alu_shift")
7081                       (const_string "alu_shift_reg")))]
7082 )
7083
7084 (define_insn "*arm_cmpsi_shiftsi_swp"
7085   [(set (reg:CC_SWP CC_REGNUM)
7086         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7087                          [(match_operand:SI 1 "s_register_operand" "r")
7088                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
7089                         (match_operand:SI 0 "s_register_operand" "r")))]
7090   "TARGET_ARM"
7091   "cmp%?\\t%0, %1%S3"
7092   [(set_attr "conds" "set")
7093    (set_attr "shift" "1")
7094    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7095                       (const_string "alu_shift")
7096                       (const_string "alu_shift_reg")))]
7097 )
7098
7099 (define_insn "*arm_cmpsi_negshiftsi_si"
7100   [(set (reg:CC_Z CC_REGNUM)
7101         (compare:CC_Z
7102          (neg:SI (match_operator:SI 1 "shift_operator"
7103                     [(match_operand:SI 2 "s_register_operand" "r")
7104                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7105          (match_operand:SI 0 "s_register_operand" "r")))]
7106   "TARGET_ARM"
7107   "cmn%?\\t%0, %2%S1"
7108   [(set_attr "conds" "set")
7109    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7110                                     (const_string "alu_shift")
7111                                     (const_string "alu_shift_reg")))]
7112 )
7113
7114 ;; Cirrus SF compare instruction
7115 (define_insn "*cirrus_cmpsf"
7116   [(set (reg:CCFP CC_REGNUM)
7117         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7118                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
7119   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7120   "cfcmps%?\\tr15, %V0, %V1"
7121   [(set_attr "type"   "mav_farith")
7122    (set_attr "cirrus" "compare")]
7123 )
7124
7125 ;; Cirrus DF compare instruction
7126 (define_insn "*cirrus_cmpdf"
7127   [(set (reg:CCFP CC_REGNUM)
7128         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7129                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
7130   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7131   "cfcmpd%?\\tr15, %V0, %V1"
7132   [(set_attr "type"   "mav_farith")
7133    (set_attr "cirrus" "compare")]
7134 )
7135
7136 ;; Cirrus DI compare instruction
7137 (define_expand "cmpdi"
7138   [(match_operand:DI 0 "cirrus_fp_register" "")
7139    (match_operand:DI 1 "cirrus_fp_register" "")]
7140   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7141   "{
7142      arm_compare_op0 = operands[0];
7143      arm_compare_op1 = operands[1];
7144      DONE;
7145    }")
7146
7147 (define_insn "*cirrus_cmpdi"
7148   [(set (reg:CC CC_REGNUM)
7149         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7150                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
7151   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7152   "cfcmp64%?\\tr15, %V0, %V1"
7153   [(set_attr "type"   "mav_farith")
7154    (set_attr "cirrus" "compare")]
7155 )
7156
7157 ; This insn allows redundant compares to be removed by cse, nothing should
7158 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7159 ; is deleted later on. The match_dup will match the mode here, so that
7160 ; mode changes of the condition codes aren't lost by this even though we don't
7161 ; specify what they are.
7162
7163 (define_insn "*deleted_compare"
7164   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7165   "TARGET_32BIT"
7166   "\\t%@ deleted compare"
7167   [(set_attr "conds" "set")
7168    (set_attr "length" "0")]
7169 )
7170
7171 \f
7172 ;; Conditional branch insns
7173
7174 (define_expand "beq"
7175   [(set (pc)
7176         (if_then_else (eq (match_dup 1) (const_int 0))
7177                       (label_ref (match_operand 0 "" ""))
7178                       (pc)))]
7179   "TARGET_32BIT"
7180   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7181 )
7182
7183 (define_expand "bne"
7184   [(set (pc)
7185         (if_then_else (ne (match_dup 1) (const_int 0))
7186                       (label_ref (match_operand 0 "" ""))
7187                       (pc)))]
7188   "TARGET_32BIT"
7189   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7190 )
7191
7192 (define_expand "bgt"
7193   [(set (pc)
7194         (if_then_else (gt (match_dup 1) (const_int 0))
7195                       (label_ref (match_operand 0 "" ""))
7196                       (pc)))]
7197   "TARGET_32BIT"
7198   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7199 )
7200
7201 (define_expand "ble"
7202   [(set (pc)
7203         (if_then_else (le (match_dup 1) (const_int 0))
7204                       (label_ref (match_operand 0 "" ""))
7205                       (pc)))]
7206   "TARGET_32BIT"
7207   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7208 )
7209
7210 (define_expand "bge"
7211   [(set (pc)
7212         (if_then_else (ge (match_dup 1) (const_int 0))
7213                       (label_ref (match_operand 0 "" ""))
7214                       (pc)))]
7215   "TARGET_32BIT"
7216   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7217 )
7218
7219 (define_expand "blt"
7220   [(set (pc)
7221         (if_then_else (lt (match_dup 1) (const_int 0))
7222                       (label_ref (match_operand 0 "" ""))
7223                       (pc)))]
7224   "TARGET_32BIT"
7225   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7226 )
7227
7228 (define_expand "bgtu"
7229   [(set (pc)
7230         (if_then_else (gtu (match_dup 1) (const_int 0))
7231                       (label_ref (match_operand 0 "" ""))
7232                       (pc)))]
7233   "TARGET_32BIT"
7234   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7235 )
7236
7237 (define_expand "bleu"
7238   [(set (pc)
7239         (if_then_else (leu (match_dup 1) (const_int 0))
7240                       (label_ref (match_operand 0 "" ""))
7241                       (pc)))]
7242   "TARGET_32BIT"
7243   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7244 )
7245
7246 (define_expand "bgeu"
7247   [(set (pc)
7248         (if_then_else (geu (match_dup 1) (const_int 0))
7249                       (label_ref (match_operand 0 "" ""))
7250                       (pc)))]
7251   "TARGET_32BIT"
7252   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7253 )
7254
7255 (define_expand "bltu"
7256   [(set (pc)
7257         (if_then_else (ltu (match_dup 1) (const_int 0))
7258                       (label_ref (match_operand 0 "" ""))
7259                       (pc)))]
7260   "TARGET_32BIT"
7261   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7262 )
7263
7264 (define_expand "bunordered"
7265   [(set (pc)
7266         (if_then_else (unordered (match_dup 1) (const_int 0))
7267                       (label_ref (match_operand 0 "" ""))
7268                       (pc)))]
7269   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7270   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7271                                       arm_compare_op1);"
7272 )
7273
7274 (define_expand "bordered"
7275   [(set (pc)
7276         (if_then_else (ordered (match_dup 1) (const_int 0))
7277                       (label_ref (match_operand 0 "" ""))
7278                       (pc)))]
7279   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7280   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7281                                       arm_compare_op1);"
7282 )
7283
7284 (define_expand "bungt"
7285   [(set (pc)
7286         (if_then_else (ungt (match_dup 1) (const_int 0))
7287                       (label_ref (match_operand 0 "" ""))
7288                       (pc)))]
7289   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7290   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7291 )
7292
7293 (define_expand "bunlt"
7294   [(set (pc)
7295         (if_then_else (unlt (match_dup 1) (const_int 0))
7296                       (label_ref (match_operand 0 "" ""))
7297                       (pc)))]
7298   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7299   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7300 )
7301
7302 (define_expand "bunge"
7303   [(set (pc)
7304         (if_then_else (unge (match_dup 1) (const_int 0))
7305                       (label_ref (match_operand 0 "" ""))
7306                       (pc)))]
7307   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7308   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7309 )
7310
7311 (define_expand "bunle"
7312   [(set (pc)
7313         (if_then_else (unle (match_dup 1) (const_int 0))
7314                       (label_ref (match_operand 0 "" ""))
7315                       (pc)))]
7316   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7317   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7318 )
7319
7320 ;; The following two patterns need two branch instructions, since there is
7321 ;; no single instruction that will handle all cases.
7322 (define_expand "buneq"
7323   [(set (pc)
7324         (if_then_else (uneq (match_dup 1) (const_int 0))
7325                       (label_ref (match_operand 0 "" ""))
7326                       (pc)))]
7327   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7328   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7329 )
7330
7331 (define_expand "bltgt"
7332   [(set (pc)
7333         (if_then_else (ltgt (match_dup 1) (const_int 0))
7334                       (label_ref (match_operand 0 "" ""))
7335                       (pc)))]
7336   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7337   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7338 )
7339
7340 ;;
7341 ;; Patterns to match conditional branch insns.
7342 ;;
7343
7344 ; Special pattern to match UNEQ.
7345 (define_insn "*arm_buneq"
7346   [(set (pc)
7347         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7348                       (label_ref (match_operand 0 "" ""))
7349                       (pc)))]
7350   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7351   "*
7352   gcc_assert (!arm_ccfsm_state);
7353
7354   return \"bvs\\t%l0\;beq\\t%l0\";
7355   "
7356   [(set_attr "conds" "jump_clob")
7357    (set_attr "length" "8")]
7358 )
7359
7360 ; Special pattern to match LTGT.
7361 (define_insn "*arm_bltgt"
7362   [(set (pc)
7363         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7364                       (label_ref (match_operand 0 "" ""))
7365                       (pc)))]
7366   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7367   "*
7368   gcc_assert (!arm_ccfsm_state);
7369
7370   return \"bmi\\t%l0\;bgt\\t%l0\";
7371   "
7372   [(set_attr "conds" "jump_clob")
7373    (set_attr "length" "8")]
7374 )
7375
7376 (define_insn "*arm_cond_branch"
7377   [(set (pc)
7378         (if_then_else (match_operator 1 "arm_comparison_operator"
7379                        [(match_operand 2 "cc_register" "") (const_int 0)])
7380                       (label_ref (match_operand 0 "" ""))
7381                       (pc)))]
7382   "TARGET_32BIT"
7383   "*
7384   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7385     {
7386       arm_ccfsm_state += 2;
7387       return \"\";
7388     }
7389   return \"b%d1\\t%l0\";
7390   "
7391   [(set_attr "conds" "use")
7392    (set_attr "type" "branch")]
7393 )
7394
7395 ; Special pattern to match reversed UNEQ.
7396 (define_insn "*arm_buneq_reversed"
7397   [(set (pc)
7398         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7399                       (pc)
7400                       (label_ref (match_operand 0 "" ""))))]
7401   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7402   "*
7403   gcc_assert (!arm_ccfsm_state);
7404
7405   return \"bmi\\t%l0\;bgt\\t%l0\";
7406   "
7407   [(set_attr "conds" "jump_clob")
7408    (set_attr "length" "8")]
7409 )
7410
7411 ; Special pattern to match reversed LTGT.
7412 (define_insn "*arm_bltgt_reversed"
7413   [(set (pc)
7414         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7415                       (pc)
7416                       (label_ref (match_operand 0 "" ""))))]
7417   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7418   "*
7419   gcc_assert (!arm_ccfsm_state);
7420
7421   return \"bvs\\t%l0\;beq\\t%l0\";
7422   "
7423   [(set_attr "conds" "jump_clob")
7424    (set_attr "length" "8")]
7425 )
7426
7427 (define_insn "*arm_cond_branch_reversed"
7428   [(set (pc)
7429         (if_then_else (match_operator 1 "arm_comparison_operator"
7430                        [(match_operand 2 "cc_register" "") (const_int 0)])
7431                       (pc)
7432                       (label_ref (match_operand 0 "" ""))))]
7433   "TARGET_32BIT"
7434   "*
7435   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7436     {
7437       arm_ccfsm_state += 2;
7438       return \"\";
7439     }
7440   return \"b%D1\\t%l0\";
7441   "
7442   [(set_attr "conds" "use")
7443    (set_attr "type" "branch")]
7444 )
7445
7446 \f
7447
7448 ; scc insns
7449
7450 (define_expand "seq"
7451   [(set (match_operand:SI 0 "s_register_operand" "")
7452         (eq:SI (match_dup 1) (const_int 0)))]
7453   "TARGET_32BIT"
7454   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7455 )
7456
7457 (define_expand "sne"
7458   [(set (match_operand:SI 0 "s_register_operand" "")
7459         (ne:SI (match_dup 1) (const_int 0)))]
7460   "TARGET_32BIT"
7461   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7462 )
7463
7464 (define_expand "sgt"
7465   [(set (match_operand:SI 0 "s_register_operand" "")
7466         (gt:SI (match_dup 1) (const_int 0)))]
7467   "TARGET_32BIT"
7468   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7469 )
7470
7471 (define_expand "sle"
7472   [(set (match_operand:SI 0 "s_register_operand" "")
7473         (le:SI (match_dup 1) (const_int 0)))]
7474   "TARGET_32BIT"
7475   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7476 )
7477
7478 (define_expand "sge"
7479   [(set (match_operand:SI 0 "s_register_operand" "")
7480         (ge:SI (match_dup 1) (const_int 0)))]
7481   "TARGET_32BIT"
7482   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7483 )
7484
7485 (define_expand "slt"
7486   [(set (match_operand:SI 0 "s_register_operand" "")
7487         (lt:SI (match_dup 1) (const_int 0)))]
7488   "TARGET_32BIT"
7489   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7490 )
7491
7492 (define_expand "sgtu"
7493   [(set (match_operand:SI 0 "s_register_operand" "")
7494         (gtu:SI (match_dup 1) (const_int 0)))]
7495   "TARGET_32BIT"
7496   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7497 )
7498
7499 (define_expand "sleu"
7500   [(set (match_operand:SI 0 "s_register_operand" "")
7501         (leu:SI (match_dup 1) (const_int 0)))]
7502   "TARGET_32BIT"
7503   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7504 )
7505
7506 (define_expand "sgeu"
7507   [(set (match_operand:SI 0 "s_register_operand" "")
7508         (geu:SI (match_dup 1) (const_int 0)))]
7509   "TARGET_32BIT"
7510   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7511 )
7512
7513 (define_expand "sltu"
7514   [(set (match_operand:SI 0 "s_register_operand" "")
7515         (ltu:SI (match_dup 1) (const_int 0)))]
7516   "TARGET_32BIT"
7517   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7518 )
7519
7520 (define_expand "sunordered"
7521   [(set (match_operand:SI 0 "s_register_operand" "")
7522         (unordered:SI (match_dup 1) (const_int 0)))]
7523   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7524   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7525                                       arm_compare_op1);"
7526 )
7527
7528 (define_expand "sordered"
7529   [(set (match_operand:SI 0 "s_register_operand" "")
7530         (ordered:SI (match_dup 1) (const_int 0)))]
7531   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7532   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7533                                       arm_compare_op1);"
7534 )
7535
7536 (define_expand "sungt"
7537   [(set (match_operand:SI 0 "s_register_operand" "")
7538         (ungt:SI (match_dup 1) (const_int 0)))]
7539   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7540   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7541                                       arm_compare_op1);"
7542 )
7543
7544 (define_expand "sunge"
7545   [(set (match_operand:SI 0 "s_register_operand" "")
7546         (unge:SI (match_dup 1) (const_int 0)))]
7547   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7548   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7549                                       arm_compare_op1);"
7550 )
7551
7552 (define_expand "sunlt"
7553   [(set (match_operand:SI 0 "s_register_operand" "")
7554         (unlt:SI (match_dup 1) (const_int 0)))]
7555   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7556   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7557                                       arm_compare_op1);"
7558 )
7559
7560 (define_expand "sunle"
7561   [(set (match_operand:SI 0 "s_register_operand" "")
7562         (unle:SI (match_dup 1) (const_int 0)))]
7563   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7564   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7565                                       arm_compare_op1);"
7566 )
7567
7568 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7569 ;;; simple ARM instructions. 
7570 ;
7571 ; (define_expand "suneq"
7572 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7573 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7574 ;   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7575 ;   "gcc_unreachable ();"
7576 ; )
7577 ;
7578 ; (define_expand "sltgt"
7579 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7580 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7581 ;   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7582 ;   "gcc_unreachable ();"
7583 ; )
7584
7585 (define_insn "*mov_scc"
7586   [(set (match_operand:SI 0 "s_register_operand" "=r")
7587         (match_operator:SI 1 "arm_comparison_operator"
7588          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7589   "TARGET_ARM"
7590   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7591   [(set_attr "conds" "use")
7592    (set_attr "length" "8")]
7593 )
7594
7595 (define_insn "*mov_negscc"
7596   [(set (match_operand:SI 0 "s_register_operand" "=r")
7597         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7598                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7599   "TARGET_ARM"
7600   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7601   [(set_attr "conds" "use")
7602    (set_attr "length" "8")]
7603 )
7604
7605 (define_insn "*mov_notscc"
7606   [(set (match_operand:SI 0 "s_register_operand" "=r")
7607         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7608                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7609   "TARGET_ARM"
7610   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7611   [(set_attr "conds" "use")
7612    (set_attr "length" "8")]
7613 )
7614
7615 (define_expand "cstoresi4"
7616   [(set (match_operand:SI 0 "s_register_operand" "")
7617         (match_operator:SI 1 "arm_comparison_operator"
7618          [(match_operand:SI 2 "s_register_operand" "")
7619           (match_operand:SI 3 "reg_or_int_operand" "")]))]
7620   "TARGET_THUMB1"
7621   "{
7622   rtx op3, scratch, scratch2;
7623
7624   if (operands[3] == const0_rtx)
7625     {
7626       switch (GET_CODE (operands[1]))
7627         {
7628         case EQ:
7629           emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7630           break;
7631
7632         case NE:
7633           emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7634           break;
7635
7636         case LE:
7637           scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7638                                   NULL_RTX, 0, OPTAB_WIDEN);
7639           scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7640                                   NULL_RTX, 0, OPTAB_WIDEN);
7641           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7642                         operands[0], 1, OPTAB_WIDEN);
7643           break;
7644
7645         case GE:
7646           scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7647                                  NULL_RTX, 1);
7648           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7649                         NULL_RTX, 1, OPTAB_WIDEN);
7650           break;
7651
7652         case GT:
7653           scratch = expand_binop (SImode, ashr_optab, operands[2],
7654                                   GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7655           scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7656                                   NULL_RTX, 0, OPTAB_WIDEN);
7657           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7658                         0, OPTAB_WIDEN);
7659           break;
7660
7661         /* LT is handled by generic code.  No need for unsigned with 0.  */
7662         default:
7663           FAIL;
7664         }
7665       DONE;
7666     }
7667
7668   switch (GET_CODE (operands[1]))
7669     {
7670     case EQ:
7671       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7672                               NULL_RTX, 0, OPTAB_WIDEN);
7673       emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7674       break;
7675
7676     case NE:
7677       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7678                               NULL_RTX, 0, OPTAB_WIDEN);
7679       emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7680       break;
7681
7682     case LE:
7683       op3 = force_reg (SImode, operands[3]);
7684
7685       scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7686                               NULL_RTX, 1, OPTAB_WIDEN);
7687       scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7688                               NULL_RTX, 0, OPTAB_WIDEN);
7689       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7690                                           op3, operands[2]));
7691       break;
7692
7693     case GE:
7694       op3 = operands[3];
7695       if (!thumb1_cmp_operand (op3, SImode))
7696         op3 = force_reg (SImode, op3);
7697       scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7698                               NULL_RTX, 0, OPTAB_WIDEN);
7699       scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7700                                NULL_RTX, 1, OPTAB_WIDEN);
7701       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7702                                           operands[2], op3));
7703       break;
7704
7705     case LEU:
7706       op3 = force_reg (SImode, operands[3]);
7707       scratch = force_reg (SImode, const0_rtx);
7708       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7709                                           op3, operands[2]));
7710       break;
7711
7712     case GEU:
7713       op3 = operands[3];
7714       if (!thumb1_cmp_operand (op3, SImode))
7715         op3 = force_reg (SImode, op3);
7716       scratch = force_reg (SImode, const0_rtx);
7717       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7718                                           operands[2], op3));
7719       break;
7720
7721     case LTU:
7722       op3 = operands[3];
7723       if (!thumb1_cmp_operand (op3, SImode))
7724         op3 = force_reg (SImode, op3);
7725       scratch = gen_reg_rtx (SImode);
7726       emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
7727       emit_insn (gen_negsi2 (operands[0], scratch));
7728       break;
7729
7730     case GTU:
7731       op3 = force_reg (SImode, operands[3]);
7732       scratch = gen_reg_rtx (SImode);
7733       emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
7734       emit_insn (gen_negsi2 (operands[0], scratch));
7735       break;
7736
7737     /* No good sequences for GT, LT.  */
7738     default:
7739       FAIL;
7740     }
7741   DONE;
7742 }")
7743
7744 (define_expand "cstoresi_eq0_thumb1"
7745   [(parallel
7746     [(set (match_operand:SI 0 "s_register_operand" "")
7747           (eq:SI (match_operand:SI 1 "s_register_operand" "")
7748                  (const_int 0)))
7749      (clobber (match_dup:SI 2))])]
7750   "TARGET_THUMB1"
7751   "operands[2] = gen_reg_rtx (SImode);"
7752 )
7753
7754 (define_expand "cstoresi_ne0_thumb1"
7755   [(parallel
7756     [(set (match_operand:SI 0 "s_register_operand" "")
7757           (ne:SI (match_operand:SI 1 "s_register_operand" "")
7758                  (const_int 0)))
7759      (clobber (match_dup:SI 2))])]
7760   "TARGET_THUMB1"
7761   "operands[2] = gen_reg_rtx (SImode);"
7762 )
7763
7764 (define_insn "*cstoresi_eq0_thumb1_insn"
7765   [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7766         (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7767                (const_int 0)))
7768    (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
7769   "TARGET_THUMB1"
7770   "@
7771    neg\\t%0, %1\;adc\\t%0, %0, %1
7772    neg\\t%2, %1\;adc\\t%0, %1, %2"
7773   [(set_attr "length" "4")]
7774 )
7775
7776 (define_insn "*cstoresi_ne0_thumb1_insn"
7777   [(set (match_operand:SI 0 "s_register_operand" "=l")
7778         (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7779                (const_int 0)))
7780    (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
7781   "TARGET_THUMB1"
7782   "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7783   [(set_attr "length" "4")]
7784 )
7785
7786 (define_insn "cstoresi_nltu_thumb1"
7787   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7788         (neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7789                         (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7790   "TARGET_THUMB1"
7791   "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7792   [(set_attr "length" "4")]
7793 )
7794
7795 ;; Used as part of the expansion of thumb les sequence.
7796 (define_insn "thumb1_addsi3_addgeu"
7797   [(set (match_operand:SI 0 "s_register_operand" "=l")
7798         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7799                           (match_operand:SI 2 "s_register_operand" "l"))
7800                  (geu:SI (match_operand:SI 3 "s_register_operand" "l")
7801                          (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7802   "TARGET_THUMB1"
7803   "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7804   [(set_attr "length" "4")]
7805 )
7806
7807 \f
7808 ;; Conditional move insns
7809
7810 (define_expand "movsicc"
7811   [(set (match_operand:SI 0 "s_register_operand" "")
7812         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7813                          (match_operand:SI 2 "arm_not_operand" "")
7814                          (match_operand:SI 3 "arm_not_operand" "")))]
7815   "TARGET_32BIT"
7816   "
7817   {
7818     enum rtx_code code = GET_CODE (operands[1]);
7819     rtx ccreg;
7820
7821     if (code == UNEQ || code == LTGT)
7822       FAIL;
7823
7824     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7825     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7826   }"
7827 )
7828
7829 (define_expand "movsfcc"
7830   [(set (match_operand:SF 0 "s_register_operand" "")
7831         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7832                          (match_operand:SF 2 "s_register_operand" "")
7833                          (match_operand:SF 3 "nonmemory_operand" "")))]
7834   "TARGET_32BIT"
7835   "
7836   {
7837     enum rtx_code code = GET_CODE (operands[1]);
7838     rtx ccreg;
7839
7840     if (code == UNEQ || code == LTGT)
7841       FAIL;
7842
7843     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7844        Otherwise, ensure it is a valid FP add operand */
7845     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7846         || (!arm_float_add_operand (operands[3], SFmode)))
7847       operands[3] = force_reg (SFmode, operands[3]);
7848
7849     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7850     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7851   }"
7852 )
7853
7854 (define_expand "movdfcc"
7855   [(set (match_operand:DF 0 "s_register_operand" "")
7856         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7857                          (match_operand:DF 2 "s_register_operand" "")
7858                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7859   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7860   "
7861   {
7862     enum rtx_code code = GET_CODE (operands[1]);
7863     rtx ccreg;
7864
7865     if (code == UNEQ || code == LTGT)
7866       FAIL;
7867
7868     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7869     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7870   }"
7871 )
7872
7873 (define_insn "*movsicc_insn"
7874   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7875         (if_then_else:SI
7876          (match_operator 3 "arm_comparison_operator"
7877           [(match_operand 4 "cc_register" "") (const_int 0)])
7878          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7879          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7880   "TARGET_ARM"
7881   "@
7882    mov%D3\\t%0, %2
7883    mvn%D3\\t%0, #%B2
7884    mov%d3\\t%0, %1
7885    mvn%d3\\t%0, #%B1
7886    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7887    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7888    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7889    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7890   [(set_attr "length" "4,4,4,4,8,8,8,8")
7891    (set_attr "conds" "use")]
7892 )
7893
7894 (define_insn "*movsfcc_soft_insn"
7895   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7896         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7897                           [(match_operand 4 "cc_register" "") (const_int 0)])
7898                          (match_operand:SF 1 "s_register_operand" "0,r")
7899                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7900   "TARGET_ARM && TARGET_SOFT_FLOAT"
7901   "@
7902    mov%D3\\t%0, %2
7903    mov%d3\\t%0, %1"
7904   [(set_attr "conds" "use")]
7905 )
7906
7907 \f
7908 ;; Jump and linkage insns
7909
7910 (define_expand "jump"
7911   [(set (pc)
7912         (label_ref (match_operand 0 "" "")))]
7913   "TARGET_EITHER"
7914   ""
7915 )
7916
7917 (define_insn "*arm_jump"
7918   [(set (pc)
7919         (label_ref (match_operand 0 "" "")))]
7920   "TARGET_32BIT"
7921   "*
7922   {
7923     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7924       {
7925         arm_ccfsm_state += 2;
7926         return \"\";
7927       }
7928     return \"b%?\\t%l0\";
7929   }
7930   "
7931   [(set_attr "predicable" "yes")]
7932 )
7933
7934 (define_insn "*thumb_jump"
7935   [(set (pc)
7936         (label_ref (match_operand 0 "" "")))]
7937   "TARGET_THUMB1"
7938   "*
7939   if (get_attr_length (insn) == 2)
7940     return \"b\\t%l0\";
7941   return \"bl\\t%l0\\t%@ far jump\";
7942   "
7943   [(set (attr "far_jump")
7944         (if_then_else
7945             (eq_attr "length" "4")
7946             (const_string "yes")
7947             (const_string "no")))
7948    (set (attr "length") 
7949         (if_then_else
7950             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7951                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7952             (const_int 2)
7953             (const_int 4)))]
7954 )
7955
7956 (define_expand "call"
7957   [(parallel [(call (match_operand 0 "memory_operand" "")
7958                     (match_operand 1 "general_operand" ""))
7959               (use (match_operand 2 "" ""))
7960               (clobber (reg:SI LR_REGNUM))])]
7961   "TARGET_EITHER"
7962   "
7963   {
7964     rtx callee;
7965     
7966     /* In an untyped call, we can get NULL for operand 2.  */
7967     if (operands[2] == NULL_RTX)
7968       operands[2] = const0_rtx;
7969       
7970     /* This is to decide if we should generate indirect calls by loading the
7971        32 bit address of the callee into a register before performing the
7972        branch and link.  operand[2] encodes the long_call/short_call
7973        attribute of the function being called.  This attribute is set whenever
7974        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7975        is used, and the short_call attribute can also be set if function is
7976        declared as static or if it has already been defined in the current
7977        compilation unit.  See arm.c and arm.h for info about this.  The third
7978        parameter to arm_is_longcall_p is used to tell it which pattern
7979        invoked it.  */
7980     callee  = XEXP (operands[0], 0);
7981     
7982     if ((GET_CODE (callee) == SYMBOL_REF
7983          && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7984         || (GET_CODE (callee) != SYMBOL_REF
7985             && GET_CODE (callee) != REG))
7986       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7987   }"
7988 )
7989
7990 (define_insn "*call_reg_armv5"
7991   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7992          (match_operand 1 "" ""))
7993    (use (match_operand 2 "" ""))
7994    (clobber (reg:SI LR_REGNUM))]
7995   "TARGET_ARM && arm_arch5"
7996   "blx%?\\t%0"
7997   [(set_attr "type" "call")]
7998 )
7999
8000 (define_insn "*call_reg_arm"
8001   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8002          (match_operand 1 "" ""))
8003    (use (match_operand 2 "" ""))
8004    (clobber (reg:SI LR_REGNUM))]
8005   "TARGET_ARM && !arm_arch5"
8006   "*
8007   return output_call (operands);
8008   "
8009   ;; length is worst case, normally it is only two
8010   [(set_attr "length" "12")
8011    (set_attr "type" "call")]
8012 )
8013
8014 (define_insn "*call_mem"
8015   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
8016          (match_operand 1 "" ""))
8017    (use (match_operand 2 "" ""))
8018    (clobber (reg:SI LR_REGNUM))]
8019   "TARGET_ARM"
8020   "*
8021   return output_call_mem (operands);
8022   "
8023   [(set_attr "length" "12")
8024    (set_attr "type" "call")]
8025 )
8026
8027 (define_insn "*call_reg_thumb1_v5"
8028   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8029          (match_operand 1 "" ""))
8030    (use (match_operand 2 "" ""))
8031    (clobber (reg:SI LR_REGNUM))]
8032   "TARGET_THUMB1 && arm_arch5"
8033   "blx\\t%0"
8034   [(set_attr "length" "2")
8035    (set_attr "type" "call")]
8036 )
8037
8038 (define_insn "*call_reg_thumb1"
8039   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8040          (match_operand 1 "" ""))
8041    (use (match_operand 2 "" ""))
8042    (clobber (reg:SI LR_REGNUM))]
8043   "TARGET_THUMB1 && !arm_arch5"
8044   "*
8045   {
8046     if (!TARGET_CALLER_INTERWORKING)
8047       return thumb_call_via_reg (operands[0]);
8048     else if (operands[1] == const0_rtx)
8049       return \"bl\\t%__interwork_call_via_%0\";
8050     else if (frame_pointer_needed)
8051       return \"bl\\t%__interwork_r7_call_via_%0\";
8052     else
8053       return \"bl\\t%__interwork_r11_call_via_%0\";
8054   }"
8055   [(set_attr "type" "call")]
8056 )
8057
8058 (define_expand "call_value"
8059   [(parallel [(set (match_operand       0 "" "")
8060                    (call (match_operand 1 "memory_operand" "")
8061                          (match_operand 2 "general_operand" "")))
8062               (use (match_operand 3 "" ""))
8063               (clobber (reg:SI LR_REGNUM))])]
8064   "TARGET_EITHER"
8065   "
8066   {
8067     rtx callee = XEXP (operands[1], 0);
8068     
8069     /* In an untyped call, we can get NULL for operand 2.  */
8070     if (operands[3] == 0)
8071       operands[3] = const0_rtx;
8072       
8073     /* See the comment in define_expand \"call\".  */
8074     if ((GET_CODE (callee) == SYMBOL_REF
8075          && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
8076         || (GET_CODE (callee) != SYMBOL_REF
8077             && GET_CODE (callee) != REG))
8078       XEXP (operands[1], 0) = force_reg (Pmode, callee);
8079   }"
8080 )
8081
8082 (define_insn "*call_value_reg_armv5"
8083   [(set (match_operand 0 "" "")
8084         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8085               (match_operand 2 "" "")))
8086    (use (match_operand 3 "" ""))
8087    (clobber (reg:SI LR_REGNUM))]
8088   "TARGET_ARM && arm_arch5"
8089   "blx%?\\t%1"
8090   [(set_attr "type" "call")]
8091 )
8092
8093 (define_insn "*call_value_reg_arm"
8094   [(set (match_operand 0 "" "")
8095         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8096               (match_operand 2 "" "")))
8097    (use (match_operand 3 "" ""))
8098    (clobber (reg:SI LR_REGNUM))]
8099   "TARGET_ARM && !arm_arch5"
8100   "*
8101   return output_call (&operands[1]);
8102   "
8103   [(set_attr "length" "12")
8104    (set_attr "type" "call")]
8105 )
8106
8107 (define_insn "*call_value_mem"
8108   [(set (match_operand 0 "" "")
8109         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8110               (match_operand 2 "" "")))
8111    (use (match_operand 3 "" ""))
8112    (clobber (reg:SI LR_REGNUM))]
8113   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8114   "*
8115   return output_call_mem (&operands[1]);
8116   "
8117   [(set_attr "length" "12")
8118    (set_attr "type" "call")]
8119 )
8120
8121 (define_insn "*call_value_reg_thumb1_v5"
8122   [(set (match_operand 0 "" "")
8123         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8124               (match_operand 2 "" "")))
8125    (use (match_operand 3 "" ""))
8126    (clobber (reg:SI LR_REGNUM))]
8127   "TARGET_THUMB1 && arm_arch5"
8128   "blx\\t%1"
8129   [(set_attr "length" "2")
8130    (set_attr "type" "call")]
8131 )
8132
8133 (define_insn "*call_value_reg_thumb1"
8134   [(set (match_operand 0 "" "")
8135         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8136               (match_operand 2 "" "")))
8137    (use (match_operand 3 "" ""))
8138    (clobber (reg:SI LR_REGNUM))]
8139   "TARGET_THUMB1 && !arm_arch5"
8140   "*
8141   {
8142     if (!TARGET_CALLER_INTERWORKING)
8143       return thumb_call_via_reg (operands[1]);
8144     else if (operands[2] == const0_rtx)
8145       return \"bl\\t%__interwork_call_via_%1\";
8146     else if (frame_pointer_needed)
8147       return \"bl\\t%__interwork_r7_call_via_%1\";
8148     else
8149       return \"bl\\t%__interwork_r11_call_via_%1\";
8150   }"
8151   [(set_attr "type" "call")]
8152 )
8153
8154 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8155 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8156
8157 (define_insn "*call_symbol"
8158   [(call (mem:SI (match_operand:SI 0 "" ""))
8159          (match_operand 1 "" ""))
8160    (use (match_operand 2 "" ""))
8161    (clobber (reg:SI LR_REGNUM))]
8162   "TARGET_ARM
8163    && (GET_CODE (operands[0]) == SYMBOL_REF)
8164    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
8165   "*
8166   {
8167     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8168   }"
8169   [(set_attr "type" "call")]
8170 )
8171
8172 (define_insn "*call_value_symbol"
8173   [(set (match_operand 0 "" "")
8174         (call (mem:SI (match_operand:SI 1 "" ""))
8175         (match_operand:SI 2 "" "")))
8176    (use (match_operand 3 "" ""))
8177    (clobber (reg:SI LR_REGNUM))]
8178   "TARGET_ARM
8179    && (GET_CODE (operands[1]) == SYMBOL_REF)
8180    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
8181   "*
8182   {
8183     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8184   }"
8185   [(set_attr "type" "call")]
8186 )
8187
8188 (define_insn "*call_insn"
8189   [(call (mem:SI (match_operand:SI 0 "" ""))
8190          (match_operand:SI 1 "" ""))
8191    (use (match_operand 2 "" ""))
8192    (clobber (reg:SI LR_REGNUM))]
8193   "TARGET_THUMB
8194    && GET_CODE (operands[0]) == SYMBOL_REF
8195    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
8196   "bl\\t%a0"
8197   [(set_attr "length" "4")
8198    (set_attr "type" "call")]
8199 )
8200
8201 (define_insn "*call_value_insn"
8202   [(set (match_operand 0 "" "")
8203         (call (mem:SI (match_operand 1 "" ""))
8204               (match_operand 2 "" "")))
8205    (use (match_operand 3 "" ""))
8206    (clobber (reg:SI LR_REGNUM))]
8207   "TARGET_THUMB
8208    && GET_CODE (operands[1]) == SYMBOL_REF
8209    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
8210   "bl\\t%a1"
8211   [(set_attr "length" "4")
8212    (set_attr "type" "call")]
8213 )
8214
8215 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8216 (define_expand "sibcall"
8217   [(parallel [(call (match_operand 0 "memory_operand" "")
8218                     (match_operand 1 "general_operand" ""))
8219               (return)
8220               (use (match_operand 2 "" ""))])]
8221   "TARGET_ARM"
8222   "
8223   {
8224     if (operands[2] == NULL_RTX)
8225       operands[2] = const0_rtx;
8226   }"
8227 )
8228
8229 (define_expand "sibcall_value"
8230   [(parallel [(set (match_operand 0 "" "")
8231                    (call (match_operand 1 "memory_operand" "")
8232                          (match_operand 2 "general_operand" "")))
8233               (return)
8234               (use (match_operand 3 "" ""))])]
8235   "TARGET_ARM"
8236   "
8237   {
8238     if (operands[3] == NULL_RTX)
8239       operands[3] = const0_rtx;
8240   }"
8241 )
8242
8243 (define_insn "*sibcall_insn"
8244  [(call (mem:SI (match_operand:SI 0 "" "X"))
8245         (match_operand 1 "" ""))
8246   (return)
8247   (use (match_operand 2 "" ""))]
8248   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8249   "*
8250   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8251   "
8252   [(set_attr "type" "call")]
8253 )
8254
8255 (define_insn "*sibcall_value_insn"
8256  [(set (match_operand 0 "" "")
8257        (call (mem:SI (match_operand:SI 1 "" "X"))
8258              (match_operand 2 "" "")))
8259   (return)
8260   (use (match_operand 3 "" ""))]
8261   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8262   "*
8263   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8264   "
8265   [(set_attr "type" "call")]
8266 )
8267
8268 ;; Often the return insn will be the same as loading from memory, so set attr
8269 (define_insn "return"
8270   [(return)]
8271   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8272   "*
8273   {
8274     if (arm_ccfsm_state == 2)
8275       {
8276         arm_ccfsm_state += 2;
8277         return \"\";
8278       }
8279     return output_return_instruction (const_true_rtx, TRUE, FALSE);
8280   }"
8281   [(set_attr "type" "load1")
8282    (set_attr "length" "12")
8283    (set_attr "predicable" "yes")]
8284 )
8285
8286 (define_insn "*cond_return"
8287   [(set (pc)
8288         (if_then_else (match_operator 0 "arm_comparison_operator"
8289                        [(match_operand 1 "cc_register" "") (const_int 0)])
8290                       (return)
8291                       (pc)))]
8292   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8293   "*
8294   {
8295     if (arm_ccfsm_state == 2)
8296       {
8297         arm_ccfsm_state += 2;
8298         return \"\";
8299       }
8300     return output_return_instruction (operands[0], TRUE, FALSE);
8301   }"
8302   [(set_attr "conds" "use")
8303    (set_attr "length" "12")
8304    (set_attr "type" "load1")]
8305 )
8306
8307 (define_insn "*cond_return_inverted"
8308   [(set (pc)
8309         (if_then_else (match_operator 0 "arm_comparison_operator"
8310                        [(match_operand 1 "cc_register" "") (const_int 0)])
8311                       (pc)
8312                       (return)))]
8313   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8314   "*
8315   {
8316     if (arm_ccfsm_state == 2)
8317       {
8318         arm_ccfsm_state += 2;
8319         return \"\";
8320       }
8321     return output_return_instruction (operands[0], TRUE, TRUE);
8322   }"
8323   [(set_attr "conds" "use")
8324    (set_attr "length" "12")
8325    (set_attr "type" "load1")]
8326 )
8327
8328 ;; Generate a sequence of instructions to determine if the processor is
8329 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8330 ;; mask.
8331
8332 (define_expand "return_addr_mask"
8333   [(set (match_dup 1)
8334       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8335                        (const_int 0)))
8336    (set (match_operand:SI 0 "s_register_operand" "")
8337       (if_then_else:SI (eq (match_dup 1) (const_int 0))
8338                        (const_int -1)
8339                        (const_int 67108860)))] ; 0x03fffffc
8340   "TARGET_ARM"
8341   "
8342   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8343   ")
8344
8345 (define_insn "*check_arch2"
8346   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8347       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8348                        (const_int 0)))]
8349   "TARGET_ARM"
8350   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8351   [(set_attr "length" "8")
8352    (set_attr "conds" "set")]
8353 )
8354
8355 ;; Call subroutine returning any type.
8356
8357 (define_expand "untyped_call"
8358   [(parallel [(call (match_operand 0 "" "")
8359                     (const_int 0))
8360               (match_operand 1 "" "")
8361               (match_operand 2 "" "")])]
8362   "TARGET_EITHER"
8363   "
8364   {
8365     int i;
8366     rtx par = gen_rtx_PARALLEL (VOIDmode,
8367                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8368     rtx addr = gen_reg_rtx (Pmode);
8369     rtx mem;
8370     int size = 0;
8371
8372     emit_move_insn (addr, XEXP (operands[1], 0));
8373     mem = change_address (operands[1], BLKmode, addr);
8374
8375     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8376       {
8377         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8378
8379         /* Default code only uses r0 as a return value, but we could
8380            be using anything up to 4 registers.  */
8381         if (REGNO (src) == R0_REGNUM)
8382           src = gen_rtx_REG (TImode, R0_REGNUM);
8383
8384         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8385                                                  GEN_INT (size));
8386         size += GET_MODE_SIZE (GET_MODE (src));
8387       }
8388
8389     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8390                                     const0_rtx));
8391
8392     size = 0;
8393
8394     for (i = 0; i < XVECLEN (par, 0); i++)
8395       {
8396         HOST_WIDE_INT offset = 0;
8397         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8398
8399         if (size != 0)
8400           emit_move_insn (addr, plus_constant (addr, size));
8401
8402         mem = change_address (mem, GET_MODE (reg), NULL);
8403         if (REGNO (reg) == R0_REGNUM)
8404           {
8405             /* On thumb we have to use a write-back instruction.  */
8406             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8407                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8408             size = TARGET_ARM ? 16 : 0;
8409           }
8410         else
8411           {
8412             emit_move_insn (mem, reg);
8413             size = GET_MODE_SIZE (GET_MODE (reg));
8414           }
8415       }
8416
8417     /* The optimizer does not know that the call sets the function value
8418        registers we stored in the result block.  We avoid problems by
8419        claiming that all hard registers are used and clobbered at this
8420        point.  */
8421     emit_insn (gen_blockage ());
8422
8423     DONE;
8424   }"
8425 )
8426
8427 (define_expand "untyped_return"
8428   [(match_operand:BLK 0 "memory_operand" "")
8429    (match_operand 1 "" "")]
8430   "TARGET_EITHER"
8431   "
8432   {
8433     int i;
8434     rtx addr = gen_reg_rtx (Pmode);
8435     rtx mem;
8436     int size = 0;
8437
8438     emit_move_insn (addr, XEXP (operands[0], 0));
8439     mem = change_address (operands[0], BLKmode, addr);
8440
8441     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8442       {
8443         HOST_WIDE_INT offset = 0;
8444         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8445
8446         if (size != 0)
8447           emit_move_insn (addr, plus_constant (addr, size));
8448
8449         mem = change_address (mem, GET_MODE (reg), NULL);
8450         if (REGNO (reg) == R0_REGNUM)
8451           {
8452             /* On thumb we have to use a write-back instruction.  */
8453             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8454                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8455             size = TARGET_ARM ? 16 : 0;
8456           }
8457         else
8458           {
8459             emit_move_insn (reg, mem);
8460             size = GET_MODE_SIZE (GET_MODE (reg));
8461           }
8462       }
8463
8464     /* Emit USE insns before the return.  */
8465     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8466       emit_insn (gen_rtx_USE (VOIDmode,
8467                               SET_DEST (XVECEXP (operands[1], 0, i))));
8468
8469     /* Construct the return.  */
8470     expand_naked_return ();
8471
8472     DONE;
8473   }"
8474 )
8475
8476 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8477 ;; all of memory.  This blocks insns from being moved across this point.
8478
8479 (define_insn "blockage"
8480   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8481   "TARGET_EITHER"
8482   ""
8483   [(set_attr "length" "0")
8484    (set_attr "type" "block")]
8485 )
8486
8487 (define_expand "casesi"
8488   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8489    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8490    (match_operand:SI 2 "const_int_operand" "")  ; total range
8491    (match_operand:SI 3 "" "")                   ; table label
8492    (match_operand:SI 4 "" "")]                  ; Out of range label
8493   "TARGET_32BIT"
8494   "
8495   {
8496     rtx reg;
8497     if (operands[1] != const0_rtx)
8498       {
8499         reg = gen_reg_rtx (SImode);
8500
8501         emit_insn (gen_addsi3 (reg, operands[0],
8502                                GEN_INT (-INTVAL (operands[1]))));
8503         operands[0] = reg;
8504       }
8505
8506     if (!const_ok_for_arm (INTVAL (operands[2])))
8507       operands[2] = force_reg (SImode, operands[2]);
8508
8509     if (TARGET_ARM)
8510       {
8511         emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
8512                                                  operands[3], operands[4]));
8513       }
8514     else if (flag_pic)
8515       {
8516         emit_jump_insn (gen_thumb2_casesi_internal_pic (operands[0],
8517             operands[2], operands[3], operands[4]));
8518       }
8519     else
8520       {
8521         emit_jump_insn (gen_thumb2_casesi_internal (operands[0], operands[2],
8522                                                     operands[3], operands[4]));
8523       }
8524     DONE;
8525   }"
8526 )
8527
8528 ;; The USE in this pattern is needed to tell flow analysis that this is
8529 ;; a CASESI insn.  It has no other purpose.
8530 (define_insn "arm_casesi_internal"
8531   [(parallel [(set (pc)
8532                (if_then_else
8533                 (leu (match_operand:SI 0 "s_register_operand" "r")
8534                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8535                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8536                                  (label_ref (match_operand 2 "" ""))))
8537                 (label_ref (match_operand 3 "" ""))))
8538               (clobber (reg:CC CC_REGNUM))
8539               (use (label_ref (match_dup 2)))])]
8540   "TARGET_ARM"
8541   "*
8542     if (flag_pic)
8543       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8544     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8545   "
8546   [(set_attr "conds" "clob")
8547    (set_attr "length" "12")]
8548 )
8549
8550 (define_expand "indirect_jump"
8551   [(set (pc)
8552         (match_operand:SI 0 "s_register_operand" ""))]
8553   "TARGET_EITHER"
8554   "
8555   /* Thumb-2 doesn't have mov pc, reg.  Explicitly set the low bit of the
8556      address and use bx.  */
8557   if (TARGET_THUMB2)
8558     {
8559       rtx tmp;
8560       tmp = gen_reg_rtx (SImode);
8561       emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8562       operands[0] = tmp;
8563     }
8564   "
8565 )
8566
8567 ;; NB Never uses BX.
8568 (define_insn "*arm_indirect_jump"
8569   [(set (pc)
8570         (match_operand:SI 0 "s_register_operand" "r"))]
8571   "TARGET_ARM"
8572   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8573   [(set_attr "predicable" "yes")]
8574 )
8575
8576 (define_insn "*load_indirect_jump"
8577   [(set (pc)
8578         (match_operand:SI 0 "memory_operand" "m"))]
8579   "TARGET_ARM"
8580   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8581   [(set_attr "type" "load1")
8582    (set_attr "pool_range" "4096")
8583    (set_attr "neg_pool_range" "4084")
8584    (set_attr "predicable" "yes")]
8585 )
8586
8587 ;; NB Never uses BX.
8588 (define_insn "*thumb1_indirect_jump"
8589   [(set (pc)
8590         (match_operand:SI 0 "register_operand" "l*r"))]
8591   "TARGET_THUMB1"
8592   "mov\\tpc, %0"
8593   [(set_attr "conds" "clob")
8594    (set_attr "length" "2")]
8595 )
8596
8597 \f
8598 ;; Misc insns
8599
8600 (define_insn "nop"
8601   [(const_int 0)]
8602   "TARGET_EITHER"
8603   "*
8604   if (TARGET_UNIFIED_ASM)
8605     return \"nop\";
8606   if (TARGET_ARM)
8607     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8608   return  \"mov\\tr8, r8\";
8609   "
8610   [(set (attr "length")
8611         (if_then_else (eq_attr "is_thumb" "yes")
8612                       (const_int 2)
8613                       (const_int 4)))]
8614 )
8615
8616 \f
8617 ;; Patterns to allow combination of arithmetic, cond code and shifts
8618
8619 (define_insn "*arith_shiftsi"
8620   [(set (match_operand:SI 0 "s_register_operand" "=r")
8621         (match_operator:SI 1 "shiftable_operator"
8622           [(match_operator:SI 3 "shift_operator"
8623              [(match_operand:SI 4 "s_register_operand" "r")
8624               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8625            (match_operand:SI 2 "s_register_operand" "r")]))]
8626   "TARGET_ARM"
8627   "%i1%?\\t%0, %2, %4%S3"
8628   [(set_attr "predicable" "yes")
8629    (set_attr "shift" "4")
8630    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8631                       (const_string "alu_shift")
8632                       (const_string "alu_shift_reg")))]
8633 )
8634
8635 (define_split
8636   [(set (match_operand:SI 0 "s_register_operand" "")
8637         (match_operator:SI 1 "shiftable_operator"
8638          [(match_operator:SI 2 "shiftable_operator"
8639            [(match_operator:SI 3 "shift_operator"
8640              [(match_operand:SI 4 "s_register_operand" "")
8641               (match_operand:SI 5 "reg_or_int_operand" "")])
8642             (match_operand:SI 6 "s_register_operand" "")])
8643           (match_operand:SI 7 "arm_rhs_operand" "")]))
8644    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8645   "TARGET_ARM"
8646   [(set (match_dup 8)
8647         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8648                          (match_dup 6)]))
8649    (set (match_dup 0)
8650         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8651   "")
8652
8653 (define_insn "*arith_shiftsi_compare0"
8654   [(set (reg:CC_NOOV CC_REGNUM)
8655         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8656                           [(match_operator:SI 3 "shift_operator"
8657                             [(match_operand:SI 4 "s_register_operand" "r")
8658                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8659                            (match_operand:SI 2 "s_register_operand" "r")])
8660                          (const_int 0)))
8661    (set (match_operand:SI 0 "s_register_operand" "=r")
8662         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8663                          (match_dup 2)]))]
8664   "TARGET_ARM"
8665   "%i1%.\\t%0, %2, %4%S3"
8666   [(set_attr "conds" "set")
8667    (set_attr "shift" "4")
8668    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8669                       (const_string "alu_shift")
8670                       (const_string "alu_shift_reg")))]
8671 )
8672
8673 (define_insn "*arith_shiftsi_compare0_scratch"
8674   [(set (reg:CC_NOOV CC_REGNUM)
8675         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8676                           [(match_operator:SI 3 "shift_operator"
8677                             [(match_operand:SI 4 "s_register_operand" "r")
8678                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8679                            (match_operand:SI 2 "s_register_operand" "r")])
8680                          (const_int 0)))
8681    (clobber (match_scratch:SI 0 "=r"))]
8682   "TARGET_ARM"
8683   "%i1%.\\t%0, %2, %4%S3"
8684   [(set_attr "conds" "set")
8685    (set_attr "shift" "4")
8686    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8687                       (const_string "alu_shift")
8688                       (const_string "alu_shift_reg")))]
8689 )
8690
8691 (define_insn "*sub_shiftsi"
8692   [(set (match_operand:SI 0 "s_register_operand" "=r")
8693         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8694                   (match_operator:SI 2 "shift_operator"
8695                    [(match_operand:SI 3 "s_register_operand" "r")
8696                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8697   "TARGET_ARM"
8698   "sub%?\\t%0, %1, %3%S2"
8699   [(set_attr "predicable" "yes")
8700    (set_attr "shift" "3")
8701    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8702                       (const_string "alu_shift")
8703                       (const_string "alu_shift_reg")))]
8704 )
8705
8706 (define_insn "*sub_shiftsi_compare0"
8707   [(set (reg:CC_NOOV CC_REGNUM)
8708         (compare:CC_NOOV
8709          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8710                    (match_operator:SI 2 "shift_operator"
8711                     [(match_operand:SI 3 "s_register_operand" "r")
8712                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8713          (const_int 0)))
8714    (set (match_operand:SI 0 "s_register_operand" "=r")
8715         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8716                                                  (match_dup 4)])))]
8717   "TARGET_ARM"
8718   "sub%.\\t%0, %1, %3%S2"
8719   [(set_attr "conds" "set")
8720    (set_attr "shift" "3")
8721    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8722                       (const_string "alu_shift")
8723                       (const_string "alu_shift_reg")))]
8724 )
8725
8726 (define_insn "*sub_shiftsi_compare0_scratch"
8727   [(set (reg:CC_NOOV CC_REGNUM)
8728         (compare:CC_NOOV
8729          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8730                    (match_operator:SI 2 "shift_operator"
8731                     [(match_operand:SI 3 "s_register_operand" "r")
8732                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8733          (const_int 0)))
8734    (clobber (match_scratch:SI 0 "=r"))]
8735   "TARGET_ARM"
8736   "sub%.\\t%0, %1, %3%S2"
8737   [(set_attr "conds" "set")
8738    (set_attr "shift" "3")
8739    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8740                       (const_string "alu_shift")
8741                       (const_string "alu_shift_reg")))]
8742 )
8743
8744 \f
8745
8746 (define_insn "*and_scc"
8747   [(set (match_operand:SI 0 "s_register_operand" "=r")
8748         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8749                  [(match_operand 3 "cc_register" "") (const_int 0)])
8750                 (match_operand:SI 2 "s_register_operand" "r")))]
8751   "TARGET_ARM"
8752   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8753   [(set_attr "conds" "use")
8754    (set_attr "length" "8")]
8755 )
8756
8757 (define_insn "*ior_scc"
8758   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8759         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8760                  [(match_operand 3 "cc_register" "") (const_int 0)])
8761                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8762   "TARGET_ARM"
8763   "@
8764    orr%d2\\t%0, %1, #1
8765    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8766   [(set_attr "conds" "use")
8767    (set_attr "length" "4,8")]
8768 )
8769
8770 (define_insn "*compare_scc"
8771   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8772         (match_operator:SI 1 "arm_comparison_operator"
8773          [(match_operand:SI 2 "s_register_operand" "r,r")
8774           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8775    (clobber (reg:CC CC_REGNUM))]
8776   "TARGET_ARM"
8777   "*
8778     if (operands[3] == const0_rtx)
8779       {
8780         if (GET_CODE (operands[1]) == LT)
8781           return \"mov\\t%0, %2, lsr #31\";
8782
8783         if (GET_CODE (operands[1]) == GE)
8784           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8785
8786         if (GET_CODE (operands[1]) == EQ)
8787           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8788       }
8789
8790     if (GET_CODE (operands[1]) == NE)
8791       {
8792         if (which_alternative == 1)
8793           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8794         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8795       }
8796     if (which_alternative == 1)
8797       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8798     else
8799       output_asm_insn (\"cmp\\t%2, %3\", operands);
8800     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8801   "
8802   [(set_attr "conds" "clob")
8803    (set_attr "length" "12")]
8804 )
8805
8806 (define_insn "*cond_move"
8807   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8808         (if_then_else:SI (match_operator 3 "equality_operator"
8809                           [(match_operator 4 "arm_comparison_operator"
8810                             [(match_operand 5 "cc_register" "") (const_int 0)])
8811                            (const_int 0)])
8812                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8813                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8814   "TARGET_ARM"
8815   "*
8816     if (GET_CODE (operands[3]) == NE)
8817       {
8818         if (which_alternative != 1)
8819           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8820         if (which_alternative != 0)
8821           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8822         return \"\";
8823       }
8824     if (which_alternative != 0)
8825       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8826     if (which_alternative != 1)
8827       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8828     return \"\";
8829   "
8830   [(set_attr "conds" "use")
8831    (set_attr "length" "4,4,8")]
8832 )
8833
8834 (define_insn "*cond_arith"
8835   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8836         (match_operator:SI 5 "shiftable_operator" 
8837          [(match_operator:SI 4 "arm_comparison_operator"
8838            [(match_operand:SI 2 "s_register_operand" "r,r")
8839             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8840           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8841    (clobber (reg:CC CC_REGNUM))]
8842   "TARGET_ARM"
8843   "*
8844     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8845       return \"%i5\\t%0, %1, %2, lsr #31\";
8846
8847     output_asm_insn (\"cmp\\t%2, %3\", operands);
8848     if (GET_CODE (operands[5]) == AND)
8849       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8850     else if (GET_CODE (operands[5]) == MINUS)
8851       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8852     else if (which_alternative != 0)
8853       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8854     return \"%i5%d4\\t%0, %1, #1\";
8855   "
8856   [(set_attr "conds" "clob")
8857    (set_attr "length" "12")]
8858 )
8859
8860 (define_insn "*cond_sub"
8861   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8862         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8863                   (match_operator:SI 4 "arm_comparison_operator"
8864                    [(match_operand:SI 2 "s_register_operand" "r,r")
8865                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8866    (clobber (reg:CC CC_REGNUM))]
8867   "TARGET_ARM"
8868   "*
8869     output_asm_insn (\"cmp\\t%2, %3\", operands);
8870     if (which_alternative != 0)
8871       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8872     return \"sub%d4\\t%0, %1, #1\";
8873   "
8874   [(set_attr "conds" "clob")
8875    (set_attr "length" "8,12")]
8876 )
8877
8878 ;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
8879 (define_insn "*cmp_ite0"
8880   [(set (match_operand 6 "dominant_cc_register" "")
8881         (compare
8882          (if_then_else:SI
8883           (match_operator 4 "arm_comparison_operator"
8884            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8885             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8886           (match_operator:SI 5 "arm_comparison_operator"
8887            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8888             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8889           (const_int 0))
8890          (const_int 0)))]
8891   "TARGET_ARM"
8892   "*
8893   {
8894     static const char * const opcodes[4][2] =
8895     {
8896       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8897        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8898       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8899        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8900       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8901        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8902       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8903        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8904     };
8905     int swap =
8906       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8907
8908     return opcodes[which_alternative][swap];
8909   }"
8910   [(set_attr "conds" "set")
8911    (set_attr "length" "8")]
8912 )
8913
8914 (define_insn "*cmp_ite1"
8915   [(set (match_operand 6 "dominant_cc_register" "")
8916         (compare
8917          (if_then_else:SI
8918           (match_operator 4 "arm_comparison_operator"
8919            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8920             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8921           (match_operator:SI 5 "arm_comparison_operator"
8922            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8923             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8924           (const_int 1))
8925          (const_int 0)))]
8926   "TARGET_ARM"
8927   "*
8928   {
8929     static const char * const opcodes[4][2] =
8930     {
8931       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8932        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8933       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8934        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8935       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8936        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8937       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8938        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8939     };
8940     int swap =
8941       comparison_dominates_p (GET_CODE (operands[5]),
8942                               reverse_condition (GET_CODE (operands[4])));
8943
8944     return opcodes[which_alternative][swap];
8945   }"
8946   [(set_attr "conds" "set")
8947    (set_attr "length" "8")]
8948 )
8949
8950 (define_insn "*cmp_and"
8951   [(set (match_operand 6 "dominant_cc_register" "")
8952         (compare
8953          (and:SI
8954           (match_operator 4 "arm_comparison_operator"
8955            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8956             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8957           (match_operator:SI 5 "arm_comparison_operator"
8958            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8959             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8960          (const_int 0)))]
8961   "TARGET_ARM"
8962   "*
8963   {
8964     static const char *const opcodes[4][2] =
8965     {
8966       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8967        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8968       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8969        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8970       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8971        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8972       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8973        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8974     };
8975     int swap =
8976       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8977
8978     return opcodes[which_alternative][swap];
8979   }"
8980   [(set_attr "conds" "set")
8981    (set_attr "predicable" "no")
8982    (set_attr "length" "8")]
8983 )
8984
8985 (define_insn "*cmp_ior"
8986   [(set (match_operand 6 "dominant_cc_register" "")
8987         (compare
8988          (ior:SI
8989           (match_operator 4 "arm_comparison_operator"
8990            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8991             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8992           (match_operator:SI 5 "arm_comparison_operator"
8993            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8994             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8995          (const_int 0)))]
8996   "TARGET_ARM"
8997   "*
8998 {
8999   static const char *const opcodes[4][2] =
9000   {
9001     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9002      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9003     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9004      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9005     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9006      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9007     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9008      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9009   };
9010   int swap =
9011     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9012
9013   return opcodes[which_alternative][swap];
9014 }
9015 "
9016   [(set_attr "conds" "set")
9017    (set_attr "length" "8")]
9018 )
9019
9020 (define_insn_and_split "*ior_scc_scc"
9021   [(set (match_operand:SI 0 "s_register_operand" "=r")
9022         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9023                  [(match_operand:SI 1 "s_register_operand" "r")
9024                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9025                 (match_operator:SI 6 "arm_comparison_operator"
9026                  [(match_operand:SI 4 "s_register_operand" "r")
9027                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9028    (clobber (reg:CC CC_REGNUM))]
9029   "TARGET_ARM
9030    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9031        != CCmode)"
9032   "#"
9033   "TARGET_ARM && reload_completed"
9034   [(set (match_dup 7)
9035         (compare
9036          (ior:SI
9037           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9038           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9039          (const_int 0)))
9040    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9041   "operands[7]
9042      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9043                                                   DOM_CC_X_OR_Y),
9044                     CC_REGNUM);"
9045   [(set_attr "conds" "clob")
9046    (set_attr "length" "16")])
9047
9048 ; If the above pattern is followed by a CMP insn, then the compare is 
9049 ; redundant, since we can rework the conditional instruction that follows.
9050 (define_insn_and_split "*ior_scc_scc_cmp"
9051   [(set (match_operand 0 "dominant_cc_register" "")
9052         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9053                           [(match_operand:SI 1 "s_register_operand" "r")
9054                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9055                          (match_operator:SI 6 "arm_comparison_operator"
9056                           [(match_operand:SI 4 "s_register_operand" "r")
9057                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9058                  (const_int 0)))
9059    (set (match_operand:SI 7 "s_register_operand" "=r")
9060         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9061                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9062   "TARGET_ARM"
9063   "#"
9064   "TARGET_ARM && reload_completed"
9065   [(set (match_dup 0)
9066         (compare
9067          (ior:SI
9068           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9069           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9070          (const_int 0)))
9071    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9072   ""
9073   [(set_attr "conds" "set")
9074    (set_attr "length" "16")])
9075
9076 (define_insn_and_split "*and_scc_scc"
9077   [(set (match_operand:SI 0 "s_register_operand" "=r")
9078         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9079                  [(match_operand:SI 1 "s_register_operand" "r")
9080                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9081                 (match_operator:SI 6 "arm_comparison_operator"
9082                  [(match_operand:SI 4 "s_register_operand" "r")
9083                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9084    (clobber (reg:CC CC_REGNUM))]
9085   "TARGET_ARM
9086    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9087        != CCmode)"
9088   "#"
9089   "TARGET_ARM && reload_completed
9090    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9091        != CCmode)"
9092   [(set (match_dup 7)
9093         (compare
9094          (and:SI
9095           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9096           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9097          (const_int 0)))
9098    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9099   "operands[7]
9100      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9101                                                   DOM_CC_X_AND_Y),
9102                     CC_REGNUM);"
9103   [(set_attr "conds" "clob")
9104    (set_attr "length" "16")])
9105
9106 ; If the above pattern is followed by a CMP insn, then the compare is 
9107 ; redundant, since we can rework the conditional instruction that follows.
9108 (define_insn_and_split "*and_scc_scc_cmp"
9109   [(set (match_operand 0 "dominant_cc_register" "")
9110         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9111                           [(match_operand:SI 1 "s_register_operand" "r")
9112                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9113                          (match_operator:SI 6 "arm_comparison_operator"
9114                           [(match_operand:SI 4 "s_register_operand" "r")
9115                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9116                  (const_int 0)))
9117    (set (match_operand:SI 7 "s_register_operand" "=r")
9118         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9119                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9120   "TARGET_ARM"
9121   "#"
9122   "TARGET_ARM && reload_completed"
9123   [(set (match_dup 0)
9124         (compare
9125          (and:SI
9126           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9127           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9128          (const_int 0)))
9129    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9130   ""
9131   [(set_attr "conds" "set")
9132    (set_attr "length" "16")])
9133
9134 ;; If there is no dominance in the comparison, then we can still save an
9135 ;; instruction in the AND case, since we can know that the second compare
9136 ;; need only zero the value if false (if true, then the value is already
9137 ;; correct).
9138 (define_insn_and_split "*and_scc_scc_nodom"
9139   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9140         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9141                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
9142                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9143                 (match_operator:SI 6 "arm_comparison_operator"
9144                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
9145                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9146    (clobber (reg:CC CC_REGNUM))]
9147   "TARGET_ARM
9148    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9149        == CCmode)"
9150   "#"
9151   "TARGET_ARM && reload_completed"
9152   [(parallel [(set (match_dup 0)
9153                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9154               (clobber (reg:CC CC_REGNUM))])
9155    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9156    (set (match_dup 0)
9157         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9158                          (match_dup 0)
9159                          (const_int 0)))]
9160   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9161                                               operands[4], operands[5]),
9162                               CC_REGNUM);
9163    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9164                                   operands[5]);"
9165   [(set_attr "conds" "clob")
9166    (set_attr "length" "20")])
9167
9168 (define_split
9169   [(set (reg:CC_NOOV CC_REGNUM)
9170         (compare:CC_NOOV (ior:SI
9171                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9172                                   (const_int 1))
9173                           (match_operator:SI 1 "comparison_operator"
9174                            [(match_operand:SI 2 "s_register_operand" "")
9175                             (match_operand:SI 3 "arm_add_operand" "")]))
9176                          (const_int 0)))
9177    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9178   "TARGET_ARM"
9179   [(set (match_dup 4)
9180         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9181                 (match_dup 0)))
9182    (set (reg:CC_NOOV CC_REGNUM)
9183         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9184                          (const_int 0)))]
9185   "")
9186
9187 (define_split
9188   [(set (reg:CC_NOOV CC_REGNUM)
9189         (compare:CC_NOOV (ior:SI
9190                           (match_operator:SI 1 "comparison_operator"
9191                            [(match_operand:SI 2 "s_register_operand" "")
9192                             (match_operand:SI 3 "arm_add_operand" "")])
9193                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9194                                   (const_int 1)))
9195                          (const_int 0)))
9196    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9197   "TARGET_ARM"
9198   [(set (match_dup 4)
9199         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9200                 (match_dup 0)))
9201    (set (reg:CC_NOOV CC_REGNUM)
9202         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9203                          (const_int 0)))]
9204   "")
9205 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9206
9207 (define_insn "*negscc"
9208   [(set (match_operand:SI 0 "s_register_operand" "=r")
9209         (neg:SI (match_operator 3 "arm_comparison_operator"
9210                  [(match_operand:SI 1 "s_register_operand" "r")
9211                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9212    (clobber (reg:CC CC_REGNUM))]
9213   "TARGET_ARM"
9214   "*
9215   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
9216     return \"mov\\t%0, %1, asr #31\";
9217
9218   if (GET_CODE (operands[3]) == NE)
9219     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9220
9221   if (GET_CODE (operands[3]) == GT)
9222     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
9223
9224   output_asm_insn (\"cmp\\t%1, %2\", operands);
9225   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9226   return \"mvn%d3\\t%0, #0\";
9227   "
9228   [(set_attr "conds" "clob")
9229    (set_attr "length" "12")]
9230 )
9231
9232 (define_insn "movcond"
9233   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9234         (if_then_else:SI
9235          (match_operator 5 "arm_comparison_operator"
9236           [(match_operand:SI 3 "s_register_operand" "r,r,r")
9237            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9238          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9239          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9240    (clobber (reg:CC CC_REGNUM))]
9241   "TARGET_ARM"
9242   "*
9243   if (GET_CODE (operands[5]) == LT
9244       && (operands[4] == const0_rtx))
9245     {
9246       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9247         {
9248           if (operands[2] == const0_rtx)
9249             return \"and\\t%0, %1, %3, asr #31\";
9250           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9251         }
9252       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9253         {
9254           if (operands[1] == const0_rtx)
9255             return \"bic\\t%0, %2, %3, asr #31\";
9256           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9257         }
9258       /* The only case that falls through to here is when both ops 1 & 2
9259          are constants.  */
9260     }
9261
9262   if (GET_CODE (operands[5]) == GE
9263       && (operands[4] == const0_rtx))
9264     {
9265       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9266         {
9267           if (operands[2] == const0_rtx)
9268             return \"bic\\t%0, %1, %3, asr #31\";
9269           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9270         }
9271       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9272         {
9273           if (operands[1] == const0_rtx)
9274             return \"and\\t%0, %2, %3, asr #31\";
9275           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9276         }
9277       /* The only case that falls through to here is when both ops 1 & 2
9278          are constants.  */
9279     }
9280   if (GET_CODE (operands[4]) == CONST_INT
9281       && !const_ok_for_arm (INTVAL (operands[4])))
9282     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9283   else
9284     output_asm_insn (\"cmp\\t%3, %4\", operands);
9285   if (which_alternative != 0)
9286     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9287   if (which_alternative != 1)
9288     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9289   return \"\";
9290   "
9291   [(set_attr "conds" "clob")
9292    (set_attr "length" "8,8,12")]
9293 )
9294
9295 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9296
9297 (define_insn "*ifcompare_plus_move"
9298   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9299         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9300                           [(match_operand:SI 4 "s_register_operand" "r,r")
9301                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9302                          (plus:SI
9303                           (match_operand:SI 2 "s_register_operand" "r,r")
9304                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9305                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9306    (clobber (reg:CC CC_REGNUM))]
9307   "TARGET_ARM"
9308   "#"
9309   [(set_attr "conds" "clob")
9310    (set_attr "length" "8,12")]
9311 )
9312
9313 (define_insn "*if_plus_move"
9314   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9315         (if_then_else:SI
9316          (match_operator 4 "arm_comparison_operator"
9317           [(match_operand 5 "cc_register" "") (const_int 0)])
9318          (plus:SI
9319           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9320           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9321          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9322   "TARGET_ARM"
9323   "@
9324    add%d4\\t%0, %2, %3
9325    sub%d4\\t%0, %2, #%n3
9326    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9327    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9328   [(set_attr "conds" "use")
9329    (set_attr "length" "4,4,8,8")
9330    (set_attr "type" "*,*,*,*")]
9331 )
9332
9333 (define_insn "*ifcompare_move_plus"
9334   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9335         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9336                           [(match_operand:SI 4 "s_register_operand" "r,r")
9337                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9338                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9339                          (plus:SI
9340                           (match_operand:SI 2 "s_register_operand" "r,r")
9341                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9342    (clobber (reg:CC CC_REGNUM))]
9343   "TARGET_ARM"
9344   "#"
9345   [(set_attr "conds" "clob")
9346    (set_attr "length" "8,12")]
9347 )
9348
9349 (define_insn "*if_move_plus"
9350   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9351         (if_then_else:SI
9352          (match_operator 4 "arm_comparison_operator"
9353           [(match_operand 5 "cc_register" "") (const_int 0)])
9354          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9355          (plus:SI
9356           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9357           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9358   "TARGET_ARM"
9359   "@
9360    add%D4\\t%0, %2, %3
9361    sub%D4\\t%0, %2, #%n3
9362    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9363    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9364   [(set_attr "conds" "use")
9365    (set_attr "length" "4,4,8,8")
9366    (set_attr "type" "*,*,*,*")]
9367 )
9368
9369 (define_insn "*ifcompare_arith_arith"
9370   [(set (match_operand:SI 0 "s_register_operand" "=r")
9371         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9372                           [(match_operand:SI 5 "s_register_operand" "r")
9373                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9374                          (match_operator:SI 8 "shiftable_operator"
9375                           [(match_operand:SI 1 "s_register_operand" "r")
9376                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9377                          (match_operator:SI 7 "shiftable_operator"
9378                           [(match_operand:SI 3 "s_register_operand" "r")
9379                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9380    (clobber (reg:CC CC_REGNUM))]
9381   "TARGET_ARM"
9382   "#"
9383   [(set_attr "conds" "clob")
9384    (set_attr "length" "12")]
9385 )
9386
9387 (define_insn "*if_arith_arith"
9388   [(set (match_operand:SI 0 "s_register_operand" "=r")
9389         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9390                           [(match_operand 8 "cc_register" "") (const_int 0)])
9391                          (match_operator:SI 6 "shiftable_operator"
9392                           [(match_operand:SI 1 "s_register_operand" "r")
9393                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9394                          (match_operator:SI 7 "shiftable_operator"
9395                           [(match_operand:SI 3 "s_register_operand" "r")
9396                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9397   "TARGET_ARM"
9398   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9399   [(set_attr "conds" "use")
9400    (set_attr "length" "8")]
9401 )
9402
9403 (define_insn "*ifcompare_arith_move"
9404   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9405         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9406                           [(match_operand:SI 2 "s_register_operand" "r,r")
9407                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9408                          (match_operator:SI 7 "shiftable_operator"
9409                           [(match_operand:SI 4 "s_register_operand" "r,r")
9410                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9411                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9412    (clobber (reg:CC CC_REGNUM))]
9413   "TARGET_ARM"
9414   "*
9415   /* If we have an operation where (op x 0) is the identity operation and
9416      the conditional operator is LT or GE and we are comparing against zero and
9417      everything is in registers then we can do this in two instructions.  */
9418   if (operands[3] == const0_rtx
9419       && GET_CODE (operands[7]) != AND
9420       && GET_CODE (operands[5]) == REG
9421       && GET_CODE (operands[1]) == REG 
9422       && REGNO (operands[1]) == REGNO (operands[4])
9423       && REGNO (operands[4]) != REGNO (operands[0]))
9424     {
9425       if (GET_CODE (operands[6]) == LT)
9426         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9427       else if (GET_CODE (operands[6]) == GE)
9428         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9429     }
9430   if (GET_CODE (operands[3]) == CONST_INT
9431       && !const_ok_for_arm (INTVAL (operands[3])))
9432     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9433   else
9434     output_asm_insn (\"cmp\\t%2, %3\", operands);
9435   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9436   if (which_alternative != 0)
9437     return \"mov%D6\\t%0, %1\";
9438   return \"\";
9439   "
9440   [(set_attr "conds" "clob")
9441    (set_attr "length" "8,12")]
9442 )
9443
9444 (define_insn "*if_arith_move"
9445   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9446         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9447                           [(match_operand 6 "cc_register" "") (const_int 0)])
9448                          (match_operator:SI 5 "shiftable_operator"
9449                           [(match_operand:SI 2 "s_register_operand" "r,r")
9450                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9451                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9452   "TARGET_ARM"
9453   "@
9454    %I5%d4\\t%0, %2, %3
9455    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9456   [(set_attr "conds" "use")
9457    (set_attr "length" "4,8")
9458    (set_attr "type" "*,*")]
9459 )
9460
9461 (define_insn "*ifcompare_move_arith"
9462   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9463         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9464                           [(match_operand:SI 4 "s_register_operand" "r,r")
9465                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9466                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9467                          (match_operator:SI 7 "shiftable_operator"
9468                           [(match_operand:SI 2 "s_register_operand" "r,r")
9469                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9470    (clobber (reg:CC CC_REGNUM))]
9471   "TARGET_ARM"
9472   "*
9473   /* If we have an operation where (op x 0) is the identity operation and
9474      the conditional operator is LT or GE and we are comparing against zero and
9475      everything is in registers then we can do this in two instructions */
9476   if (operands[5] == const0_rtx
9477       && GET_CODE (operands[7]) != AND
9478       && GET_CODE (operands[3]) == REG
9479       && GET_CODE (operands[1]) == REG 
9480       && REGNO (operands[1]) == REGNO (operands[2])
9481       && REGNO (operands[2]) != REGNO (operands[0]))
9482     {
9483       if (GET_CODE (operands[6]) == GE)
9484         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9485       else if (GET_CODE (operands[6]) == LT)
9486         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9487     }
9488
9489   if (GET_CODE (operands[5]) == CONST_INT
9490       && !const_ok_for_arm (INTVAL (operands[5])))
9491     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9492   else
9493     output_asm_insn (\"cmp\\t%4, %5\", operands);
9494
9495   if (which_alternative != 0)
9496     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9497   return \"%I7%D6\\t%0, %2, %3\";
9498   "
9499   [(set_attr "conds" "clob")
9500    (set_attr "length" "8,12")]
9501 )
9502
9503 (define_insn "*if_move_arith"
9504   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9505         (if_then_else:SI
9506          (match_operator 4 "arm_comparison_operator"
9507           [(match_operand 6 "cc_register" "") (const_int 0)])
9508          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9509          (match_operator:SI 5 "shiftable_operator"
9510           [(match_operand:SI 2 "s_register_operand" "r,r")
9511            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9512   "TARGET_ARM"
9513   "@
9514    %I5%D4\\t%0, %2, %3
9515    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9516   [(set_attr "conds" "use")
9517    (set_attr "length" "4,8")
9518    (set_attr "type" "*,*")]
9519 )
9520
9521 (define_insn "*ifcompare_move_not"
9522   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9523         (if_then_else:SI
9524          (match_operator 5 "arm_comparison_operator"
9525           [(match_operand:SI 3 "s_register_operand" "r,r")
9526            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9527          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9528          (not:SI
9529           (match_operand:SI 2 "s_register_operand" "r,r"))))
9530    (clobber (reg:CC CC_REGNUM))]
9531   "TARGET_ARM"
9532   "#"
9533   [(set_attr "conds" "clob")
9534    (set_attr "length" "8,12")]
9535 )
9536
9537 (define_insn "*if_move_not"
9538   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9539         (if_then_else:SI
9540          (match_operator 4 "arm_comparison_operator"
9541           [(match_operand 3 "cc_register" "") (const_int 0)])
9542          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9543          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9544   "TARGET_ARM"
9545   "@
9546    mvn%D4\\t%0, %2
9547    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9548    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9549   [(set_attr "conds" "use")
9550    (set_attr "length" "4,8,8")]
9551 )
9552
9553 (define_insn "*ifcompare_not_move"
9554   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9555         (if_then_else:SI 
9556          (match_operator 5 "arm_comparison_operator"
9557           [(match_operand:SI 3 "s_register_operand" "r,r")
9558            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9559          (not:SI
9560           (match_operand:SI 2 "s_register_operand" "r,r"))
9561          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9562    (clobber (reg:CC CC_REGNUM))]
9563   "TARGET_ARM"
9564   "#"
9565   [(set_attr "conds" "clob")
9566    (set_attr "length" "8,12")]
9567 )
9568
9569 (define_insn "*if_not_move"
9570   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9571         (if_then_else:SI
9572          (match_operator 4 "arm_comparison_operator"
9573           [(match_operand 3 "cc_register" "") (const_int 0)])
9574          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9575          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9576   "TARGET_ARM"
9577   "@
9578    mvn%d4\\t%0, %2
9579    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9580    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9581   [(set_attr "conds" "use")
9582    (set_attr "length" "4,8,8")]
9583 )
9584
9585 (define_insn "*ifcompare_shift_move"
9586   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9587         (if_then_else:SI
9588          (match_operator 6 "arm_comparison_operator"
9589           [(match_operand:SI 4 "s_register_operand" "r,r")
9590            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9591          (match_operator:SI 7 "shift_operator"
9592           [(match_operand:SI 2 "s_register_operand" "r,r")
9593            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9594          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9595    (clobber (reg:CC CC_REGNUM))]
9596   "TARGET_ARM"
9597   "#"
9598   [(set_attr "conds" "clob")
9599    (set_attr "length" "8,12")]
9600 )
9601
9602 (define_insn "*if_shift_move"
9603   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9604         (if_then_else:SI
9605          (match_operator 5 "arm_comparison_operator"
9606           [(match_operand 6 "cc_register" "") (const_int 0)])
9607          (match_operator:SI 4 "shift_operator"
9608           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9609            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9610          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9611   "TARGET_ARM"
9612   "@
9613    mov%d5\\t%0, %2%S4
9614    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9615    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9616   [(set_attr "conds" "use")
9617    (set_attr "shift" "2")
9618    (set_attr "length" "4,8,8")
9619    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9620                       (const_string "alu_shift")
9621                       (const_string "alu_shift_reg")))]
9622 )
9623
9624 (define_insn "*ifcompare_move_shift"
9625   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9626         (if_then_else:SI
9627          (match_operator 6 "arm_comparison_operator"
9628           [(match_operand:SI 4 "s_register_operand" "r,r")
9629            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9630          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9631          (match_operator:SI 7 "shift_operator"
9632           [(match_operand:SI 2 "s_register_operand" "r,r")
9633            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9634    (clobber (reg:CC CC_REGNUM))]
9635   "TARGET_ARM"
9636   "#"
9637   [(set_attr "conds" "clob")
9638    (set_attr "length" "8,12")]
9639 )
9640
9641 (define_insn "*if_move_shift"
9642   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9643         (if_then_else:SI
9644          (match_operator 5 "arm_comparison_operator"
9645           [(match_operand 6 "cc_register" "") (const_int 0)])
9646          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9647          (match_operator:SI 4 "shift_operator"
9648           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9649            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9650   "TARGET_ARM"
9651   "@
9652    mov%D5\\t%0, %2%S4
9653    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9654    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9655   [(set_attr "conds" "use")
9656    (set_attr "shift" "2")
9657    (set_attr "length" "4,8,8")
9658    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9659                       (const_string "alu_shift")
9660                       (const_string "alu_shift_reg")))]
9661 )
9662
9663 (define_insn "*ifcompare_shift_shift"
9664   [(set (match_operand:SI 0 "s_register_operand" "=r")
9665         (if_then_else:SI
9666          (match_operator 7 "arm_comparison_operator"
9667           [(match_operand:SI 5 "s_register_operand" "r")
9668            (match_operand:SI 6 "arm_add_operand" "rIL")])
9669          (match_operator:SI 8 "shift_operator"
9670           [(match_operand:SI 1 "s_register_operand" "r")
9671            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9672          (match_operator:SI 9 "shift_operator"
9673           [(match_operand:SI 3 "s_register_operand" "r")
9674            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9675    (clobber (reg:CC CC_REGNUM))]
9676   "TARGET_ARM"
9677   "#"
9678   [(set_attr "conds" "clob")
9679    (set_attr "length" "12")]
9680 )
9681
9682 (define_insn "*if_shift_shift"
9683   [(set (match_operand:SI 0 "s_register_operand" "=r")
9684         (if_then_else:SI
9685          (match_operator 5 "arm_comparison_operator"
9686           [(match_operand 8 "cc_register" "") (const_int 0)])
9687          (match_operator:SI 6 "shift_operator"
9688           [(match_operand:SI 1 "s_register_operand" "r")
9689            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9690          (match_operator:SI 7 "shift_operator"
9691           [(match_operand:SI 3 "s_register_operand" "r")
9692            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9693   "TARGET_ARM"
9694   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9695   [(set_attr "conds" "use")
9696    (set_attr "shift" "1")
9697    (set_attr "length" "8")
9698    (set (attr "type") (if_then_else
9699                         (and (match_operand 2 "const_int_operand" "")
9700                              (match_operand 4 "const_int_operand" ""))
9701                       (const_string "alu_shift")
9702                       (const_string "alu_shift_reg")))]
9703 )
9704
9705 (define_insn "*ifcompare_not_arith"
9706   [(set (match_operand:SI 0 "s_register_operand" "=r")
9707         (if_then_else:SI
9708          (match_operator 6 "arm_comparison_operator"
9709           [(match_operand:SI 4 "s_register_operand" "r")
9710            (match_operand:SI 5 "arm_add_operand" "rIL")])
9711          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9712          (match_operator:SI 7 "shiftable_operator"
9713           [(match_operand:SI 2 "s_register_operand" "r")
9714            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9715    (clobber (reg:CC CC_REGNUM))]
9716   "TARGET_ARM"
9717   "#"
9718   [(set_attr "conds" "clob")
9719    (set_attr "length" "12")]
9720 )
9721
9722 (define_insn "*if_not_arith"
9723   [(set (match_operand:SI 0 "s_register_operand" "=r")
9724         (if_then_else:SI
9725          (match_operator 5 "arm_comparison_operator"
9726           [(match_operand 4 "cc_register" "") (const_int 0)])
9727          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9728          (match_operator:SI 6 "shiftable_operator"
9729           [(match_operand:SI 2 "s_register_operand" "r")
9730            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9731   "TARGET_ARM"
9732   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9733   [(set_attr "conds" "use")
9734    (set_attr "length" "8")]
9735 )
9736
9737 (define_insn "*ifcompare_arith_not"
9738   [(set (match_operand:SI 0 "s_register_operand" "=r")
9739         (if_then_else:SI
9740          (match_operator 6 "arm_comparison_operator"
9741           [(match_operand:SI 4 "s_register_operand" "r")
9742            (match_operand:SI 5 "arm_add_operand" "rIL")])
9743          (match_operator:SI 7 "shiftable_operator"
9744           [(match_operand:SI 2 "s_register_operand" "r")
9745            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9746          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9747    (clobber (reg:CC CC_REGNUM))]
9748   "TARGET_ARM"
9749   "#"
9750   [(set_attr "conds" "clob")
9751    (set_attr "length" "12")]
9752 )
9753
9754 (define_insn "*if_arith_not"
9755   [(set (match_operand:SI 0 "s_register_operand" "=r")
9756         (if_then_else:SI
9757          (match_operator 5 "arm_comparison_operator"
9758           [(match_operand 4 "cc_register" "") (const_int 0)])
9759          (match_operator:SI 6 "shiftable_operator"
9760           [(match_operand:SI 2 "s_register_operand" "r")
9761            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9762          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9763   "TARGET_ARM"
9764   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9765   [(set_attr "conds" "use")
9766    (set_attr "length" "8")]
9767 )
9768
9769 (define_insn "*ifcompare_neg_move"
9770   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9771         (if_then_else:SI
9772          (match_operator 5 "arm_comparison_operator"
9773           [(match_operand:SI 3 "s_register_operand" "r,r")
9774            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9775          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9776          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9777    (clobber (reg:CC CC_REGNUM))]
9778   "TARGET_ARM"
9779   "#"
9780   [(set_attr "conds" "clob")
9781    (set_attr "length" "8,12")]
9782 )
9783
9784 (define_insn "*if_neg_move"
9785   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9786         (if_then_else:SI
9787          (match_operator 4 "arm_comparison_operator"
9788           [(match_operand 3 "cc_register" "") (const_int 0)])
9789          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9790          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9791   "TARGET_ARM"
9792   "@
9793    rsb%d4\\t%0, %2, #0
9794    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9795    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9796   [(set_attr "conds" "use")
9797    (set_attr "length" "4,8,8")]
9798 )
9799
9800 (define_insn "*ifcompare_move_neg"
9801   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9802         (if_then_else:SI
9803          (match_operator 5 "arm_comparison_operator"
9804           [(match_operand:SI 3 "s_register_operand" "r,r")
9805            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9806          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9807          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9808    (clobber (reg:CC CC_REGNUM))]
9809   "TARGET_ARM"
9810   "#"
9811   [(set_attr "conds" "clob")
9812    (set_attr "length" "8,12")]
9813 )
9814
9815 (define_insn "*if_move_neg"
9816   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9817         (if_then_else:SI
9818          (match_operator 4 "arm_comparison_operator"
9819           [(match_operand 3 "cc_register" "") (const_int 0)])
9820          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9821          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9822   "TARGET_ARM"
9823   "@
9824    rsb%D4\\t%0, %2, #0
9825    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9826    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9827   [(set_attr "conds" "use")
9828    (set_attr "length" "4,8,8")]
9829 )
9830
9831 (define_insn "*arith_adjacentmem"
9832   [(set (match_operand:SI 0 "s_register_operand" "=r")
9833         (match_operator:SI 1 "shiftable_operator"
9834          [(match_operand:SI 2 "memory_operand" "m")
9835           (match_operand:SI 3 "memory_operand" "m")]))
9836    (clobber (match_scratch:SI 4 "=r"))]
9837   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9838   "*
9839   {
9840     rtx ldm[3];
9841     rtx arith[4];
9842     rtx base_reg;
9843     HOST_WIDE_INT val1 = 0, val2 = 0;
9844
9845     if (REGNO (operands[0]) > REGNO (operands[4]))
9846       {
9847         ldm[1] = operands[4];
9848         ldm[2] = operands[0];
9849       }
9850     else
9851       {
9852         ldm[1] = operands[0];
9853         ldm[2] = operands[4];
9854       }
9855
9856     base_reg = XEXP (operands[2], 0);
9857
9858     if (!REG_P (base_reg))
9859       {
9860         val1 = INTVAL (XEXP (base_reg, 1));
9861         base_reg = XEXP (base_reg, 0);
9862       }
9863
9864     if (!REG_P (XEXP (operands[3], 0)))
9865       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9866
9867     arith[0] = operands[0];
9868     arith[3] = operands[1];
9869
9870     if (val1 < val2)
9871       {
9872         arith[1] = ldm[1];
9873         arith[2] = ldm[2];
9874       }
9875     else
9876       {
9877         arith[1] = ldm[2];
9878         arith[2] = ldm[1];
9879       }
9880
9881     ldm[0] = base_reg;
9882     if (val1 !=0 && val2 != 0)
9883       {
9884         rtx ops[3];
9885
9886         if (val1 == 4 || val2 == 4)
9887           /* Other val must be 8, since we know they are adjacent and neither
9888              is zero.  */
9889           output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
9890         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
9891           {
9892             ldm[0] = ops[0] = operands[4];
9893             ops[1] = base_reg;
9894             ops[2] = GEN_INT (val1);
9895             output_add_immediate (ops);
9896             if (val1 < val2)
9897               output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
9898             else
9899               output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
9900           }
9901         else
9902           {
9903             /* Offset is out of range for a single add, so use two ldr.  */
9904             ops[0] = ldm[1];
9905             ops[1] = base_reg;
9906             ops[2] = GEN_INT (val1);
9907             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9908             ops[0] = ldm[2];
9909             ops[2] = GEN_INT (val2);
9910             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9911           }
9912       }
9913     else if (val1 != 0)
9914       {
9915         if (val1 < val2)
9916           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
9917         else
9918           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
9919       }
9920     else
9921       {
9922         if (val1 < val2)
9923           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
9924         else
9925           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
9926       }
9927     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9928     return \"\";
9929   }"
9930   [(set_attr "length" "12")
9931    (set_attr "predicable" "yes")
9932    (set_attr "type" "load1")]
9933 )
9934
9935 ; This pattern is never tried by combine, so do it as a peephole
9936
9937 (define_peephole2
9938   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9939         (match_operand:SI 1 "arm_general_register_operand" ""))
9940    (set (reg:CC CC_REGNUM)
9941         (compare:CC (match_dup 1) (const_int 0)))]
9942   "TARGET_ARM"
9943   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9944               (set (match_dup 0) (match_dup 1))])]
9945   ""
9946 )
9947
9948 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9949 ; reversed, check that the memory references aren't volatile.
9950
9951 (define_peephole
9952   [(set (match_operand:SI 0 "s_register_operand" "=r")
9953         (match_operand:SI 4 "memory_operand" "m"))
9954    (set (match_operand:SI 1 "s_register_operand" "=r")
9955         (match_operand:SI 5 "memory_operand" "m"))
9956    (set (match_operand:SI 2 "s_register_operand" "=r")
9957         (match_operand:SI 6 "memory_operand" "m"))
9958    (set (match_operand:SI 3 "s_register_operand" "=r")
9959         (match_operand:SI 7 "memory_operand" "m"))]
9960   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9961   "*
9962   return emit_ldm_seq (operands, 4);
9963   "
9964 )
9965
9966 (define_peephole
9967   [(set (match_operand:SI 0 "s_register_operand" "=r")
9968         (match_operand:SI 3 "memory_operand" "m"))
9969    (set (match_operand:SI 1 "s_register_operand" "=r")
9970         (match_operand:SI 4 "memory_operand" "m"))
9971    (set (match_operand:SI 2 "s_register_operand" "=r")
9972         (match_operand:SI 5 "memory_operand" "m"))]
9973   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9974   "*
9975   return emit_ldm_seq (operands, 3);
9976   "
9977 )
9978
9979 (define_peephole
9980   [(set (match_operand:SI 0 "s_register_operand" "=r")
9981         (match_operand:SI 2 "memory_operand" "m"))
9982    (set (match_operand:SI 1 "s_register_operand" "=r")
9983         (match_operand:SI 3 "memory_operand" "m"))]
9984   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9985   "*
9986   return emit_ldm_seq (operands, 2);
9987   "
9988 )
9989
9990 (define_peephole
9991   [(set (match_operand:SI 4 "memory_operand" "=m")
9992         (match_operand:SI 0 "s_register_operand" "r"))
9993    (set (match_operand:SI 5 "memory_operand" "=m")
9994         (match_operand:SI 1 "s_register_operand" "r"))
9995    (set (match_operand:SI 6 "memory_operand" "=m")
9996         (match_operand:SI 2 "s_register_operand" "r"))
9997    (set (match_operand:SI 7 "memory_operand" "=m")
9998         (match_operand:SI 3 "s_register_operand" "r"))]
9999   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10000   "*
10001   return emit_stm_seq (operands, 4);
10002   "
10003 )
10004
10005 (define_peephole
10006   [(set (match_operand:SI 3 "memory_operand" "=m")
10007         (match_operand:SI 0 "s_register_operand" "r"))
10008    (set (match_operand:SI 4 "memory_operand" "=m")
10009         (match_operand:SI 1 "s_register_operand" "r"))
10010    (set (match_operand:SI 5 "memory_operand" "=m")
10011         (match_operand:SI 2 "s_register_operand" "r"))]
10012   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10013   "*
10014   return emit_stm_seq (operands, 3);
10015   "
10016 )
10017
10018 (define_peephole
10019   [(set (match_operand:SI 2 "memory_operand" "=m")
10020         (match_operand:SI 0 "s_register_operand" "r"))
10021    (set (match_operand:SI 3 "memory_operand" "=m")
10022         (match_operand:SI 1 "s_register_operand" "r"))]
10023   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10024   "*
10025   return emit_stm_seq (operands, 2);
10026   "
10027 )
10028
10029 (define_split
10030   [(set (match_operand:SI 0 "s_register_operand" "")
10031         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10032                        (const_int 0))
10033                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10034                          [(match_operand:SI 3 "s_register_operand" "")
10035                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
10036    (clobber (match_operand:SI 5 "s_register_operand" ""))]
10037   "TARGET_ARM"
10038   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10039    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10040                               (match_dup 5)))]
10041   ""
10042 )
10043
10044 ;; This split can be used because CC_Z mode implies that the following
10045 ;; branch will be an equality, or an unsigned inequality, so the sign
10046 ;; extension is not needed.
10047
10048 (define_split
10049   [(set (reg:CC_Z CC_REGNUM)
10050         (compare:CC_Z
10051          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10052                     (const_int 24))
10053          (match_operand 1 "const_int_operand" "")))
10054    (clobber (match_scratch:SI 2 ""))]
10055   "TARGET_ARM
10056    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10057        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10058   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10059    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10060   "
10061   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10062   "
10063 )
10064 ;; ??? Check the patterns above for Thumb-2 usefulness
10065
10066 (define_expand "prologue"
10067   [(clobber (const_int 0))]
10068   "TARGET_EITHER"
10069   "if (TARGET_32BIT)
10070      arm_expand_prologue ();
10071    else
10072      thumb1_expand_prologue ();
10073   DONE;
10074   "
10075 )
10076
10077 (define_expand "epilogue"
10078   [(clobber (const_int 0))]
10079   "TARGET_EITHER"
10080   "
10081   if (current_function_calls_eh_return)
10082     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10083   if (TARGET_THUMB1)
10084     thumb1_expand_epilogue ();
10085   else if (USE_RETURN_INSN (FALSE))
10086     {
10087       emit_jump_insn (gen_return ());
10088       DONE;
10089     }
10090   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10091         gen_rtvec (1,
10092                 gen_rtx_RETURN (VOIDmode)),
10093         VUNSPEC_EPILOGUE));
10094   DONE;
10095   "
10096 )
10097
10098 ;; Note - although unspec_volatile's USE all hard registers,
10099 ;; USEs are ignored after relaod has completed.  Thus we need
10100 ;; to add an unspec of the link register to ensure that flow
10101 ;; does not think that it is unused by the sibcall branch that
10102 ;; will replace the standard function epilogue.
10103 (define_insn "sibcall_epilogue"
10104   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10105               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10106   "TARGET_32BIT"
10107   "*
10108   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10109     return output_return_instruction (const_true_rtx, FALSE, FALSE);
10110   return arm_output_epilogue (next_nonnote_insn (insn));
10111   "
10112 ;; Length is absolute worst case
10113   [(set_attr "length" "44")
10114    (set_attr "type" "block")
10115    ;; We don't clobber the conditions, but the potential length of this
10116    ;; operation is sufficient to make conditionalizing the sequence 
10117    ;; unlikely to be profitable.
10118    (set_attr "conds" "clob")]
10119 )
10120
10121 (define_insn "*epilogue_insns"
10122   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10123   "TARGET_EITHER"
10124   "*
10125   if (TARGET_32BIT)
10126     return arm_output_epilogue (NULL);
10127   else /* TARGET_THUMB1 */
10128     return thumb_unexpanded_epilogue ();
10129   "
10130   ; Length is absolute worst case
10131   [(set_attr "length" "44")
10132    (set_attr "type" "block")
10133    ;; We don't clobber the conditions, but the potential length of this
10134    ;; operation is sufficient to make conditionalizing the sequence 
10135    ;; unlikely to be profitable.
10136    (set_attr "conds" "clob")]
10137 )
10138
10139 (define_expand "eh_epilogue"
10140   [(use (match_operand:SI 0 "register_operand" ""))
10141    (use (match_operand:SI 1 "register_operand" ""))
10142    (use (match_operand:SI 2 "register_operand" ""))]
10143   "TARGET_EITHER"
10144   "
10145   {
10146     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10147     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10148       {
10149         rtx ra = gen_rtx_REG (Pmode, 2);
10150
10151         emit_move_insn (ra, operands[2]);
10152         operands[2] = ra;
10153       }
10154     /* This is a hack -- we may have crystalized the function type too
10155        early.  */
10156     cfun->machine->func_type = 0;
10157   }"
10158 )
10159
10160 ;; This split is only used during output to reduce the number of patterns
10161 ;; that need assembler instructions adding to them.  We allowed the setting
10162 ;; of the conditions to be implicit during rtl generation so that
10163 ;; the conditional compare patterns would work.  However this conflicts to
10164 ;; some extent with the conditional data operations, so we have to split them
10165 ;; up again here.
10166
10167 ;; ??? Need to audit these splitters for Thumb-2.  Why isn't normal
10168 ;; conditional execution sufficient?
10169
10170 (define_split
10171   [(set (match_operand:SI 0 "s_register_operand" "")
10172         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10173                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10174                          (match_dup 0)
10175                          (match_operand 4 "" "")))
10176    (clobber (reg:CC CC_REGNUM))]
10177   "TARGET_ARM && reload_completed"
10178   [(set (match_dup 5) (match_dup 6))
10179    (cond_exec (match_dup 7)
10180               (set (match_dup 0) (match_dup 4)))]
10181   "
10182   {
10183     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10184                                              operands[2], operands[3]);
10185     enum rtx_code rc = GET_CODE (operands[1]);
10186
10187     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10188     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10189     if (mode == CCFPmode || mode == CCFPEmode)
10190       rc = reverse_condition_maybe_unordered (rc);
10191     else
10192       rc = reverse_condition (rc);
10193
10194     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10195   }"
10196 )
10197
10198 (define_split
10199   [(set (match_operand:SI 0 "s_register_operand" "")
10200         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10201                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10202                          (match_operand 4 "" "")
10203                          (match_dup 0)))
10204    (clobber (reg:CC CC_REGNUM))]
10205   "TARGET_ARM && reload_completed"
10206   [(set (match_dup 5) (match_dup 6))
10207    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10208               (set (match_dup 0) (match_dup 4)))]
10209   "
10210   {
10211     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10212                                              operands[2], operands[3]);
10213
10214     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10215     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10216   }"
10217 )
10218
10219 (define_split
10220   [(set (match_operand:SI 0 "s_register_operand" "")
10221         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10222                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10223                          (match_operand 4 "" "")
10224                          (match_operand 5 "" "")))
10225    (clobber (reg:CC CC_REGNUM))]
10226   "TARGET_ARM && reload_completed"
10227   [(set (match_dup 6) (match_dup 7))
10228    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10229               (set (match_dup 0) (match_dup 4)))
10230    (cond_exec (match_dup 8)
10231               (set (match_dup 0) (match_dup 5)))]
10232   "
10233   {
10234     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10235                                              operands[2], operands[3]);
10236     enum rtx_code rc = GET_CODE (operands[1]);
10237
10238     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10239     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10240     if (mode == CCFPmode || mode == CCFPEmode)
10241       rc = reverse_condition_maybe_unordered (rc);
10242     else
10243       rc = reverse_condition (rc);
10244
10245     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10246   }"
10247 )
10248
10249 (define_split
10250   [(set (match_operand:SI 0 "s_register_operand" "")
10251         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10252                           [(match_operand:SI 2 "s_register_operand" "")
10253                            (match_operand:SI 3 "arm_add_operand" "")])
10254                          (match_operand:SI 4 "arm_rhs_operand" "")
10255                          (not:SI
10256                           (match_operand:SI 5 "s_register_operand" ""))))
10257    (clobber (reg:CC CC_REGNUM))]
10258   "TARGET_ARM && reload_completed"
10259   [(set (match_dup 6) (match_dup 7))
10260    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10261               (set (match_dup 0) (match_dup 4)))
10262    (cond_exec (match_dup 8)
10263               (set (match_dup 0) (not:SI (match_dup 5))))]
10264   "
10265   {
10266     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10267                                              operands[2], operands[3]);
10268     enum rtx_code rc = GET_CODE (operands[1]);
10269
10270     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10271     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10272     if (mode == CCFPmode || mode == CCFPEmode)
10273       rc = reverse_condition_maybe_unordered (rc);
10274     else
10275       rc = reverse_condition (rc);
10276
10277     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10278   }"
10279 )
10280
10281 (define_insn "*cond_move_not"
10282   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10283         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10284                           [(match_operand 3 "cc_register" "") (const_int 0)])
10285                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10286                          (not:SI
10287                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10288   "TARGET_ARM"
10289   "@
10290    mvn%D4\\t%0, %2
10291    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10292   [(set_attr "conds" "use")
10293    (set_attr "length" "4,8")]
10294 )
10295
10296 ;; The next two patterns occur when an AND operation is followed by a
10297 ;; scc insn sequence 
10298
10299 (define_insn "*sign_extract_onebit"
10300   [(set (match_operand:SI 0 "s_register_operand" "=r")
10301         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10302                          (const_int 1)
10303                          (match_operand:SI 2 "const_int_operand" "n")))
10304     (clobber (reg:CC CC_REGNUM))]
10305   "TARGET_ARM"
10306   "*
10307     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10308     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10309     return \"mvnne\\t%0, #0\";
10310   "
10311   [(set_attr "conds" "clob")
10312    (set_attr "length" "8")]
10313 )
10314
10315 (define_insn "*not_signextract_onebit"
10316   [(set (match_operand:SI 0 "s_register_operand" "=r")
10317         (not:SI
10318          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10319                           (const_int 1)
10320                           (match_operand:SI 2 "const_int_operand" "n"))))
10321    (clobber (reg:CC CC_REGNUM))]
10322   "TARGET_ARM"
10323   "*
10324     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10325     output_asm_insn (\"tst\\t%1, %2\", operands);
10326     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10327     return \"movne\\t%0, #0\";
10328   "
10329   [(set_attr "conds" "clob")
10330    (set_attr "length" "12")]
10331 )
10332 ;; ??? The above patterns need auditing for Thumb-2
10333
10334 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10335 ;; expressions.  For simplicity, the first register is also in the unspec
10336 ;; part.
10337 (define_insn "*push_multi"
10338   [(match_parallel 2 "multi_register_push"
10339     [(set (match_operand:BLK 0 "memory_operand" "=m")
10340           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10341                       UNSPEC_PUSH_MULT))])]
10342   "TARGET_32BIT"
10343   "*
10344   {
10345     int num_saves = XVECLEN (operands[2], 0);
10346      
10347     /* For the StrongARM at least it is faster to
10348        use STR to store only a single register.
10349        In Thumb mode always use push, and the assmebler will pick
10350        something approporiate.  */
10351     if (num_saves == 1 && TARGET_ARM)
10352       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10353     else
10354       {
10355         int i;
10356         char pattern[100];
10357
10358         if (TARGET_ARM)
10359             strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10360         else
10361             strcpy (pattern, \"push\\t{%1\");
10362
10363         for (i = 1; i < num_saves; i++)
10364           {
10365             strcat (pattern, \", %|\");
10366             strcat (pattern,
10367                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10368           }
10369
10370         strcat (pattern, \"}\");
10371         output_asm_insn (pattern, operands);
10372       }
10373
10374     return \"\";
10375   }"
10376   [(set_attr "type" "store4")]
10377 )
10378
10379 (define_insn "stack_tie"
10380   [(set (mem:BLK (scratch))
10381         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10382                      (match_operand:SI 1 "s_register_operand" "r")]
10383                     UNSPEC_PRLG_STK))]
10384   ""
10385   ""
10386   [(set_attr "length" "0")]
10387 )
10388
10389 ;; Similarly for the floating point registers
10390 (define_insn "*push_fp_multi"
10391   [(match_parallel 2 "multi_register_push"
10392     [(set (match_operand:BLK 0 "memory_operand" "=m")
10393           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10394                       UNSPEC_PUSH_MULT))])]
10395   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
10396   "*
10397   {
10398     char pattern[100];
10399
10400     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10401     output_asm_insn (pattern, operands);
10402     return \"\";
10403   }"
10404   [(set_attr "type" "f_store")]
10405 )
10406
10407 ;; Special patterns for dealing with the constant pool
10408
10409 (define_insn "align_4"
10410   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10411   "TARGET_EITHER"
10412   "*
10413   assemble_align (32);
10414   return \"\";
10415   "
10416 )
10417
10418 (define_insn "align_8"
10419   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10420   "TARGET_EITHER"
10421   "*
10422   assemble_align (64);
10423   return \"\";
10424   "
10425 )
10426
10427 (define_insn "consttable_end"
10428   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10429   "TARGET_EITHER"
10430   "*
10431   making_const_table = FALSE;
10432   return \"\";
10433   "
10434 )
10435
10436 (define_insn "consttable_1"
10437   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10438   "TARGET_THUMB1"
10439   "*
10440   making_const_table = TRUE;
10441   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10442   assemble_zeros (3);
10443   return \"\";
10444   "
10445   [(set_attr "length" "4")]
10446 )
10447
10448 (define_insn "consttable_2"
10449   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10450   "TARGET_THUMB1"
10451   "*
10452   making_const_table = TRUE;
10453   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10454   assemble_zeros (2);
10455   return \"\";
10456   "
10457   [(set_attr "length" "4")]
10458 )
10459
10460 (define_insn "consttable_4"
10461   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10462   "TARGET_EITHER"
10463   "*
10464   {
10465     making_const_table = TRUE;
10466     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10467       {
10468       case MODE_FLOAT:
10469       {
10470         REAL_VALUE_TYPE r;
10471         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10472         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10473         break;
10474       }
10475       default:
10476         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10477         break;
10478       }
10479     return \"\";
10480   }"
10481   [(set_attr "length" "4")]
10482 )
10483
10484 (define_insn "consttable_8"
10485   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10486   "TARGET_EITHER"
10487   "*
10488   {
10489     making_const_table = TRUE;
10490     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10491       {
10492        case MODE_FLOAT:
10493         {
10494           REAL_VALUE_TYPE r;
10495           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10496           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10497           break;
10498         }
10499       default:
10500         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10501         break;
10502       }
10503     return \"\";
10504   }"
10505   [(set_attr "length" "8")]
10506 )
10507
10508 ;; Miscellaneous Thumb patterns
10509
10510 (define_expand "tablejump"
10511   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10512               (use (label_ref (match_operand 1 "" "")))])]
10513   "TARGET_THUMB1"
10514   "
10515   if (flag_pic)
10516     {
10517       /* Hopefully, CSE will eliminate this copy.  */
10518       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10519       rtx reg2 = gen_reg_rtx (SImode);
10520
10521       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10522       operands[0] = reg2;
10523     }
10524   "
10525 )
10526
10527 ;; NB never uses BX.
10528 (define_insn "*thumb1_tablejump"
10529   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10530    (use (label_ref (match_operand 1 "" "")))]
10531   "TARGET_THUMB1"
10532   "mov\\t%|pc, %0"
10533   [(set_attr "length" "2")]
10534 )
10535
10536 ;; V5 Instructions,
10537
10538 (define_insn "clzsi2"
10539   [(set (match_operand:SI 0 "s_register_operand" "=r")
10540         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10541   "TARGET_32BIT && arm_arch5"
10542   "clz%?\\t%0, %1"
10543   [(set_attr "predicable" "yes")])
10544
10545 (define_expand "ffssi2"
10546   [(set (match_operand:SI 0 "s_register_operand" "")
10547         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10548   "TARGET_32BIT && arm_arch5"
10549   "
10550   {
10551     rtx t1, t2, t3;
10552
10553     t1 = gen_reg_rtx (SImode);
10554     t2 = gen_reg_rtx (SImode);
10555     t3 = gen_reg_rtx (SImode);
10556
10557     emit_insn (gen_negsi2 (t1, operands[1]));
10558     emit_insn (gen_andsi3 (t2, operands[1], t1));
10559     emit_insn (gen_clzsi2 (t3, t2));
10560     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10561     DONE;
10562   }"
10563 )
10564
10565 (define_expand "ctzsi2"
10566   [(set (match_operand:SI 0 "s_register_operand" "")
10567         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10568   "TARGET_32BIT && arm_arch5"
10569   "
10570   {
10571     rtx t1, t2, t3;
10572
10573     t1 = gen_reg_rtx (SImode);
10574     t2 = gen_reg_rtx (SImode);
10575     t3 = gen_reg_rtx (SImode);
10576
10577     emit_insn (gen_negsi2 (t1, operands[1]));
10578     emit_insn (gen_andsi3 (t2, operands[1], t1));
10579     emit_insn (gen_clzsi2 (t3, t2));
10580     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10581     DONE;
10582   }"
10583 )
10584
10585 ;; V5E instructions.
10586
10587 (define_insn "prefetch"
10588   [(prefetch (match_operand:SI 0 "address_operand" "p")
10589              (match_operand:SI 1 "" "")
10590              (match_operand:SI 2 "" ""))]
10591   "TARGET_32BIT && arm_arch5e"
10592   "pld\\t%a0")
10593
10594 ;; General predication pattern
10595
10596 (define_cond_exec
10597   [(match_operator 0 "arm_comparison_operator"
10598     [(match_operand 1 "cc_register" "")
10599      (const_int 0)])]
10600   "TARGET_32BIT"
10601   ""
10602 )
10603
10604 (define_insn "prologue_use"
10605   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10606   ""
10607   "%@ %0 needed for prologue"
10608 )
10609
10610
10611 ;; Patterns for exception handling
10612
10613 (define_expand "eh_return"
10614   [(use (match_operand 0 "general_operand" ""))]
10615   "TARGET_EITHER"
10616   "
10617   {
10618     if (TARGET_32BIT)
10619       emit_insn (gen_arm_eh_return (operands[0]));
10620     else
10621       emit_insn (gen_thumb_eh_return (operands[0]));
10622     DONE;
10623   }"
10624 )
10625                                    
10626 ;; We can't expand this before we know where the link register is stored.
10627 (define_insn_and_split "arm_eh_return"
10628   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10629                     VUNSPEC_EH_RETURN)
10630    (clobber (match_scratch:SI 1 "=&r"))]
10631   "TARGET_ARM"
10632   "#"
10633   "&& reload_completed"
10634   [(const_int 0)]
10635   "
10636   {
10637     arm_set_return_address (operands[0], operands[1]);
10638     DONE;
10639   }"
10640 )
10641
10642 (define_insn_and_split "thumb_eh_return"
10643   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10644                     VUNSPEC_EH_RETURN)
10645    (clobber (match_scratch:SI 1 "=&l"))]
10646   "TARGET_THUMB1"
10647   "#"
10648   "&& reload_completed"
10649   [(const_int 0)]
10650   "
10651   {
10652     thumb_set_return_address (operands[0], operands[1]);
10653     DONE;
10654   }"
10655 )
10656
10657 \f
10658 ;; TLS support
10659
10660 (define_insn "load_tp_hard"
10661   [(set (match_operand:SI 0 "register_operand" "=r")
10662         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10663   "TARGET_HARD_TP"
10664   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10665   [(set_attr "predicable" "yes")]
10666 )
10667
10668 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
10669 (define_insn "load_tp_soft"
10670   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10671    (clobber (reg:SI LR_REGNUM))
10672    (clobber (reg:SI IP_REGNUM))
10673    (clobber (reg:CC CC_REGNUM))]
10674   "TARGET_SOFT_TP"
10675   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10676   [(set_attr "conds" "clob")]
10677 )
10678
10679 ;; Load the FPA co-processor patterns
10680 (include "fpa.md")
10681 ;; Load the Maverick co-processor patterns
10682 (include "cirrus.md")
10683 ;; Load the Intel Wireless Multimedia Extension patterns
10684 (include "iwmmxt.md")
10685 ;; Load the VFP co-processor patterns
10686 (include "vfp.md")
10687 ;; Thumb-2 patterns
10688 (include "thumb2.md")
10689